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>
Showing
6 changed files
with
294 additions
and
2 deletions
CHANGELOG.md
0 → 100644
CLAUDE.md
0 → 100644
| 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:-}'" | ... | ... |
12.7 KB
11.1 KB
task/2025-03-04.md
0 → 100644
| 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×tamp=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. ✅ 拆分函数后模板调用已更新 |
-
Please register or login to post a comment