hookehuyr

fix(deploy): 修复部署脚本在代理环境下SSH/SCP连接失败的问题

- 在 upload_server 函数中为 SSH/SCP 命令添加 unset http_proxy/https_proxy
- 添加代理处理说明注释,解释各步骤的代理使用策略
- 新增项目文档:CLAUDE.md、CHANGELOG.md
- 新增任务记录:task/2025-03-04.md
- 新增图片资源:三坛大戒相关图片

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 +# 变更日志
2 +
3 +记录项目开发过程中的重要变更和完成任务。
4 +
5 +## 2026-03-04
6 +
7 +### 13:44:02 - 完成任务
8 +
9 +**影响文件**:
10 +- `src/views/MastersDetail.vue`
11 +- `src/views/Splash.vue`
12 +
13 +**变更摘要**:
14 +- 无详细描述
1 +# CLAUDE.md
2 +
3 +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4 +
5 +## 项目概述
6 +
7 +这是一个基于 Vue 3 + Vite + Vant 4 的移动端 H5 项目(三坛大戒),用于展示佛教戒期相关信息。
8 +
9 +## 常用命令
10 +
11 +```bash
12 +# 开发(pnpm/npm/yarn)
13 +pnpm dev # 启动开发服务器(默认端口 5173)
14 +pnpm build # 构建生产版本
15 +pnpm lint # ESLint 检查并修复
16 +pnpm serve # 预览构建产物
17 +
18 +# 部署(依赖 qshell 和 ssh)
19 +pnpm deploy # 执行完整部署流程:构建 -> 七牛上传 -> 服务器打包上传
20 +bash scripts/deploy.sh # 直接执行部署脚本
21 +```
22 +
23 +## 项目架构
24 +
25 +### 全局 Loading 机制
26 +
27 +项目使用计数器方式管理全局加载状态,优化低网速体验:
28 +
29 +- **状态管理**`src/stores/loading.js` - 使用 `pending_count` 记录进行中的请求数
30 +- **拦截器集成**`src/utils/axios.js` - 请求开始 +1,响应成功 -1,错误时重置
31 +- **UI 展示**`src/App.vue` - 全屏蒙版 + van-loading 组件
32 +
33 +**特殊 API**:图片流媒体接口 `getImgStreamAPI` 配置了 `{ ignore_loading: true }`,不触发全局 loading。
34 +
35 +**路由级加载**`src/router/index.js` 中路由守卫也会控制 loading,避免懒加载白屏。
36 +
37 +### 登录态控制
38 +
39 +- **Token 存储**:使用 `js-cookie` 存储 `token-stdj`
40 +- **路由守卫**:除 `['/', '/jz_login']` 白名单外,所有页面需登录
41 +- **未登录处理**:重定向到 `/jz_login` 并携带 `redirect` 参数
42 +
43 +### API 层设计
44 +
45 +- **API 定义**`src/api/index.js` - 统一定义接口路径和 JSDoc
46 +- **请求封装**`src/api/fn.js` - 提供 `fn()` 处理响应、`fetch` 基于 axios
47 +- **默认参数**:所有请求自动携带 `f: 'stdj'``timestamp`(GET)
48 +
49 +**API 响应约定**
50 +```javascript
51 +// 成功响应格式(res.code === 1)
52 +{ code: 1, data: {...}, msg: 'success' }
53 +
54 +// 错误处理使用 showFailToast
55 +```
56 +
57 +### 目录结构
58 +
59 +```
60 +src/
61 +├── api/ # API 接口定义
62 +│ ├── index.js # 主接口(首页、文章、登录、用户信息)
63 +│ ├── fn.js # 请求封装与错误处理
64 +│ ├── common.js # 通用接口
65 +│ └── wx/ # 微信相关(支付、配置等)
66 +├── assets/ # 静态资源
67 +├── components/ # 通用组件(VideoPlayer、LoadingSpinner、EmptyState)
68 +├── router/ # Vue Router 配置(含登录守卫)
69 +├── stores/ # Pinia 状态管理(loading store)
70 +├── utils/ # 工具函数
71 +│ ├── axios.js # Axios 拦截器(接入 loading 计数)
72 +│ ├── request.js # Axios 实例导出
73 +│ ├── upload.js # 上传工具
74 +│ └── vconsole.js # 调试控制台
75 +├── views/ # 页面组件
76 +└── main.js # 入口文件
77 +```
78 +
79 +## 关键配置
80 +
81 +### 移动端适配
82 +
83 +- 使用 `postcss-px-to-viewport`,设计稿基准 **375px**
84 +- 选择器添加 `ignore-` 前缀可跳过转换
85 +
86 +### 路径别名
87 +
88 +```javascript
89 +@ src/
90 +@components src/components/
91 +@utils src/utils/
92 +@api src/api/
93 +@assets src/assets/
94 +@views src/views/
95 +@stores src/stores/
96 +```
97 +
98 +### 环境变量
99 +
100 +- `.env` - 默认配置
101 +- `.env.development` - 开发环境
102 +- `.env.production` - 生产环境
103 +
104 +**关键变量**
105 +- `VITE_BASE` - 资源公共路径
106 +- `VITE_PROXY_TARGET` - 代理目标服务器
107 +- `VITE_PROXY_PREFIX` - 代理前缀(默认 `/srv/`
108 +- `VITE_OUTDIR` - 构建输出目录(默认 `dist`
109 +
110 +### 自动导入
111 +
112 +- **Vue API**:通过 `unplugin-auto-import` 自动导入(见 `auto-imports.d.ts`
113 +- **Vant 组件**:通过 `unplugin-vue-components` 按需导入(见 `components.d.ts`
114 +
115 +## 部署说明
116 +
117 +部署脚本 `scripts/deploy.sh` 执行以下流程:
118 +
119 +1. **构建项目**`pnpm run build`
120 +2. **上传静态资源到七牛云**`qshell qupload ~/.qshell/stdj_upload.conf`
121 +3. **打包并上传到服务器**`scp -P 12101``zhsy@oa.jcedu.org:/home/www/f`
122 +
123 +**依赖**:本机需安装 `qshell` 并配置 `~/.qshell/stdj_upload.conf`
124 +
125 +## 开发注意事项
126 +
127 +1. **新增 API**:在 `src/api/index.js` 定义接口,使用 `fn(fetch.get/post())` 封装
128 +2. **跳过全局 Loading**:请求配置添加 `{ ignore_loading: true }`
129 +3. **路由配置**:新页面如需登录,无需添加白名单(默认需登录);公开页面添加到 `white_list`
130 +4. **组件命名**:文件名 kebab-case,组件名 PascalCase
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
2 # 2 #
3 # 部署脚本:构建项目 -> 上传七牛 -> 打包并上传到服务器 3 # 部署脚本:构建项目 -> 上传七牛 -> 打包并上传到服务器
4 # 说明:在 macOS 环境下执行,依赖 npm、qshell、ssh/scp 4 # 说明:在 macOS 环境下执行,依赖 npm、qshell、ssh/scp
5 +#
6 +# 代理处理说明:
7 +# - 构建和七牛上传:会使用系统的 http_proxy/https_proxy 环境变量
8 +# - SSH/SCP 连接:临时取消代理环境变量,直连服务器(避免代理干扰)
5 9
6 set -euo pipefail 10 set -euo pipefail
7 11
...@@ -129,13 +133,15 @@ upload_server() { ...@@ -129,13 +133,15 @@ upload_server() {
129 run_cmd "tar -czvpf '${local_tar:-}' '${local_package_dir:-}'" 133 run_cmd "tar -czvpf '${local_tar:-}' '${local_package_dir:-}'"
130 134
131 log_info "上传到服务器:${server_host:-}:${remote_dir:-}(端口 ${server_port:-})" 135 log_info "上传到服务器:${server_host:-}:${remote_dir:-}(端口 ${server_port:-})"
132 - run_cmd "scp -P '${server_port:-}' '${local_tar:-}' '${server_host:-}':'${remote_dir:-}'" 136 + # 注意:临时取消代理环境变量,避免 SSH/SCP 受代理影响
137 + run_cmd "unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY && scp -P '${server_port:-}' '${local_tar:-}' '${server_host:-}':'${remote_dir:-}'"
133 138
134 log_info "服务器解压:${remote_dir:-}/${local_tar:-}" 139 log_info "服务器解压:${remote_dir:-}/${local_tar:-}"
135 # 说明:构造远端命令,避免变量名意外字符导致的未绑定错误 140 # 说明:构造远端命令,避免变量名意外字符导致的未绑定错误
136 local remote_cmd 141 local remote_cmd
137 remote_cmd="cd \"${remote_dir:-}\" && tar -xzvf \"${local_tar:-}\" && rm -rf \"${local_tar:-}\"" 142 remote_cmd="cd \"${remote_dir:-}\" && tar -xzvf \"${local_tar:-}\" && rm -rf \"${local_tar:-}\""
138 - run_cmd "ssh -p '${server_port:-}' '${server_host:-}' \"$remote_cmd\"" 143 + # 注意:临时取消代理环境变量,避免 SSH 受代理影响
144 + run_cmd "unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY && ssh -p '${server_port:-}' '${server_host:-}' \"$remote_cmd\""
139 145
140 log_info "删除本地压缩包" 146 log_info "删除本地压缩包"
141 run_cmd "rm -f '${local_tar:-}'" 147 run_cmd "rm -f '${local_tar:-}'"
......
1 +# 2025-03-04 今日任务
2 +
3 +## 需求概述
4 +
5 +1. **法会流程跳转修改**:从跳转链接改成读取 `sn` 作为 id,跳转到新闻详情页
6 +2. **新增三坛大戒栏目**:接口需要新增字段返回
7 +3. **viewMore 函数拆分**:拆成 4 个独立的跳转函数
8 +
9 +---
10 +
11 +## ✅ 任务 1:法会流程跳转修改(已完成)
12 +
13 +### 修改内容
14 +- 移除了 `category_link` 判断逻辑
15 +- 使用 `item.parent_sn` 作为路由参数跳转到新闻详情页
16 +
17 +### 实现代码
18 +```javascript
19 +// src/views/Home.vue:472-475
20 +const viewMoreCeremony = (item) => {
21 + router.push({ name: 'NewsDetail', params: { id: item.parent_sn || item.id } })
22 +}
23 +```
24 +
25 +### 模板更新
26 +```html
27 +<!-- src/views/Home.vue:93 -->
28 +<div class="more-button" @click="viewMoreCeremony(currentStep)">
29 +```
30 +
31 +---
32 +
33 +## ✅ 任务 3:viewMore 函数拆分(已完成)
34 +
35 +### 实现内容
36 +`viewMore` 函数拆分为 4 个独立函数:
37 +1. `viewMoreCeremony` - 法会流程
38 +2. `viewMoreMasters` - 三师七证
39 +3. `viewMoreStudents` - 戒子
40 +4. `viewMoreVolunteers` - 义工
41 +5. `viewMoreByType` - 辅助分发函数(根据 item.name 分发)
42 +
43 +### 实现代码
44 +```javascript
45 +// 法会流程 - 使用 parent_sn 跳转到新闻详情页
46 +const viewMoreCeremony = (item) => {
47 + router.push({ name: 'NewsDetail', params: { id: item.parent_sn || item.id } })
48 +}
49 +
50 +// 三师七证
51 +const viewMoreMasters = (item) => {
52 + if (item?.category_link) {
53 + location.href = item?.category_link
54 + } else {
55 + router.push(`/masters?pid=${item.id}`)
56 + }
57 +}
58 +
59 +// 戒子
60 +const viewMoreStudents = (item) => {
61 + if (item?.category_link) {
62 + location.href = location.origin + location.pathname + '#/' + item?.category_link
63 + } else {
64 + router.push(`/students?i=${item.id}`)
65 + }
66 +}
67 +
68 +// 义工
69 +const viewMoreVolunteers = (item) => {
70 + if (item?.category_link) {
71 + location.href = location.origin + location.pathname + '#/' + item?.category_link
72 + } else {
73 + router.push(`/volunteers?i=${item.id}`)
74 + }
75 +}
76 +
77 +// 辅助函数:根据 item.name 分发到对应的处理函数
78 +const viewMoreByType = (item) => {
79 + const typeMap = {
80 + '三师七证': viewMoreMasters,
81 + '戒子': viewMoreStudents,
82 + '义工': viewMoreVolunteers,
83 + }
84 + const handler = typeMap[item.name]
85 + if (handler) {
86 + handler(item)
87 + } else {
88 + viewMoreMasters(item) // 默认行为
89 + }
90 +}
91 +```
92 +
93 +### 模板更新
94 +```html
95 +<!-- 法会流程:直接调用 viewMoreCeremony -->
96 +<div class="more-button" @click="viewMoreCeremony(currentStep)">
97 +
98 +<!-- 其他分类:使用 viewMoreByType 分发 -->
99 +<div class="vertical-more-btn" @click="viewMoreByType(item)">
100 +<div class="more-button" @click="viewMoreByType(item)">
101 +```
102 +
103 +---
104 +
105 +## ⏳ 任务 2:新增三坛大戒栏目(等待后端接口)
106 +
107 +### 当前接口数据结构
108 +```javascript
109 +// 接口返回:/srv/?a=home&f=stdj&timestamp=xxx
110 +{
111 + STDJSSQZ: [...], // 三师七证
112 + STDJFHLC: [...], // 法会流程
113 + STDJXGXW: [...], // 相关新闻
114 +}
115 +```
116 +
117 +### 需要新增
118 +- 新增字段 `STDJSTDJ`(三坛大戒)
119 +- 包含栏目信息和文章列表
120 +
121 +### 前端需要处理
122 +1. 更新 `src/api/index.js` 的 API 文档注释
123 +2. 添加新的数据展示区块(类似法会流程的展示方式)
124 +3. 添加对应的查看更多跳转函数
125 +
126 +### 依赖:后端接口开发
127 +
128 +---
129 +
130 +## 完成情况
131 +| 任务 | 状态 | 说明 |
132 +|------|------|------|
133 +| 任务 1 | ✅ 已完成 | 法会流程跳转逻辑修改 |
134 +| 任务 3 | ✅ 已完成 | viewMore 函数拆分(代码优化) |
135 +| 任务 2 | ⏳ 等待后端 | 依赖后端接口新增字段 |
136 +
137 +---
138 +
139 +## 注意事项
140 +1. ✅ 法会流程使用 `parent_sn` 作为路由参数
141 +2. ⏳ 新增三坛大戒栏目需要后端配合开发
142 +3. ✅ 拆分函数后模板调用已更新