hookehuyr

chore: 补充 Taro 小程序开发配置体系并格式化代码

- 新增全局规则:
  - taro-patterns.md(Taro 开发规范)
  - miniprogram-checklist.md(小程序检查清单)
  - taro-cross-platform.md(多端兼容指南)

- 新增项目配置:
  - .eslintrc.js(ESLint 规则)
  - .prettierrc(Prettier 格式化)
  - .lintstagedrc.js(Git 暂存检查)
  - .editorconfig(编辑器统一配置)
  - scripts/setup-husky.sh(Husky 自动安装)

- 新增文档:
  - docs/development-guide.md(完整开发指南)
  - docs/config-quick-reference.md(配置快速参考)

- 更新 package.json:
  - 添加代码质量相关命令(lint、format等)

- 使用 Prettier 格式化所有代码

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing 84 changed files with 2092 additions and 704 deletions
1 { 1 {
2 "permissions": { 2 "permissions": {
3 "allow": [ 3 "allow": [
4 - "Skill(glm-plan-usage:usage-query-skill)" 4 + "Skill(glm-plan-usage:usage-query-skill)",
5 + "Bash(pnpm add:*)",
6 + "Bash(chmod:*)",
7 + "Bash(bash:*)",
8 + "Bash(pnpm lint:no-fix:*)",
9 + "Bash(pnpm lint:*)",
10 + "Bash(pnpm list:*)",
11 + "Bash(pnpm format:*)",
12 + "Bash(git add:*)"
5 ] 13 ]
6 } 14 }
7 } 15 }
......
1 -# http://editorconfig.org 1 +# EditorConfig 配置
2 +# https://editorconfig.org
3 +
2 root = true 4 root = true
3 5
6 +# 所有文件
4 [*] 7 [*]
8 +charset = utf-8
5 indent_style = space 9 indent_style = space
6 indent_size = 2 10 indent_size = 2
7 -charset = utf-8 11 +end_of_line = lf
8 -trim_trailing_whitespace = true
9 insert_final_newline = true 12 insert_final_newline = true
13 +trim_trailing_whitespace = true
14 +
15 +# Vue 文件
16 +[*.{vue,js,jsx,ts,tsx}]
17 +indent_style = space
18 +indent_size = 2
19 +
20 +# Less/SCSS 文件
21 +[*.{less,scss,css}]
22 +indent_style = space
23 +indent_size = 2
10 24
25 +# JSON 文件
26 +[*.json]
27 +indent_style = space
28 +indent_size = 2
29 +
30 +# Markdown 文件
11 [*.md] 31 [*.md]
12 trim_trailing_whitespace = false 32 trim_trailing_whitespace = false
33 +indent_style = space
34 +indent_size = 2
35 +
36 +# 配置文件
37 +[*.{yml,yaml}]
38 +indent_style = space
39 +indent_size = 2
40 +
41 +# Shell 脚本
42 +[*.sh]
43 +end_of_line = lf
44 +
45 +# Windows 特定
46 +[*.{bat,cmd}]
47 +end_of_line = crlf
......
1 +module.exports = {
2 + root: true,
3 + env: {
4 + browser: true,
5 + node: true,
6 + es2021: true
7 + },
8 + extends: [
9 + 'eslint:recommended'
10 + // 暂时不使用 '@vue/eslint-config-prettier',手动配置规则避免冲突
11 + ],
12 + plugins: ['vue'],
13 + parser: 'vue-eslint-parser', // 使用 Vue parser
14 + parserOptions: {
15 + parser: 'espree', // JavaScript parser
16 + ecmaVersion: 2021,
17 + sourceType: 'module',
18 + ecmaFeatures: {
19 + jsx: true
20 + }
21 + },
22 + rules: {
23 + // Vue 规则(手动配置)
24 + 'vue/multi-word-component-names': 'off', // 允许单词组件名
25 + 'vue/no-v-html': 'warn', // 警告使用 v-html(XSS 风险)
26 + 'vue/require-default-prop': 'off', // 不强制 prop 默认值
27 + 'vue/require-prop-types': 'off', // 不强制 prop 类型(使用 JSDoc)
28 + 'vue/no-unused-vars': 'warn', // 警告未使用的变量
29 + 'vue/no-unused-components': 'warn', // 警告未使用的组件
30 +
31 + // 通用规则
32 + 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
33 + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
34 + 'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], // 警告未使用的变量
35 + 'prefer-const': 'error', // 优先使用 const
36 + 'no-var': 'error', // 禁止使用 var
37 + 'eqeqeq': ['error', 'always'], // 强制使用 === 和 !==
38 + 'curly': ['error', 'all'], // 强制使用大括号
39 + 'brace-style': ['error', '1tbs'], // 大括号风格
40 + 'quotes': ['error', 'single', { avoidEscape: true }], // 单引号
41 + 'semi': ['error', 'never'], // 不使用分号
42 + 'comma-dangle': ['error', 'never'], // 不允许尾随逗号
43 + 'arrow-parens': ['error', 'as-needed'], // 箭头函数参数括号
44 + 'object-curly-spacing': ['error', 'always'], // 对象大括号空格
45 + 'array-bracket-spacing': ['error', 'never'], // 数组方括号无空格
46 +
47 + // 代码质量
48 + 'no-duplicate-imports': 'error', // 禁止重复导入
49 + 'no-useless-return': 'error', // 禁止无用的 return
50 + 'no-else-return': 'error', // 禁止 else return(提前 return)
51 + 'prefer-template': 'error', // 优先使用模板字符串
52 + 'template-curly-spacing': 'error', // 模板字符串大括号内无空格
53 + 'object-shorthand': ['error', 'always'], // 对象属性简写
54 +
55 + // 放宽一些规则,避免过多警告
56 + 'no-prototype-builtins': 'off', // 允许使用原型方法
57 + 'no-nested-ternary': 'off', // 允许嵌套三元表达式
58 + 'no-param-reassign': 'off', // 允许修改参数
59 + 'consistent-return': 'off' // 不要求一致的 return
60 + },
61 + globals: {
62 + // Taro 全局变量
63 + wx: 'readonly',
64 + getCurrentPages: 'readonly',
65 + getApp: 'readonly',
66 +
67 + // NutUI 全局变量
68 + NutUI: 'readonly'
69 + },
70 + overrides: [
71 + // 测试文件规则
72 + {
73 + files: ['**/__tests__/**/*', '**/*.test.js', '**/*.spec.js'],
74 + env: {
75 + jest: true,
76 + node: true
77 + },
78 + rules: {
79 + 'no-console': 'off'
80 + }
81 + }
82 + ]
83 +}
1 +#!/bin/sh
2 +. "$(dirname "$0")/_/husky.sh"
3 +
4 +# 验证 commit 信息格式(可选)
5 +# commit_regex='^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\(.+\))?: .{1,50}'
6 +#
7 +#if ! grep -qE "$commit_regex" "$1"; then
8 +# echo "❌ Commit 信息格式不正确"
9 +# echo "✅ 正确格式: type(scope): subject"
10 +# echo "📝 类型: feat, fix, docs, style, refactor, test, chore, etc."
11 +# exit 1
12 +#fi
13 +
14 +echo "✅ Commit 信息验证通过"
1 +#!/bin/sh
2 +. "$(dirname "$0")/_/husky.sh"
3 +
4 +echo "🔍 运行代码检查..."
5 +pnpm lint-staged
1 +module.exports = {
2 + // Vue 文件
3 + '*.{vue,js,jsx,ts,tsx}': [
4 + 'eslint --fix',
5 + 'prettier --write'
6 + ],
7 +
8 + // 样式文件
9 + '*.{less,scss,css}': [
10 + 'prettier --write'
11 + ],
12 +
13 + // JSON/配置文件
14 + '*.{json,md,yml,yaml}': [
15 + 'prettier --write'
16 + ]
17 +}
1 +# 忽略构建输出
2 +dist/
3 +build/
4 +
5 +# 忽略依赖
6 +node_modules/
7 +
8 +# 忽略配置文件
9 +.prettierignore
10 +.eslintrc.js
11 +
12 +# 忽略锁文件
13 +package-lock.json
14 +pnpm-lock.yaml
15 +yarn.lock
16 +
17 +# 忽略日志
18 +*.log
19 +logs/
20 +
21 +# 忽略临时文件
22 +*.tmp
23 +.cache/
24 +
25 +# 忽略覆盖率报告
26 +coverage/
27 +
28 +# 忽略 Taro 配置
29 +config/prod.config.js
30 +config/dev.config.js
31 +config/index.js
32 +
33 +# 忽略静态资源
34 +src/assets/fonts/
35 +src/assets/images/
36 +
37 +# 忽略特定文件
38 +miniprogram_npm/
1 +{
2 + "semi": false,
3 + "singleQuote": true,
4 + "quoteProps": "as-needed",
5 + "trailingComma": "none",
6 + "bracketSpacing": true,
7 + "bracketSameLine": false,
8 + "arrowParens": "avoid",
9 + "printWidth": 100,
10 + "tabWidth": 2,
11 + "useTabs": false,
12 + "endOfLine": "lf",
13 + "vueIndentScriptAndStyle": false,
14 + "singleAttributePerLine": false,
15 + "overrides": [
16 + {
17 + "files": "*.vue",
18 + "options": {
19 + "parser": "vue"
20 + }
21 + },
22 + {
23 + "files": "*.less",
24 + "options": {
25 + "parser": "less"
26 + }
27 + }
28 + ]
29 +}
...@@ -23,12 +23,70 @@ ...@@ -23,12 +23,70 @@
23 ## 开发命令 23 ## 开发命令
24 24
25 ```bash 25 ```bash
26 +# 安装依赖
26 pnpm install 27 pnpm install
27 -pnpm dev:weapp 28 +
28 -pnpm build:weapp 29 +# 开发模式
29 -pnpm lint 30 +pnpm dev:weapp # 微信小程序
31 +pnpm dev:h5 # H5 端
32 +
33 +# 构建
34 +pnpm build:weapp # 微信小程序生产包
35 +pnpm build:h5 # H5 端生产包
36 +
37 +# 代码质量
38 +pnpm lint # ESLint 检查并修复
39 +pnpm format # Prettier 格式化
40 +pnpm lint:no-fix # 仅检查不修复
41 +```
42 +
43 +## 代码质量保障
44 +
45 +项目已配置完整的代码质量保障体系:
46 +
47 +### ✅ 已配置工具
48 +
49 +- **ESLint**:代码风格检查和潜在错误检测
50 +- **Prettier**:代码格式化统一
51 +- **EditorConfig**:编辑器配置统一
52 +- **Husky**:Git Hooks 自动化
53 +- **lint-staged**:提交前仅检查本次修改文件
54 +
55 +### 📋 初始配置步骤
56 +
57 +```bash
58 +# 1. 安装代码质量相关依赖
59 +pnpm add -D eslint prettier eslint-plugin-vue husky lint-staged
60 +
61 +# 2. 初始化 Husky(自动设置 Git Hooks)
62 +bash scripts/setup-husky.sh
63 +
64 +# 3. 提交代码时会自动运行检查
65 +git add .
66 +git commit -m "feat: 添加新功能"
30 ``` 67 ```
31 68
69 +### 📚 详细配置文档
70 +
71 +查看 `docs/development-guide.md` 获取完整的配置使用说明。
72 +
73 +### 🎯 Claude Code 开发配置
74 +
75 +项目配置了完善的 Claude Code 全局规则,支持:
76 +- Vue 3 最佳实践
77 +- Taro 开发规范
78 +- 小程序特性适配
79 +- 多端兼容处理
80 +- 代码审查清单
81 +
82 +全局规则位于 `~/.claude/rules/`
83 +- `taro-patterns.md` - Taro 开发规范
84 +- `miniprogram-checklist.md` - 小程序检查清单
85 +- `taro-cross-platform.md` - 多端兼容指南
86 +- `vue-patterns.md` - Vue 3 最佳实践
87 +- `frontend-testing.md` - 前端测试指南
88 +- `code-review.md` - 代码审查清单
89 +
32 ## 项目结构 90 ## 项目结构
33 91
34 ```text 92 ```text
......
1 +# 配置快速参考
2 +
3 +## 🚀 快速开始
4 +
5 +### 1. 安装依赖
6 +
7 +```bash
8 +# 安装项目依赖
9 +pnpm install
10 +
11 +# 安装代码质量工具(首次)
12 +pnpm add -D eslint prettier eslint-plugin-vue husky lint-staged @vue/eslint-config-prettier
13 +
14 +# 初始化 Git Hooks
15 +bash scripts/setup-husky.sh
16 +```
17 +
18 +### 2. 日常开发
19 +
20 +```bash
21 +# 启动开发服务器
22 +pnpm dev:weapp
23 +
24 +# 代码检查与格式化
25 +pnpm lint # ESLint 检查并修复
26 +pnpm format # Prettier 格式化
27 +
28 +# 提交代码(自动检查)
29 +git add .
30 +git commit -m "feat: 添加新功能"
31 +```
32 +
33 +## 📁 配置文件说明
34 +
35 +### 项目配置
36 +
37 +| 文件 | 用途 |
38 +|------|------|
39 +| `.eslintrc.js` | ESLint 规则配置 |
40 +| `.prettierrc` | Prettier 格式化配置 |
41 +| `.editorconfig` | 编辑器统一配置 |
42 +| `.lintstagedrc.js` | Git 暂存文件检查配置 |
43 +| `.husky/pre-commit` | Git 提交前钩子 |
44 +
45 +### 全局配置(`~/.claude/rules/`)
46 +
47 +| 文件 | 用途 |
48 +|------|------|
49 +| `taro-patterns.md` | Taro 开发规范 |
50 +| `miniprogram-checklist.md` | 小程序检查清单 |
51 +| `taro-cross-platform.md` | 多端兼容指南 |
52 +| `vue-patterns.md` | Vue 3 最佳实践 |
53 +| `frontend-testing.md` | 前端测试指南 |
54 +| `code-review.md` | 代码审查清单 |
55 +| `tailwindcss-guide.md` | TailwindCSS 使用规范 |
56 +| `frontend-performance.md` | 前端性能优化 |
57 +
58 +## 🎯 常用命令
59 +
60 +### 开发命令
61 +
62 +```bash
63 +pnpm dev:weapp # 微信小程序开发模式
64 +pnpm dev:h5 # H5 端开发模式
65 +pnpm build:weapp # 微信小程序构建
66 +pnpm build:h5 # H5 端构建
67 +```
68 +
69 +### 代码质量命令
70 +
71 +```bash
72 +pnpm lint # ESLint 检查并修复
73 +pnpm lint:no-fix # ESLint 仅检查
74 +pnpm format # Prettier 格式化
75 +pnpm format:check # Prettier 检查
76 +```
77 +
78 +### Git 命令
79 +
80 +```bash
81 +git add . # 添加所有文件
82 +git commit -m "feat: xxx" # 提交(自动运行检查)
83 +git commit --no-verify -m "xxx" # 跳过检查(不推荐)
84 +```
85 +
86 +## 📝 Commit 规范
87 +
88 +推荐使用 Conventional Commits 格式:
89 +
90 +```
91 +feat: 新功能
92 +fix: 修复 bug
93 +docs: 文档更新
94 +style: 代码格式
95 +refactor: 重构
96 +test: 测试相关
97 +chore: 构建过程或辅助工具
98 +```
99 +
100 +### 示例
101 +
102 +```bash
103 +git commit -m "feat(booking): 添加预约日期选择功能"
104 +git commit -m "fix(auth): 修复登录时 token 未持久化的问题"
105 +git commit -m "docs: 更新开发文档"
106 +```
107 +
108 +## ⚙️ VS Code 配置
109 +
110 +### 推荐插件
111 +
112 +```bash
113 +# 安装推荐插件
114 +code --install-extension dbaeumer.vscode-eslint
115 +code --install-extension esbenp.prettier-vscode
116 +code --install-extension EditorConfig.EditorConfig
117 +code --install-extension Vue.volar
118 +code --install-extension taro.vscode-tarojs
119 +```
120 +
121 +### 工作区配置
122 +
123 +创建 `.vscode/settings.json`
124 +
125 +```json
126 +{
127 + "editor.formatOnSave": false,
128 + "editor.codeActionsOnSave": {
129 + "source.fixAll.eslint": true
130 + },
131 + "[javascript]": {
132 + "editor.defaultFormatter": "esbenp.prettier-vscode"
133 + },
134 + "[vue]": {
135 + "editor.defaultFormatter": "esbenp.prettier-vscode"
136 + },
137 + "files.eol": "\n",
138 + "files.trimTrailingWhitespace": true
139 +}
140 +```
141 +
142 +## 🔍 常见问题
143 +
144 +### Q: Husky 钩子不生效?
145 +
146 +```bash
147 +# 重新初始化 Husky
148 +npx husky install
149 +npx husky add .husky/pre-commit "pnpm lint-staged"
150 +chmod +x .husky/pre-commit
151 +```
152 +
153 +### Q: ESLint 和 Prettier 冲突?
154 +
155 +```bash
156 +# 安装 @vue/eslint-config-prettier
157 +pnpm add -D @vue/eslint-config-prettier
158 +
159 +# 在 .eslintrc.js 的 extends 最后添加
160 +'@vue/eslint-config-prettier'
161 +```
162 +
163 +### Q: 想跳过检查临时提交?
164 +
165 +```bash
166 +# ⚠️ 不推荐,仅用于紧急情况
167 +git commit --no-verify -m "feat: 临时提交"
168 +```
169 +
170 +## 📋 代码审查清单
171 +
172 +提交代码前检查:
173 +
174 +- [ ] 代码已通过 `pnpm lint`
175 +- [ ] 代码已通过 `pnpm format`
176 +- [ ]`console.log``debugger`
177 +- [ ] 无注释掉的代码
178 +- [ ] 代码有必要的注释
179 +- [ ] 功能测试通过
180 +- [ ] 文档已更新(如需要)
181 +
182 +## 🎨 代码风格
183 +
184 +### Vue 组件
185 +
186 +```vue
187 +<script setup>
188 +// 1. 导入
189 +import { ref, computed } from 'vue'
190 +
191 +// 2. Props/Emits
192 +const props = defineProps({})
193 +const emit = defineEmits({})
194 +
195 +// 3. 响应式状态
196 +const count = ref(0)
197 +
198 +// 4. Computed
199 +const double = computed(() => count.value * 2)
200 +
201 +// 5. 方法
202 +const increment = () => { count.value++ }
203 +
204 +// 6. 生命周期
205 +onMounted(() => { init() })
206 +
207 +// 7. Watch
208 +watch(count, (val) => { track(val) })
209 +</script>
210 +```
211 +
212 +### 命名规范
213 +
214 +```javascript
215 +// 组件:PascalCase
216 +UserCard.vue
217 +BookingList.vue
218 +
219 +// 函数/变量:camelCase
220 +getUserInfo
221 +handleSubmit
222 +
223 +// 常量:UPPER_SNAKE_CASE
224 +API_BASE_URL
225 +MAX_RETRY_COUNT
226 +
227 +// 文件夹:kebab-case
228 +use-offline-booking.js
229 +auth-redirect.js
230 +```
231 +
232 +## 🔐 安全检查
233 +
234 +提交前确认:
235 +
236 +- [ ] 无硬编码密钥/Token
237 +- [ ] 用户输入已验证
238 +- [ ] API 错误信息不泄露敏感数据
239 +- [ ] XSS 防护(避免 `v-html` 或净化)
240 +- [ ] 敏感数据不存储在 localStorage
241 +
242 +## 🚀 性能检查
243 +
244 +部署前确认:
245 +
246 +- [ ] 主包体积 < 2MB
247 +- [ ] 单个分包 < 2MB
248 +- [ ] 首屏渲染 < 2s
249 +- [ ] 图片已优化(CDN 参数)
250 +- [ ] 长列表使用虚拟滚动
251 +- [ ] 路由懒加载已配置
252 +
253 +## 📚 参考资源
254 +
255 +- [完整开发指南](./development-guide.md)
256 +- [项目 CLAUDE.md](../CLAUDE.md)
257 +- [Taro 官方文档](https://docs.taro.zone/)
258 +- [Vue 3 官方文档](https://cn.vuejs.org/)
259 +- [NutUI 官方文档](https://nutui.jd.com/4/taro/)
260 +
261 +## 🎯 下一步
262 +
263 +1. ✅ 安装依赖并初始化 Husky
264 +2. ✅ 配置 VS Code
265 +3. ✅ 运行 `pnpm dev:weapp` 启动开发
266 +4. ✅ 开始编码,享受自动代码检查
267 +5. ✅ 查看全局配置了解最佳实践
268 +
269 +祝开发愉快!🎉
1 +# Taro 小程序开发配置指南
2 +
3 +## 配置概览
4 +
5 +项目已配置完整的代码质量保障体系:
6 +
7 +### ✅ 已创建的配置文件
8 +
9 +#### 1. ESLint 配置(`.eslintrc.js`)
10 +- Vue 3 推荐规则
11 +- Taro 小程序适配规则
12 +- 代码风格检查
13 +- 潜在错误检测
14 +
15 +#### 2. Prettier 配置(`.prettierrc`)
16 +- 代码格式化规则
17 +- 统一代码风格
18 +- 与 ESLint 无冲突集成
19 +
20 +#### 3. EditorConfig 配置(`.editorconfig`)
21 +- 编辑器统一配置
22 +- 缩进、换行符等
23 +
24 +#### 4. lint-staged 配置(`.lintstagedrc.js`)
25 +- Git 暂存文件检查
26 +- 仅检查本次修改的文件
27 +
28 +#### 5. Husky 配置(`scripts/setup-husky.sh`)
29 +- Git Hooks 自动化
30 +- 提交前自动检查
31 +
32 +## 快速开始
33 +
34 +### 步骤 1:安装依赖
35 +
36 +```bash
37 +# 安装 ESLint 相关依赖
38 +pnpm add -D eslint prettier eslint-plugin-vue @vue/eslint-config-prettier
39 +
40 +# 安装 Husky 和 lint-staged
41 +pnpm add -D husky lint-staged
42 +```
43 +
44 +### 步骤 2:初始化 Husky
45 +
46 +```bash
47 +# 方式 1:使用自动安装脚本
48 +bash scripts/setup-husky.sh
49 +
50 +# 方式 2:手动安装
51 +npx husky install
52 +npx husky add .husky/pre-commit "pnpm lint-staged"
53 +npx husky add .husky/commit-msg "npx commitlint --edit \$1"
54 +```
55 +
56 +### 步骤 3:更新 package.json
57 +
58 +`package.json``scripts` 中添加:
59 +
60 +```json
61 +{
62 + "scripts": {
63 + "dev:weapp": "npm run build:weapp -- --watch",
64 + "build:weapp": "taro build --type weapp",
65 + "lint": "eslint \"src/**/*.{js,jsx,vue,ts,tsx}\" --fix",
66 + "lint:no-fix": "eslint \"src/**/*.{js,jsx,vue,ts,tsx}\"",
67 + "format": "prettier --write \"src/**/*.{js,jsx,vue,ts,tsx,less,css,json,md}\"",
68 + "format:check": "prettier --check \"src/**/*.{js,jsx,vue,ts,tsx,less,css,json,md}\"",
69 + "prepare": "husky install"
70 + }
71 +}
72 +```
73 +
74 +## 使用说明
75 +
76 +### 日常开发
77 +
78 +#### 1. 开发前检查
79 +
80 +```bash
81 +# 启动开发服务器
82 +pnpm dev:weapp
83 +
84 +# 代码会自动检查,但有错误时不会阻止编译
85 +```
86 +
87 +#### 2. 提交代码
88 +
89 +```bash
90 +# 添加文件到暂存区
91 +git add .
92 +
93 +# 提交代码(会自动运行 lint-staged)
94 +git commit -m "feat: 添加新功能"
95 +
96 +# 如果检查失败,修复后再次提交
97 +git add .
98 +git commit -m "feat: 添加新功能"
99 +```
100 +
101 +#### 3. 手动检查代码
102 +
103 +```bash
104 +# 检查并自动修复
105 +pnpm lint
106 +
107 +# 仅检查不修复
108 +pnpm lint:no-fix
109 +
110 +# 格式化代码
111 +pnpm format
112 +
113 +# 检查代码格式
114 +pnpm format:check
115 +```
116 +
117 +### 跳过检查(不推荐)
118 +
119 +```bash
120 +# 跳过 lint-staged 检查
121 +git commit --no-verify -m "feat: 临时提交"
122 +
123 +# ⚠️ 注意:仅用于紧急情况,平时不要使用
124 +```
125 +
126 +## 编辑器集成
127 +
128 +### VS Code
129 +
130 +#### 1. 安装插件
131 +
132 +推荐安装以下 VS Code 插件:
133 +
134 +```json
135 +{
136 + "recommendations": [
137 + "dbaeumer.vscode-eslint", // ESLint
138 + "esbenp.prettier-vscode", // Prettier
139 + "EditorConfig.EditorConfig", // EditorConfig
140 + "Vue.volar", // Vue 语言支持
141 + "taro.vscode-tarojs" // Taro 开发工具
142 + ]
143 +}
144 +```
145 +
146 +#### 2. 配置 VS Code
147 +
148 +创建 `.vscode/settings.json`
149 +
150 +```json
151 +{
152 + // ESLint
153 + "editor.formatOnSave": false,
154 + "editor.codeActionsOnSave": {
155 + "source.fixAll.eslint": true
156 + },
157 +
158 + // Prettier
159 + "[javascript]": {
160 + "editor.defaultFormatter": "esbenp.prettier-vscode"
161 + },
162 + "[vue]": {
163 + "editor.defaultFormatter": "esbenp.prettier-vscode"
164 + },
165 + "[json]": {
166 + "editor.defaultFormatter": "esbenp.prettier-vscode"
167 + },
168 +
169 + // Vue
170 + "volar.autoCompleteRefs": true,
171 + "volar.codeLens.pugTools": false,
172 + "volar.completion.autoImportComponent": true,
173 +
174 + // 文件
175 + "files.eol": "\n",
176 + "files.trimTrailingWhitespace": true,
177 + "files.insertFinalNewline": true
178 +}
179 +```
180 +
181 +#### 3. 配置 VS Code 任务
182 +
183 +创建 `.vscode/tasks.json`
184 +
185 +```json
186 +{
187 + "version": "2.0.0",
188 + "tasks": [
189 + {
190 + "label": "Lint: 检查并修复",
191 + "type": "npm",
192 + "script": "lint",
193 + "problemMatcher": []
194 + },
195 + {
196 + "label": "Format: 格式化代码",
197 + "type": "npm",
198 + "script": "format",
199 + "problemMatcher": []
200 + },
201 + {
202 + "label": "Dev: 启动微信小程序",
203 + "type": "npm",
204 + "script": "dev:weapp",
205 + "problemMatcher": []
206 + }
207 + ]
208 +}
209 +```
210 +
211 +### WebStorm / IntelliJ IDEA
212 +
213 +1. **启用 ESLint**
214 + - Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint
215 + - 选择 "Automatic ESLint configuration"
216 + - 勾选 "Run eslint --fix on save"
217 +
218 +2. **启用 Prettier**
219 + - Settings → Languages & Frameworks → JavaScript → Prettier
220 + - 选择 "Run on save for files"
221 + - 勾选 "On code reformat"
222 +
223 +3. **启用 EditorConfig**
224 + - Settings → Editor → Code Style → EditorConfig
225 + - 勾选 "Enable EditorConfig support"
226 +
227 +## 配置详解
228 +
229 +### ESLint 规则说明
230 +
231 +#### Vue 相关规则
232 +
233 +```javascript
234 +'vue/multi-word-component-names': 'off', // 允许单词组件名(如 Home.vue)
235 +'vue/no-v-html': 'warn', // 警告使用 v-html(XSS 风险)
236 +'vue/require-default-prop': 'off', // 不强制 prop 默认值
237 +'vue/no-unused-vars': 'warn', // 警告未使用的变量
238 +```
239 +
240 +#### 通用规则
241 +
242 +```javascript
243 +'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境警告 console
244 +'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', // 生产环境禁止 debugger
245 +'prefer-const': 'error', // 优先使用 const
246 +'no-var': 'error', // 禁止使用 var
247 +'eqeqeq': ['error', 'always'], // 强制使用 ===
248 +'semi': ['error', 'never'], // 不使用分号
249 +'quotes': ['error', 'single'], // 使用单引号
250 +```
251 +
252 +### Prettier 规则说明
253 +
254 +```json
255 +{
256 + "semi": false, // 不使用分号
257 + "singleQuote": true, // 使用单引号
258 + "trailingComma": "none", // 不使用尾随逗号
259 + "printWidth": 100, // 每行最大 100 字符
260 + "tabWidth": 2, // 缩进 2 空格
261 + "endOfLine": "lf" // 使用 LF 换行符
262 +}
263 +```
264 +
265 +## 常见问题
266 +
267 +### Q1: Husky 钩子不生效
268 +
269 +**问题**:提交代码时没有自动运行检查
270 +
271 +**解决方案**
272 +
273 +```bash
274 +# 1. 检查 Husky 是否安装
275 +ls -la .husky/
276 +
277 +# 2. 重新安装 Husky
278 +pnpm add -D husky
279 +npx husky install
280 +
281 +# 3. 添加 pre-commit 钩子
282 +npx husky add .husky/pre-commit "pnpm lint-staged"
283 +
284 +# 4. 检查钩子文件
285 +cat .husky/pre-commit
286 +```
287 +
288 +### Q2: ESLint 和 Prettier 冲突
289 +
290 +**问题**:ESLint 和 Prettier 对同一处代码有不同规则
291 +
292 +**解决方案**
293 +
294 +```bash
295 +# 安装 @vue/eslint-config-prettier
296 +pnpm add -D @vue/eslint-config-prettier
297 +
298 +# 在 .eslintrc.js 中添加
299 +{
300 + "extends": [
301 + 'plugin:vue/vue3-recommended',
302 + '@vue/eslint-config-prettier' // 放在最后
303 + ]
304 +}
305 +```
306 +
307 +### Q3: lint-staged 检查所有文件
308 +
309 +**问题**:每次提交都检查所有文件,很慢
310 +
311 +**解决方案**
312 +
313 +```bash
314 +# 确保 lint-staged 配置正确
315 +cat .lintstagedrc.js
316 +
317 +# 应该配置为:
318 +{
319 + "*.{js,jsx,vue}": ["eslint --fix", "prettier --write"]
320 +}
321 +```
322 +
323 +### Q4: 提交被阻止,但不想修复
324 +
325 +**问题**:代码有问题但想临时提交
326 +
327 +**解决方案**
328 +
329 +```bash
330 +# ⚠️ 不推荐,仅用于紧急情况
331 +git commit --no-verify -m "feat: 临时提交"
332 +```
333 +
334 +### Q5: Taro API 报 ESLint 错误
335 +
336 +**问题**:使用了 `wx` 全局变量报错
337 +
338 +**解决方案**
339 +
340 +```javascript
341 +// .eslintrc.js 中已配置
342 +globals: {
343 + wx: 'readonly',
344 + getCurrentPages: 'readonly',
345 + getApp: 'readonly'
346 +}
347 +```
348 +
349 +## 最佳实践
350 +
351 +### 1. 提交前自检
352 +
353 +```bash
354 +# 1. 拉取最新代码
355 +git pull origin develop
356 +
357 +# 2. 运行检查
358 +pnpm lint
359 +pnpm format:check
360 +
361 +# 3. 运行测试(如果有)
362 +pnpm test
363 +
364 +# 4. 提交代码
365 +git add .
366 +git commit -m "feat: 添加新功能"
367 +```
368 +
369 +### 2. Commit 信息规范
370 +
371 +推荐使用 Conventional Commits 格式:
372 +
373 +```
374 +feat: 新功能
375 +fix: 修复 bug
376 +docs: 文档更新
377 +style: 代码格式(不影响代码运行的变动)
378 +refactor: 重构(既不是新增功能,也不是修改 bug 的代码变动)
379 +test: 测试相关
380 +chore: 构建过程或辅助工具的变动
381 +```
382 +
383 +示例:
384 +
385 +```bash
386 +git commit -m "feat(booking): 添加预约日期选择功能"
387 +git commit -m "fix(auth): 修复登录时 token 未持久化的问题"
388 +git commit -m "docs: 更新开发文档"
389 +```
390 +
391 +### 3. 代码审查清单
392 +
393 +在提交 PR 前检查:
394 +
395 +- [ ] 代码已通过 ESLint 检查
396 +- [ ] 代码已通过 Prettier 格式化
397 +- [ ]`console.log``debugger`
398 +- [ ] 无注释掉的代码
399 +- [ ] 代码有必要的注释
400 +- [ ] 测试已通过(如果有)
401 +- [ ] 文档已更新(如需要)
402 +
403 +## 团队协作
404 +
405 +### 统一开发环境
406 +
407 +确保团队成员使用相同的配置:
408 +
409 +```bash
410 +# 1. 克隆项目
411 +git clone <repo-url>
412 +
413 +# 2. 安装依赖
414 +pnpm install
415 +
416 +# 3. 初始化 Husky
417 +pnpm prepare
418 +
419 +# 4. 安装 VS Code 插件
420 +code --install-extension dbaeumer.vscode-eslint
421 +code --install-extension esbenp.prettier-vscode
422 +code --install-extension Vue.volar
423 +```
424 +
425 +### 代码审查流程
426 +
427 +1. **开发者**:提交代码前运行 `pnpm lint`
428 +2. **Husky**:自动运行 `lint-staged`
429 +3. **CI/CD**:运行完整的 `pnpm lint``pnpm test`
430 +4. **审查者**:检查代码质量和规范
431 +5. **合并**:通过所有检查后合并
432 +
433 +## 持续改进
434 +
435 +### 定期更新依赖
436 +
437 +```bash
438 +# 检查过时的依赖
439 +pnpm outdated
440 +
441 +# 更新依赖
442 +pnpm update
443 +
444 +# 更新主要版本
445 +pnpm upgrade --latest
446 +```
447 +
448 +### 自定义规则
449 +
450 +根据团队需求调整规则:
451 +
452 +```javascript
453 +// .eslintrc.js
454 +rules: {
455 + // 添加团队特定规则
456 + 'custom-rule-name': 'error'
457 +}
458 +```
459 +
460 +## 参考资源
461 +
462 +- [ESlint 官方文档](https://eslint.org/)
463 +- [Prettier 官方文档](https://prettier.io/)
464 +- [EditorConfig 官方文档](https://editorconfig.org/)
465 +- [Husky 官方文档](https://typicode.github.io/husky/)
466 +- [lint-staged 官方文档](https://github.com/okonet/lint-staged)
467 +- [Vue ESLint 官方插件](https://eslint.vuejs.org/)
468 +- [Conventional Commits](https://www.conventionalcommits.org/)
...@@ -27,7 +27,11 @@ ...@@ -27,7 +27,11 @@
27 "dev:qq": "NODE_ENV=development taro build --type qq --watch", 27 "dev:qq": "NODE_ENV=development taro build --type qq --watch",
28 "dev:quickapp": "NODE_ENV=development taro build --type quickapp --watch", 28 "dev:quickapp": "NODE_ENV=development taro build --type quickapp --watch",
29 "postinstall": "weapp-tw patch", 29 "postinstall": "weapp-tw patch",
30 - "lint": "eslint --ext .js,.vue src" 30 + "lint": "eslint \"src/**/*.{js,jsx,vue}\" --fix",
31 + "lint:no-fix": "eslint \"src/**/*.{js,jsx,vue}\"",
32 + "format": "prettier --write \"src/**/*.{js,jsx,vue,less,css,json,md}\"",
33 + "format:check": "prettier --check \"src/**/*.{js,jsx,vue,less,css,json,md}\"",
34 + "prepare": "husky install"
31 }, 35 },
32 "browserslist": [ 36 "browserslist": [
33 "last 3 versions", 37 "last 3 versions",
...@@ -72,17 +76,23 @@ ...@@ -72,17 +76,23 @@
72 "@types/webpack-env": "^1.13.6", 76 "@types/webpack-env": "^1.13.6",
73 "@vue/babel-plugin-jsx": "^1.0.6", 77 "@vue/babel-plugin-jsx": "^1.0.6",
74 "@vue/compiler-sfc": "^3.0.0", 78 "@vue/compiler-sfc": "^3.0.0",
79 + "@vue/eslint-config-prettier": "^10.2.0",
75 "autoprefixer": "^10.4.21", 80 "autoprefixer": "^10.4.21",
76 "babel-preset-taro": "4.1.9", 81 "babel-preset-taro": "4.1.9",
77 "css-loader": "3.4.2", 82 "css-loader": "3.4.2",
78 "eslint": "^8.12.0", 83 "eslint": "^8.12.0",
79 "eslint-config-taro": "4.1.9", 84 "eslint-config-taro": "4.1.9",
85 + "eslint-plugin-vue": "^10.7.0",
86 + "husky": "^9.1.7",
80 "less": "^4.2.0", 87 "less": "^4.2.0",
88 + "lint-staged": "^16.2.7",
81 "postcss": "^8.5.6", 89 "postcss": "^8.5.6",
90 + "prettier": "^3.8.1",
82 "sass": "^1.78.0", 91 "sass": "^1.78.0",
83 "style-loader": "1.3.0", 92 "style-loader": "1.3.0",
84 "tailwindcss": "^3.4.0", 93 "tailwindcss": "^3.4.0",
85 "unplugin-vue-components": "^0.26.0", 94 "unplugin-vue-components": "^0.26.0",
95 + "vue-eslint-parser": "^10.2.0",
86 "vue-loader": "^17.0.0", 96 "vue-loader": "^17.0.0",
87 "weapp-tailwindcss": "^4.1.10", 97 "weapp-tailwindcss": "^4.1.10",
88 "webpack": "5.91.0" 98 "webpack": "5.91.0"
......
This diff is collapsed. Click to expand it.
1 +#!/bin/bash
2 +
3 +# Husky 初始化脚本
4 +# 使用方法: bash scripts/setup-husky.sh
5 +
6 +set -e
7 +
8 +echo "🔧 开始设置 Husky Git Hooks..."
9 +
10 +# 检查是否在项目根目录
11 +if [ ! -f "package.json" ]; then
12 + echo "❌ 错误:请在项目根目录运行此脚本"
13 + exit 1
14 +fi
15 +
16 +# 安装依赖(如果未安装)
17 +echo "📦 安装依赖..."
18 +pnpm add -D husky lint-staged prettier || {
19 + echo "❌ 依赖安装失败"
20 + exit 1
21 +}
22 +
23 +# 初始化 Husky
24 +echo "🪝 初始化 Husky..."
25 +npx husky install || {
26 + echo "❌ Husky 初始化失败"
27 + exit 1
28 +}
29 +
30 +# 创建 pre-commit 钩子
31 +echo "📝 创建 pre-commit 钩子..."
32 +cat > .husky/pre-commit << 'EOF'
33 +#!/bin/sh
34 +. "$(dirname "$0")/_/husky.sh"
35 +
36 +echo "🔍 运行代码检查..."
37 +pnpm lint-staged
38 +EOF
39 +
40 +# 添加执行权限
41 +chmod +x .husky/pre-commit
42 +
43 +# 创建 commit-msg 钩子(可选,用于验证 commit 信息)
44 +cat > .husky/commit-msg << 'EOF'
45 +#!/bin/sh
46 +. "$(dirname "$0")/_/husky.sh"
47 +
48 +# 验证 commit 信息格式(可选)
49 +# commit_regex='^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\(.+\))?: .{1,50}'
50 +#
51 +#if ! grep -qE "$commit_regex" "$1"; then
52 +# echo "❌ Commit 信息格式不正确"
53 +# echo "✅ 正确格式: type(scope): subject"
54 +# echo "📝 类型: feat, fix, docs, style, refactor, test, chore, etc."
55 +# exit 1
56 +#fi
57 +
58 +echo "✅ Commit 信息验证通过"
59 +EOF
60 +
61 +chmod +x .husky/commit-msg
62 +
63 +# 更新 package.json scripts
64 +echo "📦 更新 package.json scripts..."
65 +if command -v jq > /dev/null 2>&1; then
66 + # 如果系统有 jq,使用它更新 package.json
67 + jq '.scripts.prepare = "husky install"' package.json > package.json.tmp && mv package.json.tmp package.json
68 +else
69 + echo "⚠️ 请手动在 package.json 的 scripts 中添加: \"prepare\": \"husky install\""
70 +fi
71 +
72 +echo "✅ Git Hooks 设置完成!"
73 +echo ""
74 +echo "📝 使用说明:"
75 +echo " - 每次 commit 前会自动运行 ESLint 和 Prettier"
76 +echo " - 如果检查失败,commit 将被中止"
77 +echo " - 使用 'git commit --no-verify' 跳过检查(不推荐)"
78 +echo ""
79 +echo "🎯 现在可以开始开发了!"
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
5 * @FilePath: /tswj/src/api/common.js 5 * @FilePath: /tswj/src/api/common.js
6 * @Description: 通用接口 6 * @Description: 通用接口
7 */ 7 */
8 -import { fn, fetch, uploadFn } from '@/api/fn'; 8 +import { fn, fetch, uploadFn } from '@/api/fn'
9 9
10 const Api = { 10 const Api = {
11 SMS: '/srv/?a=sms', 11 SMS: '/srv/?a=sms',
12 TOKEN: '/srv/?a=upload', 12 TOKEN: '/srv/?a=upload',
13 - SAVE_FILE: '/srv/?a=upload&t=save_file', 13 + SAVE_FILE: '/srv/?a=upload&t=save_file'
14 } 14 }
15 15
16 /** 16 /**
...@@ -19,7 +19,7 @@ const Api = { ...@@ -19,7 +19,7 @@ const Api = {
19 * @param {string} params.phone 手机号 19 * @param {string} params.phone 手机号
20 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 20 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
21 */ 21 */
22 -export const smsAPI = (params) => fn(fetch.post(Api.SMS, params)); 22 +export const smsAPI = params => fn(fetch.post(Api.SMS, params))
23 23
24 /** 24 /**
25 * @description: 获取七牛token 25 * @description: 获取七牛token
...@@ -28,7 +28,7 @@ export const smsAPI = (params) => fn(fetch.post(Api.SMS, params)); ...@@ -28,7 +28,7 @@ export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));
28 * @param {string} params.file 图片 base64 28 * @param {string} params.file 图片 base64
29 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回(data 为上传 token 等信息) 29 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回(data 为上传 token 等信息)
30 */ 30 */
31 -export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params)); 31 +export const qiniuTokenAPI = params => fn(fetch.stringifyPost(Api.TOKEN, params))
32 32
33 /** 33 /**
34 * @description: 上传七牛 34 * @description: 上传七牛
...@@ -37,7 +37,7 @@ export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, param ...@@ -37,7 +37,7 @@ export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, param
37 * @param {Object} config axios 配置 37 * @param {Object} config axios 配置
38 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false 38 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false
39 */ 39 */
40 -export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config)); 40 +export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config))
41 41
42 /** 42 /**
43 * @description: 保存图片 43 * @description: 保存图片
...@@ -49,4 +49,4 @@ export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url ...@@ -49,4 +49,4 @@ export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url
49 * @param {string} params.filekey 文件 key 49 * @param {string} params.filekey 文件 key
50 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 50 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
51 */ 51 */
52 -export const saveFileAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_FILE, params)); 52 +export const saveFileAPI = params => fn(fetch.stringifyPost(Api.SAVE_FILE, params))
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 * @FilePath: /xyxBooking-weapp/src/api/fn.js 5 * @FilePath: /xyxBooking-weapp/src/api/fn.js
6 * @Description: 统一后端返回格式(强制 { code, data, msg }) 6 * @Description: 统一后端返回格式(强制 { code, data, msg })
7 */ 7 */
8 -import axios from '@/utils/request'; 8 +import axios from '@/utils/request'
9 import Taro from '@tarojs/taro' 9 import Taro from '@tarojs/taro'
10 import qs from 'qs' 10 import qs from 'qs'
11 11
...@@ -16,7 +16,7 @@ import qs from 'qs' ...@@ -16,7 +16,7 @@ import qs from 'qs'
16 * @param {Promise<any>} api axios 请求 Promise 16 * @param {Promise<any>} api axios 请求 Promise
17 * @returns {Promise<{code:number,data:any,msg:string,show?:boolean}>} 标准化后的返回对象 17 * @returns {Promise<{code:number,data:any,msg:string,show?:boolean}>} 标准化后的返回对象
18 */ 18 */
19 -export const fn = (api) => { 19 +export const fn = api => {
20 return api 20 return api
21 .then(res => { 21 .then(res => {
22 // 约定:后端 code === 1 为成功 22 // 约定:后端 code === 1 为成功
...@@ -26,19 +26,29 @@ export const fn = (api) => { ...@@ -26,19 +26,29 @@ export const fn = (api) => {
26 } 26 }
27 // 失败兜底:优先返回后端响应,同时做 toast 提示 27 // 失败兜底:优先返回后端响应,同时做 toast 提示
28 console.warn('接口请求失败:', res) 28 console.warn('接口请求失败:', res)
29 - if (res_data && res_data.show === false) return res_data 29 + if (res_data && res_data.show === false) {
30 + return res_data
31 + }
30 Taro.showToast({ 32 Taro.showToast({
31 - title: (res_data && res_data.msg) ? res_data.msg : '请求失败', 33 + title: res_data && res_data.msg ? res_data.msg : '请求失败',
32 icon: 'none', 34 icon: 'none',
33 duration: 2000 35 duration: 2000
34 }) 36 })
35 return res_data || { code: 0, data: null, msg: '请求失败' } 37 return res_data || { code: 0, data: null, msg: '请求失败' }
36 }) 38 })
37 .catch(err => { 39 .catch(err => {
38 - console.error('接口请求异常:', err); 40 + console.error('接口请求异常:', err)
39 - return { code: 0, data: null, msg: (err && (err.msg || err.message || err.errMsg)) ? (err.msg || err.message || err.errMsg) : '网络异常' } 41 + return {
42 + code: 0,
43 + data: null,
44 + msg:
45 + err && (err.msg || err.message || err.errMsg)
46 + ? err.msg || err.message || err.errMsg
47 + : '网络异常'
48 + }
40 }) 49 })
41 - .finally(() => { // 最终执行 50 + .finally(() => {
51 + // 最终执行
42 }) 52 })
43 } 53 }
44 54
...@@ -47,25 +57,26 @@ export const fn = (api) => { ...@@ -47,25 +57,26 @@ export const fn = (api) => {
47 * @param {Promise<any>} api axios 请求 Promise 57 * @param {Promise<any>} api axios 请求 Promise
48 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false 58 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false
49 */ 59 */
50 -export const uploadFn = (api) => { 60 +export const uploadFn = api => {
51 return api 61 return api
52 .then(res => { 62 .then(res => {
53 if (res.statusText === 'OK') { 63 if (res.statusText === 'OK') {
54 - return res.data || true; 64 + return res.data || true
55 - } else { 65 + }
56 - console.warn('七牛上传失败:', res); 66 + console.warn('七牛上传失败:', res)
57 - if (!res.data.show) return false; 67 + if (!res.data.show) {
68 + return false
69 + }
58 Taro.showToast({ 70 Taro.showToast({
59 title: res.data.msg, 71 title: res.data.msg,
60 icon: 'none', 72 icon: 'none',
61 duration: 2000 73 duration: 2000
62 - }); 74 + })
63 - return false; 75 + return false
64 - }
65 }) 76 })
66 .catch(err => { 77 .catch(err => {
67 - console.error('七牛上传异常:', err); 78 + console.error('七牛上传异常:', err)
68 - return false; 79 + return false
69 }) 80 })
70 } 81 }
71 82
...@@ -82,7 +93,7 @@ export const fetch = { ...@@ -82,7 +93,7 @@ export const fetch = {
82 * @param {Object} params 查询参数 93 * @param {Object} params 查询参数
83 * @returns {Promise<any>} axios Promise 94 * @returns {Promise<any>} axios Promise
84 */ 95 */
85 - get: function (api, params) { 96 + get(api, params) {
86 return axios.get(api, params) 97 return axios.get(api, params)
87 }, 98 },
88 /** 99 /**
...@@ -91,7 +102,7 @@ export const fetch = { ...@@ -91,7 +102,7 @@ export const fetch = {
91 * @param {Object} params 请求体 102 * @param {Object} params 请求体
92 * @returns {Promise<any>} axios Promise 103 * @returns {Promise<any>} axios Promise
93 */ 104 */
94 - post: function (api, params) { 105 + post(api, params) {
95 return axios.post(api, params) 106 return axios.post(api, params)
96 }, 107 },
97 /** 108 /**
...@@ -100,7 +111,7 @@ export const fetch = { ...@@ -100,7 +111,7 @@ export const fetch = {
100 * @param {Object} params 请求体 111 * @param {Object} params 请求体
101 * @returns {Promise<any>} axios Promise 112 * @returns {Promise<any>} axios Promise
102 */ 113 */
103 - stringifyPost: function (api, params) { 114 + stringifyPost(api, params) {
104 return axios.post(api, qs.stringify(params), { 115 return axios.post(api, qs.stringify(params), {
105 headers: { 116 headers: {
106 'content-type': 'application/x-www-form-urlencoded' 117 'content-type': 'application/x-www-form-urlencoded'
...@@ -114,7 +125,7 @@ export const fetch = { ...@@ -114,7 +125,7 @@ export const fetch = {
114 * @param {Object} config axios 配置 125 * @param {Object} config axios 配置
115 * @returns {Promise<any>} axios Promise 126 * @returns {Promise<any>} axios Promise
116 */ 127 */
117 - basePost: function (url, data, config) { 128 + basePost(url, data, config) {
118 return axios.post(url, data, config) 129 return axios.post(url, data, config)
119 } 130 }
120 } 131 }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 * @FilePath: /xyxBooking-weapp/src/api/index.js 5 * @FilePath: /xyxBooking-weapp/src/api/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
8 -import { fn, fetch } from '@/api/fn'; 8 +import { fn, fetch } from '@/api/fn'
9 9
10 /** 10 /**
11 * @description 预约业务 API 聚合 11 * @description 预约业务 API 聚合
...@@ -30,22 +30,22 @@ const Api = { ...@@ -30,22 +30,22 @@ const Api = {
30 BILL_PREPARE: '/srv/?a=api&t=bill_person', 30 BILL_PREPARE: '/srv/?a=api&t=bill_person',
31 // BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status', 31 // BILL_PAY_STATUS: '/srv/?a=api&t=bill_pay_status',
32 QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code', 32 QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code',
33 - ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry', 33 + ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry'
34 -}; 34 +}
35 35
36 /** 36 /**
37 * @description: 可预约日期列表 37 * @description: 可预约日期列表
38 * @param {Array} month 月份,格式yyyy-mm, reserve_full 是否可约 1=可约,0=约满,-1=没有配置预约时段, open_time 在今天,开放预约最晚可预约日期的后一天的时间点, tips 不可预约的提示信息 38 * @param {Array} month 月份,格式yyyy-mm, reserve_full 是否可约 1=可约,0=约满,-1=没有配置预约时段, open_time 在今天,开放预约最晚可预约日期的后一天的时间点, tips 不可预约的提示信息
39 * @returns 39 * @returns
40 */ 40 */
41 -export const canReserveDateListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_DATE_LIST, params)); 41 +export const canReserveDateListAPI = params => fn(fetch.get(Api.CAN_RESERVE_DATE_LIST, params))
42 42
43 /** 43 /**
44 * @description: 可预约时段列表 44 * @description: 可预约时段列表
45 * @param {Array} month_date 日期,格式yyyy-mm-dd 45 * @param {Array} month_date 日期,格式yyyy-mm-dd
46 * @returns 46 * @returns
47 */ 47 */
48 -export const canReserveTimeListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_TIME_LIST, params)); 48 +export const canReserveTimeListAPI = params => fn(fetch.get(Api.CAN_RESERVE_TIME_LIST, params))
49 49
50 /** 50 /**
51 * @description: 参观者列表 51 * @description: 参观者列表
...@@ -54,7 +54,7 @@ export const canReserveTimeListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_TI ...@@ -54,7 +54,7 @@ export const canReserveTimeListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_TI
54 * @param {String} end_time 时段结束时间,格式 hh:mm 54 * @param {String} end_time 时段结束时间,格式 hh:mm
55 * @returns 55 * @returns
56 */ 56 */
57 -export const personListAPI = (params) => fn(fetch.get(Api.PERSON_LIST, params)); 57 +export const personListAPI = params => fn(fetch.get(Api.PERSON_LIST, params))
58 58
59 /** 59 /**
60 * @description: 添加参观者 60 * @description: 添加参观者
...@@ -63,14 +63,14 @@ export const personListAPI = (params) => fn(fetch.get(Api.PERSON_LIST, params)); ...@@ -63,14 +63,14 @@ export const personListAPI = (params) => fn(fetch.get(Api.PERSON_LIST, params));
63 * @param {String} id_number 证件号 63 * @param {String} id_number 证件号
64 * @returns 64 * @returns
65 */ 65 */
66 -export const addPersonAPI = (params) => fn(fetch.post(Api.ADD_PERSON, params)); 66 +export const addPersonAPI = params => fn(fetch.post(Api.ADD_PERSON, params))
67 67
68 /** 68 /**
69 * @description: 删除参观者 69 * @description: 删除参观者
70 * @param {String} person_id 参观者id 70 * @param {String} person_id 参观者id
71 * @returns 71 * @returns
72 */ 72 */
73 -export const delPersonAPI = (params) => fn(fetch.post(Api.DEL_PERSON, params)); 73 +export const delPersonAPI = params => fn(fetch.post(Api.DEL_PERSON, params))
74 74
75 /** 75 /**
76 * @description: 提交预约 76 * @description: 提交预约
...@@ -80,7 +80,7 @@ export const delPersonAPI = (params) => fn(fetch.post(Api.DEL_PERSON, params)); ...@@ -80,7 +80,7 @@ export const delPersonAPI = (params) => fn(fetch.post(Api.DEL_PERSON, params));
80 * @param {String} person_id_list 80 * @param {String} person_id_list
81 * @returns {String} bill_id 预约单id 81 * @returns {String} bill_id 预约单id
82 */ 82 */
83 -export const addReserveAPI = (params) => fn(fetch.post(Api.ADD_RESERVE, params)); 83 +export const addReserveAPI = params => fn(fetch.post(Api.ADD_RESERVE, params))
84 84
85 /** 85 /**
86 * @description: 支付准备(模拟) 86 * @description: 支付准备(模拟)
...@@ -102,34 +102,34 @@ export const addReserveAPI = (params) => fn(fetch.post(Api.ADD_RESERVE, params)) ...@@ -102,34 +102,34 @@ export const addReserveAPI = (params) => fn(fetch.post(Api.ADD_RESERVE, params))
102 * @param {String} bill_id 预约单id 102 * @param {String} bill_id 预约单id
103 * @returns {String} 103 * @returns {String}
104 */ 104 */
105 -export const billInfoAPI = (params) => fn(fetch.get(Api.BILL_INFO, params)); 105 +export const billInfoAPI = params => fn(fetch.get(Api.BILL_INFO, params))
106 106
107 /** 107 /**
108 * @description: 预约单详情,参观者列表 - 免授权接口 108 * @description: 预约单详情,参观者列表 - 免授权接口
109 * @param {String} pay_id 订单id 109 * @param {String} pay_id 订单id
110 * @returns {String} 110 * @returns {String}
111 */ 111 */
112 -export const onAuthBillInfoAPI = (params) => fn(fetch.get(Api.ON_AUTH_BILL_INFO, params)); 112 +export const onAuthBillInfoAPI = params => fn(fetch.get(Api.ON_AUTH_BILL_INFO, params))
113 113
114 /** 114 /**
115 * @description: 预约码列表 115 * @description: 预约码列表
116 * @returns {String} 116 * @returns {String}
117 */ 117 */
118 -export const qrcodeListAPI = (params) => fn(fetch.get(Api.QRCODE_LIST, params)); 118 +export const qrcodeListAPI = params => fn(fetch.get(Api.QRCODE_LIST, params))
119 119
120 /** 120 /**
121 * @description: 二维码使用状态 121 * @description: 二维码使用状态
122 * @param {String} qr_code 二维码编号 122 * @param {String} qr_code 二维码编号
123 * @returns {String} status 二维码状态 1=未激活(未支付),3=待使用(已支付),5=被取消,7=已使用 123 * @returns {String} status 二维码状态 1=未激活(未支付),3=待使用(已支付),5=被取消,7=已使用
124 */ 124 */
125 -export const qrcodeStatusAPI = (params) => fn(fetch.get(Api.QRCODE_STATUS, params)); 125 +export const qrcodeStatusAPI = params => fn(fetch.get(Api.QRCODE_STATUS, params))
126 126
127 /** 127 /**
128 * @description: 预约单列表 128 * @description: 预约单列表
129 * @param {String} 129 * @param {String}
130 * @returns {String} 130 * @returns {String}
131 */ 131 */
132 -export const billListAPI = (params) => fn(fetch.get(Api.BILL_LIST, params)); 132 +export const billListAPI = params => fn(fetch.get(Api.BILL_LIST, params))
133 133
134 /** 134 /**
135 * @description: 所有预约单的详情(用于离线缓存:列表+详情) 135 * @description: 所有预约单的详情(用于离线缓存:列表+详情)
...@@ -149,21 +149,21 @@ export const billListAPI = (params) => fn(fetch.get(Api.BILL_LIST, params)); ...@@ -149,21 +149,21 @@ export const billListAPI = (params) => fn(fetch.get(Api.BILL_LIST, params));
149 * @returns: {Object} data[].list 列表字段集合 149 * @returns: {Object} data[].list 列表字段集合
150 * @returns: {Number} data[].list.show_cancel_reserve 显示“取消预约”按钮(1=显示) 150 * @returns: {Number} data[].list.show_cancel_reserve 显示“取消预约”按钮(1=显示)
151 */ 151 */
152 -export const billOfflineAllAPI = (params) => fn(fetch.get(Api.BILL_OFFLINE_ALL, params)); 152 +export const billOfflineAllAPI = params => fn(fetch.get(Api.BILL_OFFLINE_ALL, params))
153 153
154 /** 154 /**
155 * @description: 取消预约 155 * @description: 取消预约
156 * @param {String} pay_id 156 * @param {String} pay_id
157 * @returns {String} 157 * @returns {String}
158 */ 158 */
159 -export const icbcRefundAPI = (params) => fn(fetch.post(Api.ICBC_REFUND, params)); 159 +export const icbcRefundAPI = params => fn(fetch.post(Api.ICBC_REFUND, params))
160 160
161 /** 161 /**
162 * @description: 预约单的参观者列表 162 * @description: 预约单的参观者列表
163 * @param {String} 163 * @param {String}
164 * @returns {String} 164 * @returns {String}
165 */ 165 */
166 -export const billPersonAPI = (params) => fn(fetch.get(Api.BILL_PREPARE, params)); 166 +export const billPersonAPI = params => fn(fetch.get(Api.BILL_PREPARE, params))
167 167
168 /** 168 /**
169 * 接口废弃 169 * 接口废弃
...@@ -179,7 +179,7 @@ export const billPersonAPI = (params) => fn(fetch.get(Api.BILL_PREPARE, params)) ...@@ -179,7 +179,7 @@ export const billPersonAPI = (params) => fn(fetch.get(Api.BILL_PREPARE, params))
179 * @param {string} params.id_number 身份证号 179 * @param {string} params.id_number 身份证号
180 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 180 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
181 */ 181 */
182 -export const queryQrCodeAPI = (params) => fn(fetch.get(Api.QUERY_QR_CODE, params)); 182 +export const queryQrCodeAPI = params => fn(fetch.get(Api.QUERY_QR_CODE, params))
183 183
184 /** 184 /**
185 * @description: 查询订单号 185 * @description: 查询订单号
...@@ -187,4 +187,4 @@ export const queryQrCodeAPI = (params) => fn(fetch.get(Api.QUERY_QR_CODE, params ...@@ -187,4 +187,4 @@ export const queryQrCodeAPI = (params) => fn(fetch.get(Api.QUERY_QR_CODE, params
187 * @param {string} params.pay_id 支付凭证/订单号 187 * @param {string} params.pay_id 支付凭证/订单号
188 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 188 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
189 */ 189 */
190 -export const icbcOrderQryAPI = (params) => fn(fetch.get(Api.ICBC_ORDER_QRY, params)); 190 +export const icbcOrderQryAPI = params => fn(fetch.get(Api.ICBC_ORDER_QRY, params))
......
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
5 * @FilePath: /xyxBooking-weapp/src/api/redeem.js 5 * @FilePath: /xyxBooking-weapp/src/api/redeem.js
6 * @Description: 义工核销端接口 6 * @Description: 义工核销端接口
7 */ 7 */
8 -import { fn, fetch } from '@/api/fn'; 8 +import { fn, fetch } from '@/api/fn'
9 9
10 const Api = { 10 const Api = {
11 REDEEM_LOGIN: '/srv/?f=reserve_admin&a=login', 11 REDEEM_LOGIN: '/srv/?f=reserve_admin&a=login',
12 REDEEM_CHECK_AUTH: '/srv/?f=reserve_admin&a=user&t=check_auth', 12 REDEEM_CHECK_AUTH: '/srv/?f=reserve_admin&a=user&t=check_auth',
13 - REDEEM_REDEEM: '/srv/?f=reserve_admin&a=bill&t=redeem', 13 + REDEEM_REDEEM: '/srv/?f=reserve_admin&a=bill&t=redeem'
14 } 14 }
15 15
16 /** 16 /**
...@@ -18,18 +18,18 @@ const Api = { ...@@ -18,18 +18,18 @@ const Api = {
18 * @param {Object} params 请求参数 18 * @param {Object} params 请求参数
19 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 19 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
20 */ 20 */
21 -export const volunteerLoginAPI = (params) => fn(fetch.post(Api.REDEEM_LOGIN, params)); 21 +export const volunteerLoginAPI = params => fn(fetch.post(Api.REDEEM_LOGIN, params))
22 22
23 /** 23 /**
24 * @description: 检查核销权限 24 * @description: 检查核销权限
25 * @param {Object} params 请求参数 25 * @param {Object} params 请求参数
26 * @returns {Promise<{code:number,data:{can_redeem:boolean},msg:string}>} 标准返回 26 * @returns {Promise<{code:number,data:{can_redeem:boolean},msg:string}>} 标准返回
27 */ 27 */
28 -export const checkRedeemPermissionAPI = (params) => fn(fetch.get(Api.REDEEM_CHECK_AUTH, params)); 28 +export const checkRedeemPermissionAPI = params => fn(fetch.get(Api.REDEEM_CHECK_AUTH, params))
29 29
30 /** 30 /**
31 * @description: 核销 31 * @description: 核销
32 * @param {Object} params 请求参数 32 * @param {Object} params 请求参数
33 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 33 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
34 */ 34 */
35 -export const verifyTicketAPI = (params) => fn(fetch.post(Api.REDEEM_REDEEM, params)); 35 +export const verifyTicketAPI = params => fn(fetch.post(Api.REDEEM_REDEEM, params))
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
2 * @Date: 2026-01-10 2 * @Date: 2026-01-10
3 * @Description: 从原始文档转换生成的 API 接口文件 3 * @Description: 从原始文档转换生成的 API 接口文件
4 */ 4 */
5 -import { fn, fetch } from '@/api/fn'; 5 +import { fn, fetch } from '@/api/fn'
6 6
7 const Api = { 7 const Api = {
8 CAN_RESERVE_DATE_LIST: '/srv/?a=api&t=can_reserve_date_list', 8 CAN_RESERVE_DATE_LIST: '/srv/?a=api&t=can_reserve_date_list',
9 - CAN_RESERVE_TIME_LIST: '/srv/?a=api&t=can_reserve_time_list', 9 + CAN_RESERVE_TIME_LIST: '/srv/?a=api&t=can_reserve_time_list'
10 -}; 10 +}
11 11
12 /** 12 /**
13 * @description: 可预约日期列表 13 * @description: 可预约日期列表
...@@ -22,7 +22,7 @@ const Api = { ...@@ -22,7 +22,7 @@ const Api = {
22 * }> 22 * }>
23 * }>} 23 * }>}
24 */ 24 */
25 -export const canReserveDateListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_DATE_LIST, params)); 25 +export const canReserveDateListAPI = params => fn(fetch.get(Api.CAN_RESERVE_DATE_LIST, params))
26 26
27 /** 27 /**
28 * @description: 可预约时段列表 28 * @description: 可预约时段列表
...@@ -39,4 +39,4 @@ export const canReserveDateListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_DA ...@@ -39,4 +39,4 @@ export const canReserveDateListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_DA
39 * }> 39 * }>
40 * }>} 40 * }>}
41 */ 41 */
42 -export const canReserveTimeListAPI = (params) => fn(fetch.get(Api.CAN_RESERVE_TIME_LIST, params)); 42 +export const canReserveTimeListAPI = params => fn(fetch.get(Api.CAN_RESERVE_TIME_LIST, params))
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
6 * @FilePath: /tswj/src/api/wx/config.js 6 * @FilePath: /tswj/src/api/wx/config.js
7 * @Description: 7 * @Description:
8 */ 8 */
9 -import { fn, fetch } from '@/api/fn'; 9 +import { fn, fetch } from '@/api/fn'
10 10
11 const Api = { 11 const Api = {
12 - WX_JSAPI: '/srv/?a=wx_share', 12 + WX_JSAPI: '/srv/?a=wx_share'
13 } 13 }
14 14
15 /** 15 /**
...@@ -18,4 +18,4 @@ const Api = { ...@@ -18,4 +18,4 @@ const Api = {
18 * @param {string} params.url 当前页面 URL(用于签名) 18 * @param {string} params.url 当前页面 URL(用于签名)
19 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 19 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
20 */ 20 */
21 -export const wxJsAPI = (params) => fn(fetch.get(Api.WX_JSAPI, params)); 21 +export const wxJsAPI = params => fn(fetch.get(Api.WX_JSAPI, params))
......
...@@ -11,41 +11,41 @@ ...@@ -11,41 +11,41 @@
11 * @type {Array<string>} 11 * @type {Array<string>}
12 */ 12 */
13 export const apiList = [ 13 export const apiList = [
14 - "updateAppMessageShareData", 14 + 'updateAppMessageShareData',
15 - "updateTimelineShareData", 15 + 'updateTimelineShareData',
16 - "onMenuShareTimeline", 16 + 'onMenuShareTimeline',
17 - "onMenuShareAppMessage", 17 + 'onMenuShareAppMessage',
18 - "onMenuShareQQ", 18 + 'onMenuShareQQ',
19 - "onMenuShareWeibo", 19 + 'onMenuShareWeibo',
20 - "onMenuShareQZone", 20 + 'onMenuShareQZone',
21 - "startRecord", 21 + 'startRecord',
22 - "stopRecord", 22 + 'stopRecord',
23 - "onVoiceRecordEnd", 23 + 'onVoiceRecordEnd',
24 - "playVoice", 24 + 'playVoice',
25 - "pauseVoice", 25 + 'pauseVoice',
26 - "stopVoice", 26 + 'stopVoice',
27 - "onVoicePlayEnd", 27 + 'onVoicePlayEnd',
28 - "uploadVoice", 28 + 'uploadVoice',
29 - "downloadVoice", 29 + 'downloadVoice',
30 - "chooseImage", 30 + 'chooseImage',
31 - "previewImage", 31 + 'previewImage',
32 - "uploadImage", 32 + 'uploadImage',
33 - "downloadImage", 33 + 'downloadImage',
34 - "translateVoice", 34 + 'translateVoice',
35 - "getNetworkType", 35 + 'getNetworkType',
36 - "openLocation", 36 + 'openLocation',
37 - "getLocation", 37 + 'getLocation',
38 - "hideOptionMenu", 38 + 'hideOptionMenu',
39 - "showOptionMenu", 39 + 'showOptionMenu',
40 - "hideMenuItems", 40 + 'hideMenuItems',
41 - "showMenuItems", 41 + 'showMenuItems',
42 - "hideAllNonBaseMenuItem", 42 + 'hideAllNonBaseMenuItem',
43 - "showAllNonBaseMenuItem", 43 + 'showAllNonBaseMenuItem',
44 - "closeWindow", 44 + 'closeWindow',
45 - "scanQRCode", 45 + 'scanQRCode',
46 - "chooseWXPay", 46 + 'chooseWXPay',
47 - "openProductSpecificView", 47 + 'openProductSpecificView',
48 - "addCard", 48 + 'addCard',
49 - "chooseCard", 49 + 'chooseCard',
50 - "openCard" 50 + 'openCard'
51 ] 51 ]
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
6 * @FilePath: /tswj/src/api/wx/config.js 6 * @FilePath: /tswj/src/api/wx/config.js
7 * @Description: 7 * @Description:
8 */ 8 */
9 -import { fn, fetch } from '@/api/fn'; 9 +import { fn, fetch } from '@/api/fn'
10 10
11 const Api = { 11 const Api = {
12 - WX_PAY: '/srv/?a=icbc_pay_wxamp', 12 + WX_PAY: '/srv/?a=icbc_pay_wxamp'
13 } 13 }
14 14
15 /** 15 /**
...@@ -18,4 +18,4 @@ const Api = { ...@@ -18,4 +18,4 @@ const Api = {
18 * @param {string} params.pay_id 预约单支付凭证 18 * @param {string} params.pay_id 预约单支付凭证
19 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回(data 为微信支付参数) 19 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回(data 为微信支付参数)
20 */ 20 */
21 -export const wxPayAPI = (params) => fn(fetch.post(Api.WX_PAY, params)); 21 +export const wxPayAPI = params => fn(fetch.post(Api.WX_PAY, params))
......
...@@ -24,7 +24,7 @@ const pages = [ ...@@ -24,7 +24,7 @@ const pages = [
24 'pages/weakNetwork/index', 24 'pages/weakNetwork/index',
25 'pages/offlineBookingCode/index', 25 'pages/offlineBookingCode/index',
26 'pages/offlineBookingList/index', 26 'pages/offlineBookingList/index',
27 - 'pages/offlineBookingDetail/index', 27 + 'pages/offlineBookingDetail/index'
28 ] 28 ]
29 29
30 if (process.env.NODE_ENV === 'development') { 30 if (process.env.NODE_ENV === 'development') {
...@@ -32,12 +32,13 @@ if (process.env.NODE_ENV === 'development') { ...@@ -32,12 +32,13 @@ if (process.env.NODE_ENV === 'development') {
32 pages.push('pages/tailwindTest/index') 32 pages.push('pages/tailwindTest/index')
33 } 33 }
34 34
35 -const subpackages = process.env.NODE_ENV === 'development' 35 +const subpackages =
36 + process.env.NODE_ENV === 'development'
36 ? [ 37 ? [
37 { 38 {
38 root: 'pages/demo', 39 root: 'pages/demo',
39 - pages: ['index'], 40 + pages: ['index']
40 - }, 41 + }
41 ] 42 ]
42 : [] 43 : []
43 44
...@@ -48,6 +49,6 @@ export default { ...@@ -48,6 +49,6 @@ export default {
48 backgroundTextStyle: 'light', 49 backgroundTextStyle: 'light',
49 navigationBarBackgroundColor: '#fff', 50 navigationBarBackgroundColor: '#fff',
50 navigationBarTitleText: '西园寺预约', 51 navigationBarTitleText: '西园寺预约',
51 - navigationBarTextStyle: 'black', 52 + navigationBarTextStyle: 'black'
52 - }, 53 + }
53 } 54 }
......
...@@ -11,7 +11,10 @@ import './utils/polyfill' ...@@ -11,7 +11,10 @@ import './utils/polyfill'
11 import './app.less' 11 import './app.less'
12 import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect' 12 import { saveCurrentPagePath, hasAuth, silentAuth, navigateToAuth } from '@/utils/authRedirect'
13 import Taro from '@tarojs/taro' 13 import Taro from '@tarojs/taro'
14 -import { refresh_offline_booking_cache, has_offline_booking_cache } from '@/composables/useOfflineBookingCache' 14 +import {
15 + refresh_offline_booking_cache,
16 + has_offline_booking_cache
17 +} from '@/composables/useOfflineBookingCache'
15 import { is_usable_network, get_network_type } from '@/utils/network' 18 import { is_usable_network, get_network_type } from '@/utils/network'
16 import { enable_offline_booking_cache_polling } from '@/composables/useOfflineBookingCachePolling' 19 import { enable_offline_booking_cache_polling } from '@/composables/useOfflineBookingCachePolling'
17 import { weak_network_text, get_weak_network_modal_use_cache_options } from '@/utils/uiText' 20 import { weak_network_text, get_weak_network_modal_use_cache_options } from '@/utils/uiText'
...@@ -28,7 +31,7 @@ const App = createApp({ ...@@ -28,7 +31,7 @@ const App = createApp({
28 const query = options?.query || {} 31 const query = options?.query || {}
29 32
30 const query_string = Object.keys(query) 33 const query_string = Object.keys(query)
31 - .map((key) => `${key}=${encodeURIComponent(query[key])}`) 34 + .map(key => `${key}=${encodeURIComponent(query[key])}`)
32 .join('&') 35 .join('&')
33 const full_path = query_string ? `${path}?${query_string}` : path 36 const full_path = query_string ? `${path}?${query_string}` : path
34 37
...@@ -61,10 +64,18 @@ const App = createApp({ ...@@ -61,10 +64,18 @@ const App = createApp({
61 const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : [] 64 const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : []
62 const current_page = pages && pages.length ? pages[pages.length - 1] : null 65 const current_page = pages && pages.length ? pages[pages.length - 1] : null
63 const current_route = String(current_page?.route || '') 66 const current_route = String(current_page?.route || '')
64 - if (!current_route) return false 67 + if (!current_route) {
65 - if (current_route.includes('pages/offlineBookingList/index')) return true 68 + return false
66 - if (current_route.includes('pages/offlineBookingDetail/index')) return true 69 + }
67 - if (current_route.includes('pages/offlineBookingCode/index')) return true 70 + if (current_route.includes('pages/offlineBookingList/index')) {
71 + return true
72 + }
73 + if (current_route.includes('pages/offlineBookingDetail/index')) {
74 + return true
75 + }
76 + if (current_route.includes('pages/offlineBookingCode/index')) {
77 + return true
78 + }
68 return false 79 return false
69 } 80 }
70 81
...@@ -77,13 +88,19 @@ const App = createApp({ ...@@ -77,13 +88,19 @@ const App = createApp({
77 * @returns {Promise<boolean>} true=需要中断后续启动流程,false=继续 88 * @returns {Promise<boolean>} true=需要中断后续启动流程,false=继续
78 */ 89 */
79 90
80 - const handle_bad_network = async (network_type) => { 91 + const handle_bad_network = async network_type => {
81 - if (has_shown_network_modal) return false 92 + if (has_shown_network_modal) {
82 - if (should_skip_network_prompt()) return false 93 + return false
94 + }
95 + if (should_skip_network_prompt()) {
96 + return false
97 + }
83 98
84 const is_none_network = network_type === 'none' 99 const is_none_network = network_type === 'none'
85 const is_weak_network = !is_usable_network(network_type) 100 const is_weak_network = !is_usable_network(network_type)
86 - if (!is_weak_network) return false 101 + if (!is_weak_network) {
102 + return false
103 + }
87 104
88 has_shown_network_modal = true 105 has_shown_network_modal = true
89 106
...@@ -99,7 +116,11 @@ const App = createApp({ ...@@ -99,7 +116,11 @@ const App = createApp({
99 } 116 }
100 } else { 117 } else {
101 try { 118 try {
102 - await Taro.showToast({ title: weak_network_text.toast_title, icon: 'none', duration: 2000 }) 119 + await Taro.showToast({
120 + title: weak_network_text.toast_title,
121 + icon: 'none',
122 + duration: 2000
123 + })
103 } catch (e) { 124 } catch (e) {
104 return is_none_network 125 return is_none_network
105 } 126 }
...@@ -112,7 +133,7 @@ const App = createApp({ ...@@ -112,7 +133,7 @@ const App = createApp({
112 * 监听网络状态变化 133 * 监听网络状态变化
113 * - 当网络连接且有授权时,预加载离线预约记录数据 134 * - 当网络连接且有授权时,预加载离线预约记录数据
114 */ 135 */
115 - Taro.onNetworkStatusChange((res) => { 136 + Taro.onNetworkStatusChange(res => {
116 const is_connected = res?.isConnected !== false 137 const is_connected = res?.isConnected !== false
117 const network_type = res?.networkType || 'none' 138 const network_type = res?.networkType || 'none'
118 const network_usable = is_connected && is_usable_network(network_type) 139 const network_usable = is_connected && is_usable_network(network_type)
...@@ -120,7 +141,9 @@ const App = createApp({ ...@@ -120,7 +141,9 @@ const App = createApp({
120 if (network_usable) { 141 if (network_usable) {
121 has_shown_network_modal = false 142 has_shown_network_modal = false
122 last_network_usable = true 143 last_network_usable = true
123 - if (hasAuth()) preloadBookingData() 144 + if (hasAuth()) {
145 + preloadBookingData()
146 + }
124 return 147 return
125 } 148 }
126 149
...@@ -129,7 +152,6 @@ const App = createApp({ ...@@ -129,7 +152,6 @@ const App = createApp({
129 if (should_prompt) { 152 if (should_prompt) {
130 handle_bad_network(network_type) 153 handle_bad_network(network_type)
131 } 154 }
132 - return
133 }) 155 })
134 156
135 /** 157 /**
...@@ -144,7 +166,9 @@ const App = createApp({ ...@@ -144,7 +166,9 @@ const App = createApp({
144 * - 仅在首次启动时检查网络情况 166 * - 仅在首次启动时检查网络情况
145 * - 如果用户已展示过提示弹窗,则直接返回 false 167 * - 如果用户已展示过提示弹窗,则直接返回 false
146 */ 168 */
147 - if (has_shown_network_modal) return false 169 + if (has_shown_network_modal) {
170 + return false
171 + }
148 172
149 const network_type = await get_network_type() 173 const network_type = await get_network_type()
150 last_network_usable = is_usable_network(network_type) 174 last_network_usable = is_usable_network(network_type)
...@@ -157,9 +181,11 @@ const App = createApp({ ...@@ -157,9 +181,11 @@ const App = createApp({
157 * @returns {void} 无返回值 181 * @returns {void} 无返回值
158 */ 182 */
159 const try_preload_when_online = () => { 183 const try_preload_when_online = () => {
160 - if (!hasAuth()) return 184 + if (!hasAuth()) {
185 + return
186 + }
161 Taro.getNetworkType({ 187 Taro.getNetworkType({
162 - success: (res) => { 188 + success: res => {
163 if (is_usable_network(res.networkType)) { 189 if (is_usable_network(res.networkType)) {
164 preloadBookingData() 190 preloadBookingData()
165 } 191 }
...@@ -182,7 +208,9 @@ const App = createApp({ ...@@ -182,7 +208,9 @@ const App = createApp({
182 // 处理在启动时出现的不良网络情况 208 // 处理在启动时出现的不良网络情况
183 const should_stop = await handle_bad_network_on_launch() 209 const should_stop = await handle_bad_network_on_launch()
184 // 如果用户选择进入离线模式,则直接返回 210 // 如果用户选择进入离线模式,则直接返回
185 - if (should_stop) return 211 + if (should_stop) {
212 + return
213 + }
186 214
187 /** 215 /**
188 * 尝试在有授权时预加载离线预约记录数据 216 * 尝试在有授权时预加载离线预约记录数据
...@@ -197,7 +225,9 @@ const App = createApp({ ...@@ -197,7 +225,9 @@ const App = createApp({
197 return 225 return
198 } 226 }
199 227
200 - if (path === 'pages/auth/index') return 228 + if (path === 'pages/auth/index') {
229 + return
230 + }
201 231
202 try { 232 try {
203 // 尝试静默授权 233 // 尝试静默授权
...@@ -209,12 +239,9 @@ const App = createApp({ ...@@ -209,12 +239,9 @@ const App = createApp({
209 // 授权失败则跳转至授权页面 239 // 授权失败则跳转至授权页面
210 navigateToAuth(full_path || undefined) 240 navigateToAuth(full_path || undefined)
211 } 241 }
212 -
213 - return
214 - },
215 - onShow() {
216 }, 242 },
217 -}); 243 + onShow() {}
244 +})
218 245
219 App.use(createPinia()) 246 App.use(createPinia())
220 247
......
...@@ -11,5 +11,5 @@ ...@@ -11,5 +11,5 @@
11 @tailwind utilities; 11 @tailwind utilities;
12 12
13 :root { 13 :root {
14 - --nut-primary-color: #A67939; 14 + --nut-primary-color: #a67939;
15 } 15 }
......
1 -
2 .modify-top { 1 .modify-top {
3 z-index: 36; 2 z-index: 36;
4 position: absolute; 3 position: absolute;
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
3 /* ============ 颜色 ============ */ 3 /* ============ 颜色 ============ */
4 4
5 // 主色调 5 // 主色调
6 -@base-color: #11D2B1; 6 +@base-color: #11d2b1;
7 // 文字颜色 7 // 文字颜色
8 -@base-font-color: #FFFFFF; 8 +@base-font-color: #ffffff;
9 9
10 // 定义一个映射 10 // 定义一个映射
11 #colors() { 11 #colors() {
......
...@@ -8,30 +8,24 @@ ...@@ -8,30 +8,24 @@
8 /> 8 />
9 </template> 9 </template>
10 <script> 10 <script>
11 -import Taro from "@tarojs/taro" 11 +import Taro from '@tarojs/taro'
12 -import { defineComponent, onMounted, ref } from "vue" 12 +import { defineComponent, onMounted, ref } from 'vue'
13 -import { drawImage, drawText, drawBlock, drawLine } from "./utils/draw.js" 13 +import { drawImage, drawText, drawBlock, drawLine } from './utils/draw.js'
14 -import { 14 +import { toPx, toRpx, getRandomId, getImageInfo, getLinearColor } from './utils/tools.js'
15 - toPx,
16 - toRpx,
17 - getRandomId,
18 - getImageInfo,
19 - getLinearColor,
20 -} from "./utils/tools.js"
21 15
22 export default defineComponent({ 16 export default defineComponent({
23 - name: "PosterBuilder", 17 + name: 'PosterBuilder',
24 props: { 18 props: {
25 showLoading: { 19 showLoading: {
26 type: Boolean, 20 type: Boolean,
27 - default: false, 21 + default: false
28 }, 22 },
29 config: { 23 config: {
30 type: Object, 24 type: Object,
31 - default: () => ({}), 25 + default: () => ({})
32 - }, 26 + }
33 }, 27 },
34 - emits: ["success", "fail"], 28 + emits: ['success', 'fail'],
35 setup(props, context) { 29 setup(props, context) {
36 const count = ref(1) 30 const count = ref(1)
37 const { 31 const {
...@@ -41,7 +35,7 @@ export default defineComponent({ ...@@ -41,7 +35,7 @@ export default defineComponent({
41 texts = [], 35 texts = [],
42 blocks = [], 36 blocks = [],
43 lines = [], 37 lines = [],
44 - debug = false, 38 + debug = false
45 } = props.config || {} 39 } = props.config || {}
46 40
47 const canvasId = getRandomId() 41 const canvasId = getRandomId()
...@@ -51,11 +45,9 @@ export default defineComponent({ ...@@ -51,11 +45,9 @@ export default defineComponent({
51 * @param {Array} images = imgTask 45 * @param {Array} images = imgTask
52 * @return {Promise} downloadImagePromise 46 * @return {Promise} downloadImagePromise
53 */ 47 */
54 - const initImages = (images) => { 48 + const initImages = images => {
55 - const imagesTemp = images.filter((item) => item.url) 49 + const imagesTemp = images.filter(item => item.url)
56 - const drawList = imagesTemp.map((item, index) => 50 + const drawList = imagesTemp.map((item, index) => getImageInfo(item, index))
57 - getImageInfo(item, index)
58 - )
59 return Promise.all(drawList) 51 return Promise.all(drawList)
60 } 52 }
61 53
...@@ -64,15 +56,15 @@ export default defineComponent({ ...@@ -64,15 +56,15 @@ export default defineComponent({
64 * @return {Promise} resolve 里返回其 dom 和实例 56 * @return {Promise} resolve 里返回其 dom 和实例
65 */ 57 */
66 const initCanvas = () => 58 const initCanvas = () =>
67 - new Promise((resolve) => { 59 + new Promise(resolve => {
68 setTimeout(() => { 60 setTimeout(() => {
69 const pageInstance = Taro.getCurrentInstance()?.page || {} // 拿到当前页面实例 61 const pageInstance = Taro.getCurrentInstance()?.page || {} // 拿到当前页面实例
70 const query = Taro.createSelectorQuery().in(pageInstance) // 确定在当前页面内匹配子元素 62 const query = Taro.createSelectorQuery().in(pageInstance) // 确定在当前页面内匹配子元素
71 query 63 query
72 .select(`#${canvasId}`) 64 .select(`#${canvasId}`)
73 - .fields({ node: true, size: true, context: true }, (res) => { 65 + .fields({ node: true, size: true, context: true }, res => {
74 const canvas = res.node 66 const canvas = res.node
75 - const ctx = canvas.getContext("2d") 67 + const ctx = canvas.getContext('2d')
76 resolve({ ctx, canvas }) 68 resolve({ ctx, canvas })
77 }) 69 })
78 .exec() 70 .exec()
...@@ -83,30 +75,30 @@ export default defineComponent({ ...@@ -83,30 +75,30 @@ export default defineComponent({
83 * @description 保存绘制的图片 75 * @description 保存绘制的图片
84 * @param { object } config 76 * @param { object } config
85 */ 77 */
86 - const getTempFile = (canvas) => { 78 + const getTempFile = canvas => {
87 Taro.canvasToTempFilePath( 79 Taro.canvasToTempFilePath(
88 { 80 {
89 canvas, 81 canvas,
90 - success: (result) => { 82 + success: result => {
91 Taro.hideLoading() 83 Taro.hideLoading()
92 - context.emit("success", result) 84 + context.emit('success', result)
93 }, 85 },
94 - fail: (error) => { 86 + fail: error => {
95 const { errMsg } = error 87 const { errMsg } = error
96 - if (errMsg === "canvasToTempFilePath:fail:create bitmap failed") { 88 + if (errMsg === 'canvasToTempFilePath:fail:create bitmap failed') {
97 count.value += 1 89 count.value += 1
98 if (count.value <= 3) { 90 if (count.value <= 3) {
99 getTempFile(canvas) 91 getTempFile(canvas)
100 } else { 92 } else {
101 Taro.hideLoading() 93 Taro.hideLoading()
102 Taro.showToast({ 94 Taro.showToast({
103 - icon: "none", 95 + icon: 'none',
104 - title: errMsg || "绘制海报失败", 96 + title: errMsg || '绘制海报失败'
105 }) 97 })
106 - context.emit("fail", errMsg) 98 + context.emit('fail', errMsg)
99 + }
107 } 100 }
108 } 101 }
109 - },
110 }, 102 },
111 context 103 context
112 ) 104 )
...@@ -116,7 +108,7 @@ export default defineComponent({ ...@@ -116,7 +108,7 @@ export default defineComponent({
116 * step2: 开始绘制任务 108 * step2: 开始绘制任务
117 * @param { Array } drawTasks 待绘制任务 109 * @param { Array } drawTasks 待绘制任务
118 */ 110 */
119 - const startDrawing = async (drawTasks) => { 111 + const startDrawing = async drawTasks => {
120 // TODO: check 112 // TODO: check
121 // const configHeight = getHeight(config) 113 // const configHeight = getHeight(config)
122 const { ctx, canvas } = await initCanvas() 114 const { ctx, canvas } = await initCanvas()
...@@ -135,22 +127,22 @@ export default defineComponent({ ...@@ -135,22 +127,22 @@ export default defineComponent({
135 // 将要画的方块、文字、线条放进队列数组 127 // 将要画的方块、文字、线条放进队列数组
136 const queue = drawTasks 128 const queue = drawTasks
137 .concat( 129 .concat(
138 - texts.map((item) => { 130 + texts.map(item => {
139 - item.type = "text" 131 + item.type = 'text'
140 item.zIndex = item.zIndex || 0 132 item.zIndex = item.zIndex || 0
141 return item 133 return item
142 }) 134 })
143 ) 135 )
144 .concat( 136 .concat(
145 - blocks.map((item) => { 137 + blocks.map(item => {
146 - item.type = "block" 138 + item.type = 'block'
147 item.zIndex = item.zIndex || 0 139 item.zIndex = item.zIndex || 0
148 return item 140 return item
149 }) 141 })
150 ) 142 )
151 .concat( 143 .concat(
152 - lines.map((item) => { 144 + lines.map(item => {
153 - item.type = "line" 145 + item.type = 'line'
154 item.zIndex = item.zIndex || 0 146 item.zIndex = item.zIndex || 0
155 return item 147 return item
156 }) 148 })
...@@ -162,15 +154,15 @@ export default defineComponent({ ...@@ -162,15 +154,15 @@ export default defineComponent({
162 canvas, 154 canvas,
163 ctx, 155 ctx,
164 toPx, 156 toPx,
165 - toRpx, 157 + toRpx
166 } 158 }
167 - if (queue[i].type === "image") { 159 + if (queue[i].type === 'image') {
168 await drawImage(queue[i], drawOptions) 160 await drawImage(queue[i], drawOptions)
169 - } else if (queue[i].type === "text") { 161 + } else if (queue[i].type === 'text') {
170 drawText(queue[i], drawOptions) 162 drawText(queue[i], drawOptions)
171 - } else if (queue[i].type === "block") { 163 + } else if (queue[i].type === 'block') {
172 drawBlock(queue[i], drawOptions) 164 drawBlock(queue[i], drawOptions)
173 - } else if (queue[i].type === "line") { 165 + } else if (queue[i].type === 'line') {
174 drawLine(queue[i], drawOptions) 166 drawLine(queue[i], drawOptions)
175 } 167 }
176 } 168 }
...@@ -182,21 +174,22 @@ export default defineComponent({ ...@@ -182,21 +174,22 @@ export default defineComponent({
182 174
183 // start: 初始化 canvas 实例 && 下载图片资源 175 // start: 初始化 canvas 实例 && 下载图片资源
184 const init = () => { 176 const init = () => {
185 - if (props.showLoading) 177 + if (props.showLoading) {
186 - Taro.showLoading({ mask: true, title: "生成中..." }) 178 + Taro.showLoading({ mask: true, title: '生成中...' })
179 + }
187 if (props.config?.images?.length) { 180 if (props.config?.images?.length) {
188 initImages(props.config.images) 181 initImages(props.config.images)
189 - .then((result) => { 182 + .then(result => {
190 // 1. 下载图片资源 183 // 1. 下载图片资源
191 startDrawing(result) 184 startDrawing(result)
192 }) 185 })
193 - .catch((err) => { 186 + .catch(err => {
194 Taro.hideLoading() 187 Taro.hideLoading()
195 Taro.showToast({ 188 Taro.showToast({
196 - icon: "none", 189 + icon: 'none',
197 - title: err.errMsg || "下载图片失败", 190 + title: err.errMsg || '下载图片失败'
198 }) 191 })
199 - context.emit("fail", err) 192 + context.emit('fail', err)
200 }) 193 })
201 } else { 194 } else {
202 startDrawing([]) 195 startDrawing([])
...@@ -211,8 +204,8 @@ export default defineComponent({ ...@@ -211,8 +204,8 @@ export default defineComponent({
211 canvasId, 204 canvasId,
212 debug, 205 debug,
213 width, 206 width,
214 - height, 207 + height
208 + }
215 } 209 }
216 - },
217 }) 210 })
218 </script> 211 </script>
......
...@@ -2,7 +2,9 @@ import { getLinearColor, getTextX, toPx } from './tools' ...@@ -2,7 +2,9 @@ import { getLinearColor, getTextX, toPx } from './tools'
2 2
3 const drawRadiusRect = ({ x, y, w, h, r }, { ctx }) => { 3 const drawRadiusRect = ({ x, y, w, h, r }, { ctx }) => {
4 const minSize = Math.min(w, h) 4 const minSize = Math.min(w, h)
5 - if (r > minSize / 2) r = minSize / 2 5 + if (r > minSize / 2) {
6 + r = minSize / 2
7 + }
6 ctx.beginPath() 8 ctx.beginPath()
7 ctx.moveTo(x + r, y) 9 ctx.moveTo(x + r, y)
8 ctx.arcTo(x + w, y, x + w, y + h, r) 10 ctx.arcTo(x + w, y, x + w, y + h, r)
...@@ -120,10 +122,7 @@ const drawSingleText = (drawData, drawOptions) => { ...@@ -120,10 +122,7 @@ const drawSingleText = (drawData, drawOptions) => {
120 122
121 if (restWidth < 0) { 123 if (restWidth < 0) {
122 if (line === lineNum) { 124 if (line === lineNum) {
123 - if ( 125 + if (restWidth + ctx.measureText(text[i + 1]).width > ctx.measureText('...').width) {
124 - restWidth + ctx.measureText(text[i + 1]).width >
125 - ctx.measureText('...').width
126 - ) {
127 fillText = `${fillText}...` 126 fillText = `${fillText}...`
128 } else { 127 } else {
129 fillText = `${fillText.substr(0, fillText.length - 1)}...` 128 fillText = `${fillText.substr(0, fillText.length - 1)}...`
...@@ -145,11 +144,7 @@ const drawSingleText = (drawData, drawOptions) => { ...@@ -145,11 +144,7 @@ const drawSingleText = (drawData, drawOptions) => {
145 } 144 }
146 145
147 textArr.forEach((item, index) => 146 textArr.forEach((item, index) =>
148 - ctx.fillText( 147 + ctx.fillText(item, getTextX(textAlign, x, width), y + (lineHeight || fontSize) * index)
149 - item,
150 - getTextX(textAlign, x, width),
151 - y + (lineHeight || fontSize) * index
152 - )
153 ) 148 )
154 ctx.restore() 149 ctx.restore()
155 150
...@@ -172,7 +167,7 @@ export function drawText(params, drawOptions) { ...@@ -172,7 +167,7 @@ export function drawText(params, drawOptions) {
172 const { x = 0, y = 0, text, baseLine } = params 167 const { x = 0, y = 0, text, baseLine } = params
173 if (Object.prototype.toString.call(text) === '[object Array]') { 168 if (Object.prototype.toString.call(text) === '[object Array]') {
174 const preText = { x, y, baseLine } 169 const preText = { x, y, baseLine }
175 - text.forEach((item) => { 170 + text.forEach(item => {
176 preText.x += item.marginLeft || 0 171 preText.x += item.marginLeft || 0
177 const textWidth = drawSingleText( 172 const textWidth = drawSingleText(
178 Object.assign(item, { ...preText, y: y + (item.marginTop || 0) }), 173 Object.assign(item, { ...preText, y: y + (item.marginTop || 0) }),
...@@ -188,7 +183,9 @@ export function drawText(params, drawOptions) { ...@@ -188,7 +183,9 @@ export function drawText(params, drawOptions) {
188 export function drawLine(drawData, drawOptions) { 183 export function drawLine(drawData, drawOptions) {
189 const { startX, startY, endX, endY, color, width } = drawData 184 const { startX, startY, endX, endY, color, width } = drawData
190 const { ctx } = drawOptions 185 const { ctx } = drawOptions
191 - if (!width) return 186 + if (!width) {
187 + return
188 + }
192 ctx.save() 189 ctx.save()
193 ctx.beginPath() 190 ctx.beginPath()
194 ctx.strokeStyle = color 191 ctx.strokeStyle = color
...@@ -225,10 +222,7 @@ export function drawBlock(data, drawOptions) { ...@@ -225,10 +222,7 @@ export function drawBlock(data, drawOptions) {
225 let textY = 0 222 let textY = 0
226 223
227 if (text) { 224 if (text) {
228 - const textWidth = getTextWidth( 225 + const textWidth = getTextWidth(typeof text.text === 'string' ? text : text.text, drawOptions)
229 - typeof text.text === 'string' ? text : text.text,
230 - drawOptions
231 - )
232 blockWidth = textWidth > width ? textWidth : width 226 blockWidth = textWidth > width ? textWidth : width
233 blockWidth += paddingLeft + paddingLeft 227 blockWidth += paddingLeft + paddingLeft
234 228
...@@ -296,7 +290,7 @@ export function drawBlock(data, drawOptions) { ...@@ -296,7 +290,7 @@ export function drawBlock(data, drawOptions) {
296 } 290 }
297 291
298 export const drawImage = (data, drawOptions) => 292 export const drawImage = (data, drawOptions) =>
299 - new Promise((resolve) => { 293 + new Promise(resolve => {
300 const { canvas, ctx } = drawOptions 294 const { canvas, ctx } = drawOptions
301 const { 295 const {
302 x, 296 x,
......
...@@ -59,8 +59,7 @@ export const getFactor = () => { ...@@ -59,8 +59,7 @@ export const getFactor = () => {
59 * @param {number} factor 换算系数 59 * @param {number} factor 换算系数
60 * @returns {number} px 值(整数) 60 * @returns {number} px 值(整数)
61 */ 61 */
62 -export const toPx = (rpx, factor = getFactor()) => 62 +export const toPx = (rpx, factor = getFactor()) => parseInt(String(rpx * factor), 10)
63 - parseInt(String(rpx * factor), 10)
64 63
65 /** 64 /**
66 * @description px 转 rpx 65 * @description px 转 rpx
...@@ -68,8 +67,7 @@ export const toPx = (rpx, factor = getFactor()) => ...@@ -68,8 +67,7 @@ export const toPx = (rpx, factor = getFactor()) =>
68 * @param {number} factor 换算系数 67 * @param {number} factor 换算系数
69 * @returns {number} rpx 值(整数) 68 * @returns {number} rpx 值(整数)
70 */ 69 */
71 -export const toRpx = (px, factor = getFactor()) => 70 +export const toRpx = (px, factor = getFactor()) => parseInt(String(px / factor), 10)
72 - parseInt(String(px / factor), 10)
73 71
74 /** 72 /**
75 * @description 下载图片到本地临时路径(避免跨域/协议限制) 73 * @description 下载图片到本地临时路径(避免跨域/协议限制)
...@@ -80,17 +78,15 @@ export const toRpx = (px, factor = getFactor()) => ...@@ -80,17 +78,15 @@ export const toRpx = (px, factor = getFactor()) =>
80 export function downImage(url) { 78 export function downImage(url) {
81 return new Promise((resolve, reject) => { 79 return new Promise((resolve, reject) => {
82 const wx_user_data_path = 80 const wx_user_data_path =
83 - (typeof wx !== 'undefined' && wx && wx.env && wx.env.USER_DATA_PATH) 81 + typeof wx !== 'undefined' && wx && wx.env && wx.env.USER_DATA_PATH
84 ? wx.env.USER_DATA_PATH 82 ? wx.env.USER_DATA_PATH
85 : '' 83 : ''
86 - const is_local_user_path = wx_user_data_path 84 + const is_local_user_path = wx_user_data_path ? new RegExp(wx_user_data_path).test(url) : false
87 - ? new RegExp(wx_user_data_path).test(url)
88 - : false
89 85
90 if (/^http/.test(url) && !is_local_user_path) { 86 if (/^http/.test(url) && !is_local_user_path) {
91 Taro.downloadFile({ 87 Taro.downloadFile({
92 url: mapHttpToHttps(url), 88 url: mapHttpToHttps(url),
93 - success: (res) => { 89 + success: res => {
94 if (res.statusCode === 200) { 90 if (res.statusCode === 200) {
95 resolve(res.tempFilePath) 91 resolve(res.tempFilePath)
96 } else { 92 } else {
...@@ -116,9 +112,9 @@ export function downImage(url) { ...@@ -116,9 +112,9 @@ export function downImage(url) {
116 export const getImageInfo = (item, index) => 112 export const getImageInfo = (item, index) =>
117 new Promise((resolve, reject) => { 113 new Promise((resolve, reject) => {
118 const { x, y, width, height, url, zIndex } = item 114 const { x, y, width, height, url, zIndex } = item
119 - downImage(url).then((imgPath) => 115 + downImage(url).then(imgPath =>
120 Taro.getImageInfo({ src: imgPath }) 116 Taro.getImageInfo({ src: imgPath })
121 - .then((imgInfo) => { 117 + .then(imgInfo => {
122 let sx 118 let sx
123 let sy 119 let sy
124 const borderRadius = item.borderRadius || 0 120 const borderRadius = item.borderRadius || 0
...@@ -150,7 +146,7 @@ export const getImageInfo = (item, index) => ...@@ -150,7 +146,7 @@ export const getImageInfo = (item, index) =>
150 } 146 }
151 resolve(result) 147 resolve(result)
152 }) 148 })
153 - .catch((err) => { 149 + .catch(err => {
154 reject(err) 150 reject(err)
155 }) 151 })
156 ) 152 )
......
1 <template> 1 <template>
2 <view class="index-nav" :class="[`is-${position}`]"> 2 <view class="index-nav" :class="[`is-${position}`]">
3 - <view class="nav-logo is-home" :class="{ 'is-active': active === 'home' }" @tap="() => on_select('home')"> 3 + <view
4 + class="nav-logo is-home"
5 + :class="{ 'is-active': active === 'home' }"
6 + @tap="() => on_select('home')"
7 + >
4 <view class="nav-icon-wrap"> 8 <view class="nav-icon-wrap">
5 <image class="nav-icon" :src="icons?.home" mode="aspectFit" /> 9 <image class="nav-icon" :src="icons?.home" mode="aspectFit" />
6 </view> 10 </view>
...@@ -9,7 +13,10 @@ ...@@ -9,7 +13,10 @@
9 13
10 <view 14 <view
11 class="nav-logo is-code" 15 class="nav-logo is-code"
12 - :class="[{ 'is-active': active === 'code' }, { 'is-center-raised': center_variant === 'raised' }]" 16 + :class="[
17 + { 'is-active': active === 'code' },
18 + { 'is-center-raised': center_variant === 'raised' }
19 + ]"
13 @tap="() => on_select('code')" 20 @tap="() => on_select('code')"
14 > 21 >
15 <view class="nav-icon-wrap"> 22 <view class="nav-icon-wrap">
...@@ -23,7 +30,11 @@ ...@@ -23,7 +30,11 @@
23 <text class="nav-text">预约码</text> 30 <text class="nav-text">预约码</text>
24 </view> 31 </view>
25 32
26 - <view class="nav-logo is-me" :class="{ 'is-active': active === 'me' }" @tap="() => on_select('me')"> 33 + <view
34 + class="nav-logo is-me"
35 + :class="{ 'is-active': active === 'me' }"
36 + @tap="() => on_select('me')"
37 + >
27 <view class="nav-icon-wrap"> 38 <view class="nav-icon-wrap">
28 <image class="nav-icon" :src="icons?.me" mode="aspectFit" /> 39 <image class="nav-icon" :src="icons?.me" mode="aspectFit" />
29 </view> 40 </view>
...@@ -58,8 +69,10 @@ const props = defineProps({ ...@@ -58,8 +69,10 @@ const props = defineProps({
58 69
59 const emit = defineEmits(['select']) 70 const emit = defineEmits(['select'])
60 71
61 -const on_select = (key) => { 72 +const on_select = key => {
62 - if (!props.allow_active_tap && props.active && key === props.active) return 73 + if (!props.allow_active_tap && props.active && key === props.active) {
74 + return
75 + }
63 emit('select', key) 76 emit('select', key)
64 } 77 }
65 </script> 78 </script>
...@@ -74,12 +87,12 @@ const on_select = (key) => { ...@@ -74,12 +87,12 @@ const on_select = (key) => {
74 padding-bottom: calc(0rpx + constant(safe-area-inset-bottom)); 87 padding-bottom: calc(0rpx + constant(safe-area-inset-bottom));
75 padding-bottom: calc(0rpx + env(safe-area-inset-bottom)); 88 padding-bottom: calc(0rpx + env(safe-area-inset-bottom));
76 box-sizing: border-box; 89 box-sizing: border-box;
77 - background: #FFFFFF; 90 + background: #ffffff;
78 box-shadow: 0 -8rpx 8rpx 0 rgba(0, 0, 0, 0.1); 91 box-shadow: 0 -8rpx 8rpx 0 rgba(0, 0, 0, 0.1);
79 display: flex; 92 display: flex;
80 align-items: flex-end; 93 align-items: flex-end;
81 justify-content: space-around; 94 justify-content: space-around;
82 - color: #A67939; 95 + color: #a67939;
83 z-index: 99; 96 z-index: 99;
84 97
85 &.is-fixed { 98 &.is-fixed {
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
16 <image :src="icon_2" /> 16 <image :src="icon_2" />
17 </view> 17 </view>
18 </view> 18 </view>
19 - <view style="color: red; margin-top: 32rpx;">{{ userinfo.datetime }}</view> 19 + <view style="color: red; margin-top: 32rpx">{{ userinfo.datetime }}</view>
20 - <view style="color: #999; font-size: 24rpx; margin-top: 10rpx;">(离线模式)</view> 20 + <view style="color: #999; font-size: 24rpx; margin-top: 10rpx">(离线模式)</view>
21 </view> 21 </view>
22 <view class="user-list"> 22 <view class="user-list">
23 <view 23 <view
...@@ -27,14 +27,15 @@ ...@@ -27,14 +27,15 @@
27 :class="[ 27 :class="[
28 'user-item', 28 'user-item',
29 select_index === index ? 'checked' : '', 29 select_index === index ? 'checked' : '',
30 - userList.length > 1 && item.sort ? 'border' : '', 30 + userList.length > 1 && item.sort ? 'border' : ''
31 - ]"> 31 + ]"
32 + >
32 {{ item.name }} 33 {{ item.name }}
33 </view> 34 </view>
34 </view> 35 </view>
35 </view> 36 </view>
36 <view v-else class="no-qrcode"> 37 <view v-else class="no-qrcode">
37 - <image :src="icon_3" style="width: 320rpx; height: 320rpx;" /> 38 + <image :src="icon_3" style="width: 320rpx; height: 320rpx" />
38 <view class="no-qrcode-title">本地无缓存预约记录</view> 39 <view class="no-qrcode-title">本地无缓存预约记录</view>
39 </view> 40 </view>
40 </view> 41 </view>
...@@ -54,52 +55,52 @@ const props = defineProps({ ...@@ -54,52 +55,52 @@ const props = defineProps({
54 type: Array, 55 type: Array,
55 default: () => [] 56 default: () => []
56 } 57 }
57 -}); 58 +})
58 59
59 -const select_index = ref(0); 60 +const select_index = ref(0)
60 -const userList = ref([]); 61 +const userList = ref([])
61 -const qrCodeImages = ref({}); // 存储生成的二维码图片 base64 62 +const qrCodeImages = ref({}) // 存储生成的二维码图片 base64
62 63
63 const prevCode = () => { 64 const prevCode = () => {
64 - select_index.value = select_index.value - 1; 65 + select_index.value = select_index.value - 1
65 if (select_index.value < 0) { 66 if (select_index.value < 0) {
66 - select_index.value = userList.value.length - 1; 67 + select_index.value = userList.value.length - 1
67 } 68 }
68 -}; 69 +}
69 const nextCode = () => { 70 const nextCode = () => {
70 - select_index.value = select_index.value + 1; 71 + select_index.value = select_index.value + 1
71 if (select_index.value > userList.value.length - 1) { 72 if (select_index.value > userList.value.length - 1) {
72 - select_index.value = 0; 73 + select_index.value = 0
73 } 74 }
74 -}; 75 +}
75 76
76 function replaceMiddleCharacters(inputString) { 77 function replaceMiddleCharacters(inputString) {
77 if (!inputString || inputString.length < 15) { 78 if (!inputString || inputString.length < 15) {
78 - return inputString; 79 + return inputString
79 } 80 }
80 - const start = Math.floor((inputString.length - 8) / 2); 81 + const start = Math.floor((inputString.length - 8) / 2)
81 - const end = start + 8; 82 + const end = start + 8
82 - const replacement = '*'.repeat(8); 83 + const replacement = '*'.repeat(8)
83 - return inputString.substring(0, start) + replacement + inputString.substring(end); 84 + return inputString.substring(0, start) + replacement + inputString.substring(end)
84 } 85 }
85 86
86 -const formatId = (id) => replaceMiddleCharacters(id); 87 +const formatId = id => replaceMiddleCharacters(id)
87 88
88 const userinfo = computed(() => { 89 const userinfo = computed(() => {
89 return { 90 return {
90 name: userList.value[select_index.value]?.name, 91 name: userList.value[select_index.value]?.name,
91 id: formatId(userList.value[select_index.value]?.id_number), 92 id: formatId(userList.value[select_index.value]?.id_number),
92 - datetime: userList.value[select_index.value]?.datetime, 93 + datetime: userList.value[select_index.value]?.datetime
93 - }; 94 + }
94 -}); 95 +})
95 96
96 const currentQrCodeUrl = computed(() => { 97 const currentQrCodeUrl = computed(() => {
97 - const key = userList.value[select_index.value]?.qr_code; 98 + const key = userList.value[select_index.value]?.qr_code
98 - return qrCodeImages.value[key] || ''; 99 + return qrCodeImages.value[key] || ''
99 }) 100 })
100 101
101 -const selectUser = (index) => { 102 +const selectUser = index => {
102 - select_index.value = index; 103 + select_index.value = index
103 } 104 }
104 105
105 const generateQrCodes = () => { 106 const generateQrCodes = () => {
...@@ -107,29 +108,29 @@ const generateQrCodes = () => { ...@@ -107,29 +108,29 @@ const generateQrCodes = () => {
107 if (item.qr_code && !qrCodeImages.value[item.qr_code]) { 108 if (item.qr_code && !qrCodeImages.value[item.qr_code]) {
108 try { 109 try {
109 // 使用 create + SVG 手动生成,避免 Taro 中 Canvas 依赖问题 110 // 使用 create + SVG 手动生成,避免 Taro 中 Canvas 依赖问题
110 - const qr = QRCode.create(item.qr_code, { errorCorrectionLevel: 'M' }); 111 + const qr = QRCode.create(item.qr_code, { errorCorrectionLevel: 'M' })
111 - const size = qr.modules.size; 112 + const size = qr.modules.size
112 - let d = ''; 113 + let d = ''
113 for (let row = 0; row < size; row++) { 114 for (let row = 0; row < size; row++) {
114 for (let col = 0; col < size; col++) { 115 for (let col = 0; col < size; col++) {
115 if (qr.modules.get(col, row)) { 116 if (qr.modules.get(col, row)) {
116 - d += `M${col},${row}h1v1h-1z`; 117 + d += `M${col},${row}h1v1h-1z`
117 } 118 }
118 } 119 }
119 } 120 }
120 - const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}"><path d="${d}" fill="#000"/></svg>`; 121 + const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}"><path d="${d}" fill="#000"/></svg>`
121 122
122 // 转 Base64 123 // 转 Base64
123 - const buffer = new ArrayBuffer(svg.length); 124 + const buffer = new ArrayBuffer(svg.length)
124 - const view = new Uint8Array(buffer); 125 + const view = new Uint8Array(buffer)
125 for (let i = 0; i < svg.length; i++) { 126 for (let i = 0; i < svg.length; i++) {
126 - view[i] = svg.charCodeAt(i); 127 + view[i] = svg.charCodeAt(i)
127 } 128 }
128 - const b64 = Taro.arrayBufferToBase64(buffer); 129 + const b64 = Taro.arrayBufferToBase64(buffer)
129 130
130 - qrCodeImages.value[item.qr_code] = `data:image/svg+xml;base64,${b64}`; 131 + qrCodeImages.value[item.qr_code] = `data:image/svg+xml;base64,${b64}`
131 } catch (err) { 132 } catch (err) {
132 - console.error('QR Gen Error', err); 133 + console.error('QR Gen Error', err)
133 } 134 }
134 } 135 }
135 } 136 }
...@@ -137,18 +138,21 @@ const generateQrCodes = () => { ...@@ -137,18 +138,21 @@ const generateQrCodes = () => {
137 138
138 onMounted(() => { 139 onMounted(() => {
139 if (props.list && props.list.length > 0) { 140 if (props.list && props.list.length > 0) {
140 - userList.value = props.list; 141 + userList.value = props.list
141 - generateQrCodes(); 142 + generateQrCodes()
142 } 143 }
143 -}); 144 +})
144 145
145 -watch(() => props.list, (newVal) => { 146 +watch(
147 + () => props.list,
148 + newVal => {
146 if (newVal && newVal.length > 0) { 149 if (newVal && newVal.length > 0) {
147 - userList.value = newVal; 150 + userList.value = newVal
148 - generateQrCodes(); 151 + generateQrCodes()
149 } 152 }
150 -}, { deep: true }); 153 + },
151 - 154 + { deep: true }
155 +)
152 </script> 156 </script>
153 157
154 <style lang="less"> 158 <style lang="less">
...@@ -159,12 +163,12 @@ watch(() => props.list, (newVal) => { ...@@ -159,12 +163,12 @@ watch(() => props.list, (newVal) => {
159 flex-direction: column; 163 flex-direction: column;
160 justify-content: center; 164 justify-content: center;
161 align-items: center; 165 align-items: center;
162 - background-color: #FFF; 166 + background-color: #fff;
163 border-radius: 16rpx; 167 border-radius: 16rpx;
164 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.27); 168 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.27);
165 169
166 .user-info { 170 .user-info {
167 - color: #A6A6A6; 171 + color: #a6a6a6;
168 font-size: 37rpx; 172 font-size: 37rpx;
169 margin-top: 16rpx; 173 margin-top: 16rpx;
170 margin-bottom: 16rpx; 174 margin-bottom: 16rpx;
...@@ -180,21 +184,25 @@ watch(() => props.list, (newVal) => { ...@@ -180,21 +184,25 @@ watch(() => props.list, (newVal) => {
180 align-items: center; 184 align-items: center;
181 .left { 185 .left {
182 image { 186 image {
183 - width: 56rpx; height: 56rpx; margin-right: 16rpx; 187 + width: 56rpx;
188 + height: 56rpx;
189 + margin-right: 16rpx;
184 } 190 }
185 } 191 }
186 .center { 192 .center {
187 - border: 2rpx solid #D1D1D1; 193 + border: 2rpx solid #d1d1d1;
188 border-radius: 40rpx; 194 border-radius: 40rpx;
189 padding: 46rpx; 195 padding: 46rpx;
190 position: relative; 196 position: relative;
191 image { 197 image {
192 - width: 400rpx; height: 400rpx; 198 + width: 400rpx;
199 + height: 400rpx;
193 } 200 }
194 } 201 }
195 .right { 202 .right {
196 image { 203 image {
197 - width: 56rpx; height: 56rpx; 204 + width: 56rpx;
205 + height: 56rpx;
198 margin-left: 16rpx; 206 margin-left: 16rpx;
199 } 207 }
200 } 208 }
...@@ -208,13 +216,13 @@ watch(() => props.list, (newVal) => { ...@@ -208,13 +216,13 @@ watch(() => props.list, (newVal) => {
208 .user-item { 216 .user-item {
209 position: relative; 217 position: relative;
210 padding: 8rpx 16rpx; 218 padding: 8rpx 16rpx;
211 - border: 2rpx solid #A67939; 219 + border: 2rpx solid #a67939;
212 margin: 8rpx; 220 margin: 8rpx;
213 border-radius: 10rpx; 221 border-radius: 10rpx;
214 - color: #A67939; 222 + color: #a67939;
215 &.checked { 223 &.checked {
216 - color: #FFF; 224 + color: #fff;
217 - background-color: #A67939; 225 + background-color: #a67939;
218 } 226 }
219 &.border { 227 &.border {
220 margin-right: 16rpx; 228 margin-right: 16rpx;
...@@ -224,7 +232,7 @@ watch(() => props.list, (newVal) => { ...@@ -224,7 +232,7 @@ watch(() => props.list, (newVal) => {
224 top: calc(50% - 16rpx); 232 top: calc(50% - 16rpx);
225 content: ''; 233 content: '';
226 height: 32rpx; 234 height: 32rpx;
227 - border-right: 2rpx solid #A67939; 235 + border-right: 2rpx solid #a67939;
228 } 236 }
229 } 237 }
230 } 238 }
...@@ -238,7 +246,7 @@ watch(() => props.list, (newVal) => { ...@@ -238,7 +246,7 @@ watch(() => props.list, (newVal) => {
238 margin-bottom: 32rpx; 246 margin-bottom: 32rpx;
239 247
240 .no-qrcode-title { 248 .no-qrcode-title {
241 - color: #A67939; 249 + color: #a67939;
242 font-size: 34rpx; 250 font-size: 34rpx;
243 } 251 }
244 } 252 }
......
This diff is collapsed. Click to expand it.
...@@ -16,7 +16,10 @@ ...@@ -16,7 +16,10 @@
16 </view> 16 </view>
17 <view class="center"> 17 <view class="center">
18 <image :src="userinfo.qr_code_url" mode="aspectFit" /> 18 <image :src="userinfo.qr_code_url" mode="aspectFit" />
19 - <view v-if="useStatus === STATUS_CODE.CANCELED || useStatus === STATUS_CODE.USED" class="qrcode-used"> 19 + <view
20 + v-if="useStatus === STATUS_CODE.CANCELED || useStatus === STATUS_CODE.USED"
21 + class="qrcode-used"
22 + >
20 <view class="overlay"></view> 23 <view class="overlay"></view>
21 <text class="status-text">二维码{{ qr_code_status[useStatus] }}</text> 24 <text class="status-text">二维码{{ qr_code_status[useStatus] }}</text>
22 </view> 25 </view>
...@@ -25,11 +28,14 @@ ...@@ -25,11 +28,14 @@
25 <!-- <image src="https://cdn.ipadbiz.cn/xys/booking/%E5%8F%B3@2x.png"> --> 28 <!-- <image src="https://cdn.ipadbiz.cn/xys/booking/%E5%8F%B3@2x.png"> -->
26 </view> 29 </view>
27 </view> 30 </view>
28 - <view style="color: red; margin-top: 32rpx;">{{ userinfo.datetime }}</view> 31 + <view style="color: red; margin-top: 32rpx">{{ userinfo.datetime }}</view>
29 </view> 32 </view>
30 </view> 33 </view>
31 <view v-else class="no-qrcode"> 34 <view v-else class="no-qrcode">
32 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png" style="width: 320rpx; height: 320rpx;" /> 35 + <image
36 + src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png"
37 + style="width: 320rpx; height: 320rpx"
38 + />
33 <view class="no-qrcode-title">您还没有预约过今天参观</view> 39 <view class="no-qrcode-title">您还没有预约过今天参观</view>
34 </view> 40 </view>
35 </view> 41 </view>
...@@ -37,9 +43,9 @@ ...@@ -37,9 +43,9 @@
37 43
38 <script setup> 44 <script setup>
39 import { ref, onMounted, watch, onUnmounted } from 'vue' 45 import { ref, onMounted, watch, onUnmounted } from 'vue'
40 -import { formatDatetime } from '@/utils/tools'; 46 +import { formatDatetime } from '@/utils/tools'
41 import { qrcodeStatusAPI, queryQrCodeAPI } from '@/api/index' 47 import { qrcodeStatusAPI, queryQrCodeAPI } from '@/api/index'
42 -import BASE_URL from '@/utils/config'; 48 +import BASE_URL from '@/utils/config'
43 49
44 const props = defineProps({ 50 const props = defineProps({
45 id: { 51 id: {
...@@ -50,42 +56,44 @@ const props = defineProps({ ...@@ -50,42 +56,44 @@ const props = defineProps({
50 type: Number, 56 type: Number,
51 default: 1 57 default: 1
52 } 58 }
53 -}); 59 +})
54 60
55 -const userinfo = ref({}); 61 +const userinfo = ref({})
56 62
57 -const replaceMiddleCharacters = (input_string) => { 63 +const replaceMiddleCharacters = input_string => {
58 if (!input_string || input_string.length < 15) { 64 if (!input_string || input_string.length < 15) {
59 - return input_string; 65 + return input_string
60 } 66 }
61 - const start = Math.floor((input_string.length - 8) / 2); 67 + const start = Math.floor((input_string.length - 8) / 2)
62 - const end = start + 8; 68 + const end = start + 8
63 - const replacement = '*'.repeat(8); 69 + const replacement = '*'.repeat(8)
64 - return input_string.substring(0, start) + replacement + input_string.substring(end); 70 + return input_string.substring(0, start) + replacement + input_string.substring(end)
65 } 71 }
66 72
67 -const formatId = (id) => replaceMiddleCharacters(id); 73 +const formatId = id => replaceMiddleCharacters(id)
68 74
69 -const useStatus = ref('0'); 75 +const useStatus = ref('0')
70 const is_loading = ref(false) 76 const is_loading = ref(false)
71 let is_destroyed = false 77 let is_destroyed = false
72 78
73 const qr_code_status = { 79 const qr_code_status = {
74 - '1': '未激活', 80 + 1: '未激活',
75 - '3': '待使用', 81 + 3: '待使用',
76 - '5': '被取消', 82 + 5: '被取消',
77 - '7': '已使用', 83 + 7: '已使用'
78 -}; 84 +}
79 85
80 const STATUS_CODE = { 86 const STATUS_CODE = {
81 APPLY: '1', 87 APPLY: '1',
82 SUCCESS: '3', 88 SUCCESS: '3',
83 CANCELED: '5', 89 CANCELED: '5',
84 - USED: '7', 90 + USED: '7'
85 -}; 91 +}
86 92
87 -const build_qr_code_url = (qr_code) => { 93 +const build_qr_code_url = qr_code => {
88 - if (!qr_code) return '' 94 + if (!qr_code) {
95 + return ''
96 + }
89 return `${BASE_URL}/admin?m=srv&a=get_qrcode&key=${encodeURIComponent(String(qr_code))}` 97 return `${BASE_URL}/admin?m=srv&a=get_qrcode&key=${encodeURIComponent(String(qr_code))}`
90 } 98 }
91 99
...@@ -95,8 +103,10 @@ const build_qr_code_url = (qr_code) => { ...@@ -95,8 +103,10 @@ const build_qr_code_url = (qr_code) => {
95 * @return {*} 格式化后的数据 103 * @return {*} 格式化后的数据
96 */ 104 */
97 105
98 -const normalize_item = (raw) => { 106 +const normalize_item = raw => {
99 - if (!raw || typeof raw !== 'object') return null 107 + if (!raw || typeof raw !== 'object') {
108 + return null
109 + }
100 const qr_code = raw.qr_code ? String(raw.qr_code) : '' 110 const qr_code = raw.qr_code ? String(raw.qr_code) : ''
101 const id_number = raw.id_number ? String(raw.id_number) : '' 111 const id_number = raw.id_number ? String(raw.id_number) : ''
102 return { 112 return {
...@@ -104,7 +114,7 @@ const normalize_item = (raw) => { ...@@ -104,7 +114,7 @@ const normalize_item = (raw) => {
104 qr_code, 114 qr_code,
105 qr_code_url: build_qr_code_url(qr_code), 115 qr_code_url: build_qr_code_url(qr_code),
106 datetime: formatDatetime({ begin_time: raw.begin_time, end_time: raw.end_time }), 116 datetime: formatDatetime({ begin_time: raw.begin_time, end_time: raw.end_time }),
107 - id: formatId(id_number), 117 + id: formatId(id_number)
108 } 118 }
109 } 119 }
110 120
...@@ -123,13 +133,21 @@ const reset_state = () => { ...@@ -123,13 +133,21 @@ const reset_state = () => {
123 * @return {*} 状态码 133 * @return {*} 状态码
124 */ 134 */
125 135
126 -const load_qr_code_status = async (qr_code) => { 136 +const load_qr_code_status = async qr_code => {
127 - if (!qr_code) return 137 + if (!qr_code) {
138 + return
139 + }
128 const res = await qrcodeStatusAPI({ qr_code }) 140 const res = await qrcodeStatusAPI({ qr_code })
129 - if (is_destroyed) return 141 + if (is_destroyed) {
130 - if (!res || res.code !== 1) return 142 + return
143 + }
144 + if (!res || res.code !== 1) {
145 + return
146 + }
131 const status = res?.data?.status 147 const status = res?.data?.status
132 - if (status === undefined || status === null) return 148 + if (status === undefined || status === null) {
149 + return
150 + }
133 useStatus.value = String(status) 151 useStatus.value = String(status)
134 } 152 }
135 153
...@@ -139,7 +157,7 @@ const load_qr_code_status = async (qr_code) => { ...@@ -139,7 +157,7 @@ const load_qr_code_status = async (qr_code) => {
139 * @return {*} 预约码卡信息 157 * @return {*} 预约码卡信息
140 */ 158 */
141 159
142 -const load_qr_code_info = async (id_number) => { 160 +const load_qr_code_info = async id_number => {
143 const id = String(id_number || '').trim() 161 const id = String(id_number || '').trim()
144 if (!id) { 162 if (!id) {
145 reset_state() 163 reset_state()
...@@ -148,9 +166,13 @@ const load_qr_code_info = async (id_number) => { ...@@ -148,9 +166,13 @@ const load_qr_code_info = async (id_number) => {
148 166
149 is_loading.value = true 167 is_loading.value = true
150 const params = { id_number: id } 168 const params = { id_number: id }
151 - if (props.id_type) params.id_type = props.id_type 169 + if (props.id_type) {
170 + params.id_type = props.id_type
171 + }
152 const res = await queryQrCodeAPI(params) 172 const res = await queryQrCodeAPI(params)
153 - if (is_destroyed) return 173 + if (is_destroyed) {
174 + return
175 + }
154 is_loading.value = false 176 is_loading.value = false
155 177
156 if (!res || res.code !== 1 || !res.data) { 178 if (!res || res.code !== 1 || !res.data) {
...@@ -180,7 +202,9 @@ onMounted(() => { ...@@ -180,7 +202,9 @@ onMounted(() => {
180 watch( 202 watch(
181 () => [props.id, props.id_type], 203 () => [props.id, props.id_type],
182 ([val]) => { 204 ([val]) => {
183 - if (is_loading.value) return 205 + if (is_loading.value) {
206 + return
207 + }
184 load_qr_code_info(val) 208 load_qr_code_info(val)
185 } 209 }
186 ) 210 )
...@@ -194,12 +218,12 @@ watch( ...@@ -194,12 +218,12 @@ watch(
194 flex-direction: column; 218 flex-direction: column;
195 justify-content: center; 219 justify-content: center;
196 align-items: center; 220 align-items: center;
197 - background-color: #FFF; 221 + background-color: #fff;
198 border-radius: 16rpx; 222 border-radius: 16rpx;
199 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.27); 223 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.27);
200 224
201 .user-info { 225 .user-info {
202 - color: #A6A6A6; 226 + color: #a6a6a6;
203 font-size: 37rpx; 227 font-size: 37rpx;
204 margin-top: 16rpx; 228 margin-top: 16rpx;
205 margin-bottom: 16rpx; 229 margin-bottom: 16rpx;
...@@ -208,12 +232,13 @@ watch( ...@@ -208,12 +232,13 @@ watch(
208 display: flex; 232 display: flex;
209 align-items: center; 233 align-items: center;
210 .center { 234 .center {
211 - border: 2rpx solid #D1D1D1; 235 + border: 2rpx solid #d1d1d1;
212 border-radius: 40rpx; 236 border-radius: 40rpx;
213 padding: 16rpx; 237 padding: 16rpx;
214 position: relative; 238 position: relative;
215 image { 239 image {
216 - width: 480rpx; height: 480rpx; 240 + width: 480rpx;
241 + height: 480rpx;
217 } 242 }
218 .qrcode-used { 243 .qrcode-used {
219 position: absolute; 244 position: absolute;
...@@ -233,7 +258,7 @@ watch( ...@@ -233,7 +258,7 @@ watch(
233 } 258 }
234 259
235 .status-text { 260 .status-text {
236 - color: #A67939; 261 + color: #a67939;
237 position: absolute; 262 position: absolute;
238 top: 50%; 263 top: 50%;
239 left: 50%; 264 left: 50%;
...@@ -256,7 +281,7 @@ watch( ...@@ -256,7 +281,7 @@ watch(
256 margin-bottom: 32rpx; 281 margin-bottom: 32rpx;
257 282
258 .no-qrcode-title { 283 .no-qrcode-title {
259 - color: #A67939; 284 + color: #a67939;
260 font-size: 34rpx; 285 font-size: 34rpx;
261 } 286 }
262 } 287 }
......
...@@ -14,13 +14,27 @@ ...@@ -14,13 +14,27 @@
14 </view> 14 </view>
15 <view class="booking-list-item-body"> 15 <view class="booking-list-item-body">
16 <view class="booking-num"> 16 <view class="booking-num">
17 - <view class="num-body van-ellipsis">预约人数:<text>{{ reserve_info.total_qty }} 人</text>&nbsp;<text>({{ reserve_info.person_name }})</text></view> 17 + <view class="num-body van-ellipsis"
18 - <view v-if="(reserve_info.status === CodeStatus.SUCCESS || reserve_info.status === CodeStatus.USED || reserve_info.status === CodeStatus.CANCEL)"> 18 + >预约人数:<text>{{ reserve_info.total_qty }} 人</text>&nbsp;<text
19 + >({{ reserve_info.person_name }})</text
20 + ></view
21 + >
22 + <view
23 + v-if="
24 + reserve_info.status === CodeStatus.SUCCESS ||
25 + reserve_info.status === CodeStatus.USED ||
26 + reserve_info.status === CodeStatus.CANCEL
27 + "
28 + >
19 <IconFont name="rect-right" /> 29 <IconFont name="rect-right" />
20 </view> 30 </view>
21 </view> 31 </view>
22 - <view class="booking-price">支付金额:<text>¥ {{ reserve_info.total_amt }}</text></view> 32 + <view class="booking-price"
23 - <view class="booking-time">下单时间:<text>{{ reserve_info.order_time }}</text></view> 33 + >支付金额:<text>¥ {{ reserve_info.total_amt }}</text></view
34 + >
35 + <view class="booking-time"
36 + >下单时间:<text>{{ reserve_info.order_time }}</text></view
37 + >
24 </view> 38 </view>
25 <view v-if="is_pay_pending" class="booking-list-item-footer" @tap.stop> 39 <view v-if="is_pay_pending" class="booking-list-item-footer" @tap.stop>
26 <view v-if="countdown_seconds > 0" class="countdown">剩余支付时间:{{ countdown_text }}</view> 40 <view v-if="countdown_seconds > 0" class="countdown">剩余支付时间:{{ countdown_text }}</view>
...@@ -37,26 +51,26 @@ import { IconFont } from '@nutui/icons-vue-taro' ...@@ -37,26 +51,26 @@ import { IconFont } from '@nutui/icons-vue-taro'
37 import { useGo } from '@/hooks/useGo' 51 import { useGo } from '@/hooks/useGo'
38 import { wechat_pay } from '@/utils/wechatPay' 52 import { wechat_pay } from '@/utils/wechatPay'
39 53
40 -const go = useGo(); 54 +const go = useGo()
41 55
42 const props = defineProps({ 56 const props = defineProps({
43 data: { 57 data: {
44 type: Object, 58 type: Object,
45 - default: () => ({}), 59 + default: () => ({})
46 }, 60 },
47 detail_path: { 61 detail_path: {
48 type: String, 62 type: String,
49 - default: '/bookingDetail', 63 + default: '/bookingDetail'
50 }, 64 },
51 is_offline: { 65 is_offline: {
52 type: Boolean, 66 type: Boolean,
53 - default: false, 67 + default: false
54 - }, 68 + }
55 -}); 69 +})
56 70
57 -const reserve_info = computed(() => props.data); 71 +const reserve_info = computed(() => props.data)
58 72
59 -const is_offline = computed(() => props.is_offline); 73 +const is_offline = computed(() => props.is_offline)
60 74
61 /** 75 /**
62 * @description 预约码状态枚举(与后端约定) 76 * @description 预约码状态枚举(与后端约定)
...@@ -78,7 +92,9 @@ const CodeStatus = { ...@@ -78,7 +92,9 @@ const CodeStatus = {
78 */ 92 */
79 93
80 const is_pay_pending = computed(() => { 94 const is_pay_pending = computed(() => {
81 - if (is_offline.value) return false 95 + if (is_offline.value) {
96 + return false
97 + }
82 return reserve_info.value?.status === CodeStatus.APPLY && !!reserve_info.value?.pay_id 98 return reserve_info.value?.status === CodeStatus.APPLY && !!reserve_info.value?.pay_id
83 }) 99 })
84 100
...@@ -89,7 +105,7 @@ const countdown_seconds = ref(0) ...@@ -89,7 +105,7 @@ const countdown_seconds = ref(0)
89 * @param {number|string} n 数字 105 * @param {number|string} n 数字
90 * @returns {string} 两位字符串 106 * @returns {string} 两位字符串
91 */ 107 */
92 -const format_two_digits = (n) => { 108 +const format_two_digits = n => {
93 const num = Number(n) || 0 109 const num = Number(n) || 0
94 return num < 10 ? `0${num}` : String(num) 110 return num < 10 ? `0${num}` : String(num)
95 } 111 }
...@@ -106,9 +122,11 @@ const countdown_text = computed(() => { ...@@ -106,9 +122,11 @@ const countdown_text = computed(() => {
106 * @param {string} created_time 创建时间字符串 122 * @param {string} created_time 创建时间字符串
107 * @returns {number} 毫秒时间戳;解析失败返回 0 123 * @returns {number} 毫秒时间戳;解析失败返回 0
108 */ 124 */
109 -const parse_created_time_ms = (created_time) => { 125 +const parse_created_time_ms = created_time => {
110 const raw = String(created_time || '') 126 const raw = String(created_time || '')
111 - if (!raw) return 0 127 + if (!raw) {
128 + return 0
129 + }
112 const fixed = raw.replace(/-/g, '/') 130 const fixed = raw.replace(/-/g, '/')
113 const date = new Date(fixed) 131 const date = new Date(fixed)
114 const time = date.getTime() 132 const time = date.getTime()
...@@ -157,7 +175,9 @@ const update_countdown = () => { ...@@ -157,7 +175,9 @@ const update_countdown = () => {
157 const start_countdown = () => { 175 const start_countdown = () => {
158 stop_countdown() 176 stop_countdown()
159 update_countdown() 177 update_countdown()
160 - if (countdown_seconds.value <= 0) return 178 + if (countdown_seconds.value <= 0) {
179 + return
180 + }
161 countdown_timer = setInterval(update_countdown, 1000) 181 countdown_timer = setInterval(update_countdown, 1000)
162 } 182 }
163 183
...@@ -167,8 +187,10 @@ let is_showing_pay_modal = false ...@@ -167,8 +187,10 @@ let is_showing_pay_modal = false
167 * @param {string} content 弹窗内容 187 * @param {string} content 弹窗内容
168 * @returns {Promise<boolean>} true=继续支付,false=取消 188 * @returns {Promise<boolean>} true=继续支付,false=取消
169 */ 189 */
170 -const show_pay_modal = async (content) => { 190 +const show_pay_modal = async content => {
171 - if (is_showing_pay_modal) return false 191 + if (is_showing_pay_modal) {
192 + return false
193 + }
172 is_showing_pay_modal = true 194 is_showing_pay_modal = true
173 try { 195 try {
174 const res = await Taro.showModal({ 196 const res = await Taro.showModal({
...@@ -176,7 +198,7 @@ const show_pay_modal = async (content) => { ...@@ -176,7 +198,7 @@ const show_pay_modal = async (content) => {
176 content: content || '支付未完成', 198 content: content || '支付未完成',
177 showCancel: true, 199 showCancel: true,
178 cancelText: '取消', 200 cancelText: '取消',
179 - confirmText: '继续支付', 201 + confirmText: '继续支付'
180 }) 202 })
181 return !!res?.confirm 203 return !!res?.confirm
182 } finally { 204 } finally {
...@@ -190,7 +212,9 @@ const show_pay_modal = async (content) => { ...@@ -190,7 +212,9 @@ const show_pay_modal = async (content) => {
190 */ 212 */
191 213
192 const onRepay = async () => { 214 const onRepay = async () => {
193 - if (!is_pay_pending.value) return 215 + if (!is_pay_pending.value) {
216 + return
217 + }
194 if (countdown_seconds.value <= 0) { 218 if (countdown_seconds.value <= 0) {
195 Taro.showToast({ title: '支付已超时', icon: 'none' }) 219 Taro.showToast({ title: '支付已超时', icon: 'none' })
196 return 220 return
...@@ -213,7 +237,7 @@ const onRepay = async () => { ...@@ -213,7 +237,7 @@ const onRepay = async () => {
213 * @param {string} status 订单状态码 237 * @param {string} status 订单状态码
214 * @returns {{key:string,value:string}} 展示状态(key 用于 class) 238 * @returns {{key:string,value:string}} 展示状态(key 用于 class)
215 */ 239 */
216 -const formatStatus = (status) => { 240 +const formatStatus = status => {
217 switch (status) { 241 switch (status) {
218 case CodeStatus.APPLY: 242 case CodeStatus.APPLY:
219 return { 243 return {
...@@ -265,10 +289,14 @@ const status_info = computed(() => { ...@@ -265,10 +289,14 @@ const status_info = computed(() => {
265 * @param {Object} item 预约记录 289 * @param {Object} item 预约记录
266 * @returns {void} 无返回值 290 * @returns {void} 无返回值
267 */ 291 */
268 -const goToDetail = (item) => { 292 +const goToDetail = item => {
269 // 只有成功、已使用、已取消(退款成功)才跳转详情 293 // 只有成功、已使用、已取消(退款成功)才跳转详情
270 - if (item.status === CodeStatus.SUCCESS || item.status === CodeStatus.USED || item.status === CodeStatus.CANCEL) { 294 + if (
271 - go(props.detail_path, { pay_id: item.pay_id }); 295 + item.status === CodeStatus.SUCCESS ||
296 + item.status === CodeStatus.USED ||
297 + item.status === CodeStatus.CANCEL
298 + ) {
299 + go(props.detail_path, { pay_id: item.pay_id })
272 } 300 }
273 } 301 }
274 302
...@@ -278,14 +306,18 @@ const goToDetail = (item) => { ...@@ -278,14 +306,18 @@ const goToDetail = (item) => {
278 * - 退出待支付:清空倒计时 306 * - 退出待支付:清空倒计时
279 */ 307 */
280 308
281 -watch(is_pay_pending, (val) => { 309 +watch(
310 + is_pay_pending,
311 + val => {
282 if (val) { 312 if (val) {
283 start_countdown() 313 start_countdown()
284 } else { 314 } else {
285 countdown_seconds.value = 0 315 countdown_seconds.value = 0
286 stop_countdown() 316 stop_countdown()
287 } 317 }
288 -}, { immediate: true }) 318 + },
319 + { immediate: true }
320 +)
289 321
290 onUnmounted(() => { 322 onUnmounted(() => {
291 stop_countdown() 323 stop_countdown()
...@@ -294,18 +326,18 @@ onUnmounted(() => { ...@@ -294,18 +326,18 @@ onUnmounted(() => {
294 326
295 <style lang="less"> 327 <style lang="less">
296 .booking-list-item { 328 .booking-list-item {
297 - background-color: #FFF; 329 + background-color: #fff;
298 border-radius: 16rpx; 330 border-radius: 16rpx;
299 padding: 32rpx; 331 padding: 32rpx;
300 margin-bottom: 32rpx; 332 margin-bottom: 32rpx;
301 - box-shadow: 0 0 30rpx 0 rgba(106,106,106,0.1); 333 + box-shadow: 0 0 30rpx 0 rgba(106, 106, 106, 0.1);
302 334
303 .booking-list-item-header { 335 .booking-list-item-header {
304 display: flex; 336 display: flex;
305 justify-content: space-between; 337 justify-content: space-between;
306 align-items: center; 338 align-items: center;
307 padding-bottom: 16rpx; 339 padding-bottom: 16rpx;
308 - border-bottom: 2rpx dashed #E6E6E6; 340 + border-bottom: 2rpx dashed #e6e6e6;
309 margin-bottom: 16rpx; 341 margin-bottom: 16rpx;
310 font-size: 32rpx; 342 font-size: 32rpx;
311 font-weight: bold; 343 font-weight: bold;
...@@ -319,20 +351,20 @@ onUnmounted(() => { ...@@ -319,20 +351,20 @@ onUnmounted(() => {
319 351
320 &.offline { 352 &.offline {
321 color: #999; 353 color: #999;
322 - background-color: #EEE; 354 + background-color: #eee;
323 } 355 }
324 356
325 &.success { 357 &.success {
326 - color: #A67939; 358 + color: #a67939;
327 - background-color: #FBEEDC; 359 + background-color: #fbeedc;
328 } 360 }
329 &.cancel { 361 &.cancel {
330 color: #999; 362 color: #999;
331 - background-color: #EEE; 363 + background-color: #eee;
332 } 364 }
333 &.used { 365 &.used {
334 - color: #477F3D; 366 + color: #477f3d;
335 - background-color: #E5EFE3; 367 + background-color: #e5efe3;
336 } 368 }
337 } 369 }
338 } 370 }
...@@ -346,13 +378,15 @@ onUnmounted(() => { ...@@ -346,13 +378,15 @@ onUnmounted(() => {
346 color: #666; 378 color: #666;
347 379
348 .num-body { 380 .num-body {
349 - span, text { 381 + span,
350 - color: #A67939; 382 + text {
383 + color: #a67939;
351 font-weight: bold; 384 font-weight: bold;
352 } 385 }
353 } 386 }
354 } 387 }
355 - .booking-price, .booking-time { 388 + .booking-price,
389 + .booking-time {
356 color: #999; 390 color: #999;
357 font-size: 29rpx; 391 font-size: 29rpx;
358 margin-bottom: 10rpx; 392 margin-bottom: 10rpx;
...@@ -369,7 +403,7 @@ onUnmounted(() => { ...@@ -369,7 +403,7 @@ onUnmounted(() => {
369 margin-top: 16rpx; 403 margin-top: 16rpx;
370 404
371 .countdown { 405 .countdown {
372 - color: #A67939; 406 + color: #a67939;
373 font-size: 28rpx; 407 font-size: 28rpx;
374 408
375 &.timeout { 409 &.timeout {
...@@ -380,8 +414,8 @@ onUnmounted(() => { ...@@ -380,8 +414,8 @@ onUnmounted(() => {
380 .repay-btn { 414 .repay-btn {
381 padding: 8rpx 20rpx; 415 padding: 8rpx 20rpx;
382 border-radius: 12rpx; 416 border-radius: 12rpx;
383 - background-color: #A67939; 417 + background-color: #a67939;
384 - color: #FFF; 418 + color: #fff;
385 font-size: 28rpx; 419 font-size: 28rpx;
386 } 420 }
387 } 421 }
......
1 -var getDaysInOneMonth = function (year, month) { 1 +const getDaysInOneMonth = function (year, month) {
2 - let _month = parseInt(month, 10); 2 + const _month = parseInt(month, 10)
3 - let d = new Date(year, _month, 0); 3 + const d = new Date(year, _month, 0)
4 - return d.getDate(); 4 + return d.getDate()
5 } 5 }
6 -var dateDate = function (date) { 6 +const dateDate = function (date) {
7 - let year = date && date.getFullYear(); 7 + const year = date && date.getFullYear()
8 - let month = date && date.getMonth() + 1; 8 + const month = date && date.getMonth() + 1
9 - let day = date && date.getDate(); 9 + const day = date && date.getDate()
10 - let hours = date && date.getHours(); 10 + const hours = date && date.getHours()
11 - let minutes = date && date.getMinutes(); 11 + const minutes = date && date.getMinutes()
12 return { 12 return {
13 - year, month, day, hours, minutes 13 + year,
14 + month,
15 + day,
16 + hours,
17 + minutes
14 } 18 }
15 } 19 }
16 -var dateTimePicker = function (startyear, endyear) { 20 +const dateTimePicker = function (startyear, endyear) {
17 // 获取date time 年份,月份,天数,小时,分钟推后30分 21 // 获取date time 年份,月份,天数,小时,分钟推后30分
18 - const years = []; 22 + const years = []
19 - const months = []; 23 + const months = []
20 - const hours = []; 24 + const hours = []
21 - const minutes = []; 25 + const minutes = []
22 for (let i = startyear; i <= endyear; i++) { 26 for (let i = startyear; i <= endyear; i++) {
23 years.push({ 27 years.push({
24 - name: i + '年', 28 + name: `${i}年`,
25 id: i 29 id: i
26 - }); 30 + })
27 } 31 }
28 //获取月份 32 //获取月份
29 for (let i = 1; i <= 12; i++) { 33 for (let i = 1; i <= 12; i++) {
30 if (i < 10) { 34 if (i < 10) {
31 - i = "0" + i; 35 + i = `0${i}`
32 } 36 }
33 months.push({ 37 months.push({
34 - name: i + '月', 38 + name: `${i}月`,
35 id: i 39 id: i
36 - }); 40 + })
37 } 41 }
38 //获取小时 42 //获取小时
39 for (let i = 0; i < 24; i++) { 43 for (let i = 0; i < 24; i++) {
40 if (i < 10) { 44 if (i < 10) {
41 - i = "0" + i; 45 + i = `0${i}`
42 } 46 }
43 hours.push({ 47 hours.push({
44 - name: i + '时', 48 + name: `${i}时`,
45 id: i 49 id: i
46 - }); 50 + })
47 } 51 }
48 //获取分钟 52 //获取分钟
49 for (let i = 0; i < 60; i++) { 53 for (let i = 0; i < 60; i++) {
50 if (i < 10) { 54 if (i < 10) {
51 - i = "0" + i; 55 + i = `0${i}`
52 } 56 }
53 minutes.push({ 57 minutes.push({
54 - name: i + '分', 58 + name: `${i}分`,
55 id: i 59 id: i
56 - }); 60 + })
57 } 61 }
58 return function (_year, _month) { 62 return function (_year, _month) {
59 - const days = []; 63 + const days = []
60 - _year = parseInt(_year); 64 + _year = parseInt(_year)
61 - _month = parseInt(_month); 65 + _month = parseInt(_month)
62 //获取日期 66 //获取日期
63 for (let i = 1; i <= getDaysInOneMonth(_year, _month); i++) { 67 for (let i = 1; i <= getDaysInOneMonth(_year, _month); i++) {
64 if (i < 10) { 68 if (i < 10) {
65 - i = "0" + i; 69 + i = `0${i}`
66 } 70 }
67 days.push({ 71 days.push({
68 - name: i + '日', 72 + name: `${i}日`,
69 id: i 73 id: i
70 - }); 74 + })
71 } 75 }
72 - return [years, months, days, hours, minutes]; 76 + return [years, months, days, hours, minutes]
73 } 77 }
74 } 78 }
75 -export { 79 +export { dateTimePicker, getDaysInOneMonth, dateDate }
76 - dateTimePicker,
77 - getDaysInOneMonth,
78 - dateDate
79 -}
......
This diff is collapsed. Click to expand it.
...@@ -22,8 +22,10 @@ let refresh_promise = null ...@@ -22,8 +22,10 @@ let refresh_promise = null
22 * @param {Object} bill 原始预约记录 22 * @param {Object} bill 原始预约记录
23 * @returns {Object} 扁平化后的预约记录对象 23 * @returns {Object} 扁平化后的预约记录对象
24 */ 24 */
25 -const extract_bill_payload = (bill) => { 25 +const extract_bill_payload = bill => {
26 - if (!bill) return {} 26 + if (!bill) {
27 + return {}
28 + }
27 29
28 const data = { ...bill } 30 const data = { ...bill }
29 const list = data.list 31 const list = data.list
...@@ -42,8 +44,10 @@ const extract_bill_payload = (bill) => { ...@@ -42,8 +44,10 @@ const extract_bill_payload = (bill) => {
42 * @param {Object} bill 预约记录 44 * @param {Object} bill 预约记录
43 * @returns {Array} 人员列表 45 * @returns {Array} 人员列表
44 */ 46 */
45 -const extract_person_list = (bill) => { 47 +const extract_person_list = bill => {
46 - if (!bill) return [] 48 + if (!bill) {
49 + return []
50 + }
47 51
48 /** 52 /**
49 * 从预约记录中提取人员列表 53 * 从预约记录中提取人员列表
...@@ -69,7 +73,7 @@ const extract_person_list = (bill) => { ...@@ -69,7 +73,7 @@ const extract_person_list = (bill) => {
69 * @param {Object} item 原始预约记录项 73 * @param {Object} item 原始预约记录项
70 * @returns {Object} 格式化后的预约记录项 74 * @returns {Object} 格式化后的预约记录项
71 */ 75 */
72 -const normalize_bill_item = (item) => { 76 +const normalize_bill_item = item => {
73 const data = extract_bill_payload(item) 77 const data = extract_bill_payload(item)
74 78
75 data.datetime = data.datetime || formatDatetime(data) 79 data.datetime = data.datetime || formatDatetime(data)
...@@ -80,7 +84,9 @@ const normalize_bill_item = (item) => { ...@@ -80,7 +84,9 @@ const normalize_bill_item = (item) => {
80 const person_list = extract_person_list(item) 84 const person_list = extract_person_list(item)
81 const first = person_list[0] 85 const first = person_list[0]
82 const name = first?.name || first?.person_name 86 const name = first?.name || first?.person_name
83 - if (name) data.person_name = name 87 + if (name) {
88 + data.person_name = name
89 + }
84 } 90 }
85 91
86 return data 92 return data
...@@ -113,10 +119,10 @@ export const has_offline_booking_cache = () => { ...@@ -113,10 +119,10 @@ export const has_offline_booking_cache = () => {
113 * @param {*} pay_id 支付ID 119 * @param {*} pay_id 支付ID
114 * @returns {Object|null} 匹配的预约记录项或 null 120 * @returns {Object|null} 匹配的预约记录项或 null
115 */ 121 */
116 -export const get_offline_booking_by_pay_id = (pay_id) => { 122 +export const get_offline_booking_by_pay_id = pay_id => {
117 const list = get_offline_booking_cache() 123 const list = get_offline_booking_cache()
118 const target_pay_id = String(pay_id || '') 124 const target_pay_id = String(pay_id || '')
119 - return list.find((item) => String(item?.pay_id || '') === target_pay_id) || null 125 + return list.find(item => String(item?.pay_id || '') === target_pay_id) || null
120 } 126 }
121 127
122 /** 128 /**
...@@ -124,7 +130,7 @@ export const get_offline_booking_by_pay_id = (pay_id) => { ...@@ -124,7 +130,7 @@ export const get_offline_booking_by_pay_id = (pay_id) => {
124 * @param {Object} bill - 预约记录项 130 * @param {Object} bill - 预约记录项
125 * @returns {Array} 人员列表(包含姓名、身份证号、二维码等信息) 131 * @returns {Array} 人员列表(包含姓名、身份证号、二维码等信息)
126 */ 132 */
127 -export const get_offline_bill_person_list = (bill) => { 133 +export const get_offline_bill_person_list = bill => {
128 return extract_person_list(bill) 134 return extract_person_list(bill)
129 } 135 }
130 136
...@@ -133,13 +139,18 @@ export const get_offline_bill_person_list = (bill) => { ...@@ -133,13 +139,18 @@ export const get_offline_bill_person_list = (bill) => {
133 * @param {Object} bill - 预约记录项 139 * @param {Object} bill - 预约记录项
134 * @returns {Array} 二维码列表(包含姓名、身份证号、二维码、预约时间等信息) 140 * @returns {Array} 二维码列表(包含姓名、身份证号、二维码、预约时间等信息)
135 */ 141 */
136 -export const build_offline_qr_list = (bill) => { 142 +export const build_offline_qr_list = bill => {
137 const list = get_offline_bill_person_list(bill) 143 const list = get_offline_bill_person_list(bill)
138 const datetime = bill?.datetime || formatDatetime(bill || {}) 144 const datetime = bill?.datetime || formatDatetime(bill || {})
139 145
140 return list 146 return list
141 - .filter((item) => item && (item.qr_code || item.qrcode || item.qrCode) && (item.qr_code || item.qrcode || item.qrCode) !== '') 147 + .filter(
142 - .map((item) => { 148 + item =>
149 + item &&
150 + (item.qr_code || item.qrcode || item.qrCode) &&
151 + (item.qr_code || item.qrcode || item.qrCode) !== ''
152 + )
153 + .map(item => {
143 const begin_time = item.begin_time || bill?.begin_time 154 const begin_time = item.begin_time || bill?.begin_time
144 const end_time = item.end_time || bill?.end_time 155 const end_time = item.end_time || bill?.end_time
145 const qr_code = item.qr_code || item.qrcode || item.qrCode 156 const qr_code = item.qr_code || item.qrcode || item.qrCode
...@@ -151,9 +162,11 @@ export const build_offline_qr_list = (bill) => { ...@@ -151,9 +162,11 @@ export const build_offline_qr_list = (bill) => {
151 qr_code, 162 qr_code,
152 begin_time, 163 begin_time,
153 end_time, 164 end_time,
154 - datetime: item.datetime || (begin_time && end_time ? formatDatetime({ begin_time, end_time }) : datetime), 165 + datetime:
166 + item.datetime ||
167 + (begin_time && end_time ? formatDatetime({ begin_time, end_time }) : datetime),
155 pay_id: bill?.pay_id, 168 pay_id: bill?.pay_id,
156 - sort: 0, 169 + sort: 0
157 } 170 }
158 }) 171 })
159 } 172 }
...@@ -175,9 +188,13 @@ export const refresh_offline_booking_cache = async ({ force = false } = {}) => { ...@@ -175,9 +188,13 @@ export const refresh_offline_booking_cache = async ({ force = false } = {}) => {
175 // 4. 刷新完成后,将结果存储到本地缓存(key: OFFLINE_BOOKING_CACHE_KEY) 188 // 4. 刷新完成后,将结果存储到本地缓存(key: OFFLINE_BOOKING_CACHE_KEY)
176 // 5. 返回刷新结果 Promise 189 // 5. 返回刷新结果 Promise
177 190
178 - if (!hasAuth()) return { code: 0, data: null, msg: '未授权' } 191 + if (!hasAuth()) {
192 + return { code: 0, data: null, msg: '未授权' }
193 + }
179 194
180 - if (refresh_promise && !force) return refresh_promise 195 + if (refresh_promise && !force) {
196 + return refresh_promise
197 + }
181 198
182 // 核心逻辑: 199 // 核心逻辑:
183 // 1. 立刻触发异步逻辑,同时捕获 Promise 状态 200 // 1. 立刻触发异步逻辑,同时捕获 Promise 状态
...@@ -193,7 +210,9 @@ export const refresh_offline_booking_cache = async ({ force = false } = {}) => { ...@@ -193,7 +210,9 @@ export const refresh_offline_booking_cache = async ({ force = false } = {}) => {
193 const { code, data, msg } = await billOfflineAllAPI() 210 const { code, data, msg } = await billOfflineAllAPI()
194 if (code && Array.isArray(data)) { 211 if (code && Array.isArray(data)) {
195 // 过滤出状态为3(已完成)的记录 212 // 过滤出状态为3(已完成)的记录
196 - const normalized = data.map(normalize_bill_item).filter((item) => item && item.pay_id && item.status == 3) 213 + const normalized = data
214 + .map(normalize_bill_item)
215 + .filter(item => item && item.pay_id && item.status == 3)
197 if (normalized.length > 0) { 216 if (normalized.length > 0) {
198 // TAG: 核心逻辑:将过滤后的记录存储到本地缓存 217 // TAG: 核心逻辑:将过滤后的记录存储到本地缓存
199 Taro.setStorageSync(OFFLINE_BOOKING_CACHE_KEY, normalized) 218 Taro.setStorageSync(OFFLINE_BOOKING_CACHE_KEY, normalized)
......
...@@ -40,7 +40,7 @@ const polling_state = { ...@@ -40,7 +40,7 @@ const polling_state = {
40 network_usable: null, // 网络可用性 40 network_usable: null, // 网络可用性
41 has_network_listener: false, // 是否已注册网络监听器 41 has_network_listener: false, // 是否已注册网络监听器
42 network_listener: null, // 网络监听器 42 network_listener: null, // 网络监听器
43 - network_listener_promise: null, // 网络监听器Promise 43 + network_listener_promise: null // 网络监听器Promise
44 } 44 }
45 45
46 /** 46 /**
...@@ -48,7 +48,7 @@ const polling_state = { ...@@ -48,7 +48,7 @@ const polling_state = {
48 * @param {Object} options 选项 48 * @param {Object} options 选项
49 * @return {Object} 规范化后的选项 49 * @return {Object} 规范化后的选项
50 */ 50 */
51 -const normalize_options = (options) => { 51 +const normalize_options = options => {
52 return options || {} 52 return options || {}
53 } 53 }
54 54
...@@ -57,8 +57,10 @@ const normalize_options = (options) => { ...@@ -57,8 +57,10 @@ const normalize_options = (options) => {
57 * @param {Object} options 选项 57 * @param {Object} options 选项
58 * @return {Object} 保存后的选项 58 * @return {Object} 保存后的选项
59 */ 59 */
60 -const save_last_options = (options) => { 60 +const save_last_options = options => {
61 - if (options) polling_state.last_options = options 61 + if (options) {
62 + polling_state.last_options = options
63 + }
62 return polling_state.last_options 64 return polling_state.last_options
63 } 65 }
64 66
...@@ -73,11 +75,15 @@ const save_last_options = (options) => { ...@@ -73,11 +75,15 @@ const save_last_options = (options) => {
73 * @param {Object} options 选项 75 * @param {Object} options 选项
74 * @param {Boolean} options.force 是否强制刷新 76 * @param {Boolean} options.force 是否强制刷新
75 */ 77 */
76 -const run_refresh_once = async (options) => { 78 +const run_refresh_once = async options => {
77 // 前置检查:不满足轮询条件时直接返回(网络不可用或无引用) 79 // 前置检查:不满足轮询条件时直接返回(网络不可用或无引用)
78 - if (!should_run_polling()) return 80 + if (!should_run_polling()) {
81 + return
82 + }
79 // 核心防重复——如果正在刷新,直接返回 83 // 核心防重复——如果正在刷新,直接返回
80 - if (polling_state.in_flight) return 84 + if (polling_state.in_flight) {
85 + return
86 + }
81 // 标记为"正在刷新" 87 // 标记为"正在刷新"
82 polling_state.in_flight = true 88 polling_state.in_flight = true
83 try { 89 try {
...@@ -111,9 +117,15 @@ const update_network_usable = async () => { ...@@ -111,9 +117,15 @@ const update_network_usable = async () => {
111 * 2. network_usable === true:网络可用 117 * 2. network_usable === true:网络可用
112 */ 118 */
113 const should_run_polling = () => { 119 const should_run_polling = () => {
114 - if (polling_state.ref_count <= 0) return false 120 + if (polling_state.ref_count <= 0) {
115 - if (polling_state.network_usable === false) return false 121 + return false
116 - if (polling_state.network_usable === null) return false 122 + }
123 + if (polling_state.network_usable === false) {
124 + return false
125 + }
126 + if (polling_state.network_usable === null) {
127 + return false
128 + }
117 return true 129 return true
118 } 130 }
119 131
...@@ -147,7 +159,7 @@ const ensure_network_listener = async () => { ...@@ -147,7 +159,7 @@ const ensure_network_listener = async () => {
147 await update_network_usable() 159 await update_network_usable()
148 160
149 // 网络状态变化监听器, 网络状态变化时的处理逻辑,此时只是定义,不会立即执行 161 // 网络状态变化监听器, 网络状态变化时的处理逻辑,此时只是定义,不会立即执行
150 - polling_state.network_listener = (res) => { 162 + polling_state.network_listener = res => {
151 const is_connected = res?.isConnected !== false 163 const is_connected = res?.isConnected !== false
152 const type = res?.networkType || 'unknown' 164 const type = res?.networkType || 'unknown'
153 polling_state.network_usable = is_connected && is_usable_network(type) 165 polling_state.network_usable = is_connected && is_usable_network(type)
...@@ -204,9 +216,13 @@ const ensure_network_listener = async () => { ...@@ -204,9 +216,13 @@ const ensure_network_listener = async () => {
204 const teardown_network_listener = () => { 216 const teardown_network_listener = () => {
205 // 1. 前置校验:避免无效执行 217 // 1. 前置校验:避免无效执行
206 // 如果没有注册网络监听器,直接返回 218 // 如果没有注册网络监听器,直接返回
207 - if (!polling_state.has_network_listener) return 219 + if (!polling_state.has_network_listener) {
220 + return
221 + }
208 // 如果有引用计数,说明有其他地方在使用轮询,不能注销监听器 222 // 如果有引用计数,说明有其他地方在使用轮询,不能注销监听器
209 - if (polling_state.ref_count > 0) return 223 + if (polling_state.ref_count > 0) {
224 + return
225 + }
210 // 标记监听器已注销(核心状态更新) 226 // 标记监听器已注销(核心状态更新)
211 polling_state.has_network_listener = false 227 polling_state.has_network_listener = false
212 // 解绑框架层面的监听器 228 // 解绑框架层面的监听器
...@@ -239,9 +255,11 @@ const teardown_network_listener = () => { ...@@ -239,9 +255,11 @@ const teardown_network_listener = () => {
239 * @param {Boolean} options.force 是否强制刷新(透传给 refresh_offline_booking_cache) 255 * @param {Boolean} options.force 是否强制刷新(透传给 refresh_offline_booking_cache)
240 * @param {Boolean} options.restart 是否为重启操作(网络恢复时调用) 256 * @param {Boolean} options.restart 是否为重启操作(网络恢复时调用)
241 */ 257 */
242 -const start_offline_booking_cache_polling = (options) => { 258 +const start_offline_booking_cache_polling = options => {
243 options = normalize_options(options) 259 options = normalize_options(options)
244 - if (!should_run_polling()) return // 不满足轮询条件直接返回 260 + if (!should_run_polling()) {
261 + return
262 + } // 不满足轮询条件直接返回
245 263
246 const interval_ms = Number(options?.interval_ms || 60000) 264 const interval_ms = Number(options?.interval_ms || 60000)
247 const is_restart = options?.restart === true 265 const is_restart = options?.restart === true
...@@ -249,7 +267,9 @@ const start_offline_booking_cache_polling = (options) => { ...@@ -249,7 +267,9 @@ const start_offline_booking_cache_polling = (options) => {
249 // 改进:区分首次启动和重启的防重逻辑 267 // 改进:区分首次启动和重启的防重逻辑
250 // 首次启动时,如果已经在轮询则直接返回(防重复启动) 268 // 首次启动时,如果已经在轮询则直接返回(防重复启动)
251 // 重启时,需要清除旧定时器并重新建立(支持网络恢复时重启) 269 // 重启时,需要清除旧定时器并重新建立(支持网络恢复时重启)
252 - if (polling_state.running && !is_restart) return 270 + if (polling_state.running && !is_restart) {
271 + return
272 + }
253 273
254 // 如果是重启或定时器已存在,先清除旧定时器 274 // 如果是重启或定时器已存在,先清除旧定时器
255 if (is_restart && polling_state.timer_id) { 275 if (is_restart && polling_state.timer_id) {
...@@ -296,11 +316,11 @@ const stop_offline_booking_cache_polling = () => { ...@@ -296,11 +316,11 @@ const stop_offline_booking_cache_polling = () => {
296 * 核心动作:将全局的 ref_count 加 1,代表 "又多了一个场景需要使用轮询功能"。 316 * 核心动作:将全局的 ref_count 加 1,代表 "又多了一个场景需要使用轮询功能"。
297 * @param {Object} options 选项 317 * @param {Object} options 选项
298 */ 318 */
299 -const acquire_polling_ref = (options) => { 319 +const acquire_polling_ref = options => {
300 save_last_options(options) 320 save_last_options(options)
301 polling_state.ref_count += 1 321 polling_state.ref_count += 1
302 // 改进:检查网络监听器注册结果,只有成功后才启动轮询 322 // 改进:检查网络监听器注册结果,只有成功后才启动轮询
303 - ensure_network_listener().then((success) => { 323 + ensure_network_listener().then(success => {
304 if (success && polling_state.last_options) { 324 if (success && polling_state.last_options) {
305 start_offline_booking_cache_polling(polling_state.last_options) 325 start_offline_booking_cache_polling(polling_state.last_options)
306 } 326 }
...@@ -328,7 +348,7 @@ const release_polling_ref = () => { ...@@ -328,7 +348,7 @@ const release_polling_ref = () => {
328 * @param {Boolean} options.immediate 是否立即刷新一次 348 * @param {Boolean} options.immediate 是否立即刷新一次
329 * @param {Boolean} options.force 是否强制刷新(透传给 refresh_offline_booking_cache) 349 * @param {Boolean} options.force 是否强制刷新(透传给 refresh_offline_booking_cache)
330 */ 350 */
331 -export const enable_offline_booking_cache_polling = (options) => { 351 +export const enable_offline_booking_cache_polling = options => {
332 save_last_options(options) 352 save_last_options(options)
333 /** 353 /**
334 * 核心目的:对 app_enabled=true 的场景做兜底,确保轮询在 "已启用但异常停止" 时能被主动恢复,而非被动等待网络变化; 354 * 核心目的:对 app_enabled=true 的场景做兜底,确保轮询在 "已启用但异常停止" 时能被主动恢复,而非被动等待网络变化;
...@@ -336,7 +356,7 @@ export const enable_offline_booking_cache_polling = (options) => { ...@@ -336,7 +356,7 @@ export const enable_offline_booking_cache_polling = (options) => {
336 * 设计思维:体现了 "主动调用需即时生效" 的用户体验考量,以及 "依赖前置检查" 的工程化思维 —— 先保证依赖(监听器)就绪,再执行核心操作(启动轮询)。 356 * 设计思维:体现了 "主动调用需即时生效" 的用户体验考量,以及 "依赖前置检查" 的工程化思维 —— 先保证依赖(监听器)就绪,再执行核心操作(启动轮询)。
337 */ 357 */
338 if (polling_state.app_enabled) { 358 if (polling_state.app_enabled) {
339 - ensure_network_listener().then((success) => { 359 + ensure_network_listener().then(success => {
340 if (success && polling_state.last_options) { 360 if (success && polling_state.last_options) {
341 start_offline_booking_cache_polling(polling_state.last_options) 361 start_offline_booking_cache_polling(polling_state.last_options)
342 } 362 }
...@@ -352,7 +372,9 @@ export const enable_offline_booking_cache_polling = (options) => { ...@@ -352,7 +372,9 @@ export const enable_offline_booking_cache_polling = (options) => {
352 */ 372 */
353 373
354 export const disable_offline_booking_cache_polling = () => { 374 export const disable_offline_booking_cache_polling = () => {
355 - if (!polling_state.app_enabled) return 375 + if (!polling_state.app_enabled) {
376 + return
377 + }
356 polling_state.app_enabled = false 378 polling_state.app_enabled = false
357 release_polling_ref() 379 release_polling_ref()
358 } 380 }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 * @FilePath: /xyxBooking-weapp/src/hooks/useGo.js 5 * @FilePath: /xyxBooking-weapp/src/hooks/useGo.js
6 * @Description: 封装路由跳转方便行内调用 6 * @Description: 封装路由跳转方便行内调用
7 */ 7 */
8 -import Taro from '@tarojs/taro'; 8 +import Taro from '@tarojs/taro'
9 9
10 /** 10 /**
11 * @description 获取页面跳转方法(navigateTo) 11 * @description 获取页面跳转方法(navigateTo)
...@@ -13,37 +13,39 @@ import Taro from '@tarojs/taro'; ...@@ -13,37 +13,39 @@ import Taro from '@tarojs/taro';
13 * - 自动补全:pages/notice/index 13 * - 自动补全:pages/notice/index
14 * @returns {(path:string, query?:Object)=>void} go 跳转函数 14 * @returns {(path:string, query?:Object)=>void} go 跳转函数
15 */ 15 */
16 -export function useGo () { 16 +export function useGo() {
17 /** 17 /**
18 * @description 路由跳转 18 * @description 路由跳转
19 * @param {string} path 目标页面路径,支持 / 开头与短路径 19 * @param {string} path 目标页面路径,支持 / 开头与短路径
20 * @param {Object} query 查询参数(键值对) 20 * @param {Object} query 查询参数(键值对)
21 * @returns {void} 无返回值 21 * @returns {void} 无返回值
22 */ 22 */
23 - function go (path, query = {}) { 23 + function go(path, query = {}) {
24 // 补全路径,如果是 / 开头,去掉 / 24 // 补全路径,如果是 / 开头,去掉 /
25 - let url = path.startsWith('/') ? path.substring(1) : path; 25 + let url = path.startsWith('/') ? path.substring(1) : path
26 // 检查是否是 tabbar 页面 (目前没有配置 tabbar,所以都是普通跳转) 26 // 检查是否是 tabbar 页面 (目前没有配置 tabbar,所以都是普通跳转)
27 // 如果是页面,加上 pages/ 前缀 (假设都在 pages 下,且目录名和 path 一致) 27 // 如果是页面,加上 pages/ 前缀 (假设都在 pages 下,且目录名和 path 一致)
28 // H5 path 是 /notice,小程序是 pages/notice/index 28 // H5 path 是 /notice,小程序是 pages/notice/index
29 if (!url.startsWith('pages/')) { 29 if (!url.startsWith('pages/')) {
30 - url = `pages/${url}/index`; // 适配 pages/notice/index 结构 30 + url = `pages/${url}/index` // 适配 pages/notice/index 结构
31 } 31 }
32 32
33 // 构建 query string 33 // 构建 query string
34 - let queryString = Object.keys(query).map(key => key + '=' + query[key]).join('&'); 34 + const queryString = Object.keys(query)
35 + .map(key => `${key}=${query[key]}`)
36 + .join('&')
35 if (queryString) { 37 if (queryString) {
36 - url += '?' + queryString; 38 + url += `?${queryString}`
37 } 39 }
38 40
39 Taro.navigateTo({ 41 Taro.navigateTo({
40 - url: '/' + url, 42 + url: `/${url}`,
41 - fail: (err) => { 43 + fail: err => {
42 // 如果是 tabbar 页面,尝试 switchTab 44 // 如果是 tabbar 页面,尝试 switchTab
43 if (err.errMsg && err.errMsg.indexOf('tabbar') !== -1) { 45 if (err.errMsg && err.errMsg.indexOf('tabbar') !== -1) {
44 - Taro.switchTab({ url: '/' + url }); 46 + Taro.switchTab({ url: `/${url}` })
45 } else { 47 } else {
46 - console.error('页面跳转失败:', err); 48 + console.error('页面跳转失败:', err)
47 } 49 }
48 } 50 }
49 }) 51 })
...@@ -57,26 +59,28 @@ export function useGo () { ...@@ -57,26 +59,28 @@ export function useGo () {
57 * - 自动补全:pages/notice/index 59 * - 自动补全:pages/notice/index
58 * @returns {(path:string, query?:Object)=>void} replace 替换函数 60 * @returns {(path:string, query?:Object)=>void} replace 替换函数
59 */ 61 */
60 -export function useReplace () { 62 +export function useReplace() {
61 /** 63 /**
62 * @description 路由替换 64 * @description 路由替换
63 * @param {string} path 目标页面路径,支持 / 开头与短路径 65 * @param {string} path 目标页面路径,支持 / 开头与短路径
64 * @param {Object} query 查询参数(键值对) 66 * @param {Object} query 查询参数(键值对)
65 * @returns {void} 无返回值 67 * @returns {void} 无返回值
66 */ 68 */
67 - function replace (path, query = {}) { 69 + function replace(path, query = {}) {
68 - let url = path.startsWith('/') ? path.substring(1) : path; 70 + let url = path.startsWith('/') ? path.substring(1) : path
69 if (!url.startsWith('pages/')) { 71 if (!url.startsWith('pages/')) {
70 - url = `pages/${url}/index`; 72 + url = `pages/${url}/index`
71 } 73 }
72 74
73 - let queryString = Object.keys(query).map(key => key + '=' + query[key]).join('&'); 75 + const queryString = Object.keys(query)
76 + .map(key => `${key}=${query[key]}`)
77 + .join('&')
74 if (queryString) { 78 if (queryString) {
75 - url += '?' + queryString; 79 + url += `?${queryString}`
76 } 80 }
77 81
78 Taro.redirectTo({ 82 Taro.redirectTo({
79 - url: '/' + url 83 + url: `/${url}`
80 }) 84 })
81 } 85 }
82 return replace 86 return replace
......
...@@ -11,7 +11,14 @@ ...@@ -11,7 +11,14 @@
11 <view class="form-card"> 11 <view class="form-card">
12 <view class="form-row"> 12 <view class="form-row">
13 <view class="label">姓名</view> 13 <view class="label">姓名</view>
14 - <nut-input v-model="name" class="field-input" placeholder="请输入参观者真实姓名" type="text" input-align="right" :border="false" /> 14 + <nut-input
15 + v-model="name"
16 + class="field-input"
17 + placeholder="请输入参观者真实姓名"
18 + type="text"
19 + input-align="right"
20 + :border="false"
21 + />
15 </view> 22 </view>
16 <view class="form-row"> 23 <view class="form-row">
17 <view class="label">证件类型</view> 24 <view class="label">证件类型</view>
...@@ -22,7 +29,14 @@ ...@@ -22,7 +29,14 @@
22 </view> 29 </view>
23 <view class="form-row"> 30 <view class="form-row">
24 <view class="label">证件号码</view> 31 <view class="label">证件号码</view>
25 - <nut-input v-model="id_number" class="field-input" placeholder="请输入证件号码" :type="id_number_type" input-align="right" :border="false" /> 32 + <nut-input
33 + v-model="id_number"
34 + class="field-input"
35 + placeholder="请输入证件号码"
36 + :type="id_number_type"
37 + input-align="right"
38 + :border="false"
39 + />
26 </view> 40 </view>
27 </view> 41 </view>
28 42
...@@ -54,125 +68,160 @@ import Taro from '@tarojs/taro' ...@@ -54,125 +68,160 @@ import Taro from '@tarojs/taro'
54 import { addPersonAPI } from '@/api/index' 68 import { addPersonAPI } from '@/api/index'
55 import { IconFont } from '@nutui/icons-vue-taro' 69 import { IconFont } from '@nutui/icons-vue-taro'
56 70
57 -const name = ref(''); 71 +const name = ref('')
58 -const id_number = ref(''); 72 +const id_number = ref('')
59 -const show_id_type_picker = ref(false); 73 +const show_id_type_picker = ref(false)
60 const id_type_options = [ 74 const id_type_options = [
61 { label: '身份证', value: 1 }, 75 { label: '身份证', value: 1 },
62 { label: '其他', value: 3 } 76 { label: '其他', value: 3 }
63 -]; 77 +]
64 -const id_type = ref(id_type_options[0].value); 78 +const id_type = ref(id_type_options[0].value)
65 -const id_type_picker_value = ref([String(id_type.value)]); 79 +const id_type_picker_value = ref([String(id_type.value)])
66 80
67 const id_type_columns = computed(() => { 81 const id_type_columns = computed(() => {
68 return id_type_options.map(item => ({ 82 return id_type_options.map(item => ({
69 text: item.label, 83 text: item.label,
70 value: String(item.value) 84 value: String(item.value)
71 - })); 85 + }))
72 -}); 86 +})
73 const id_type_label = computed(() => { 87 const id_type_label = computed(() => {
74 - return id_type_options.find(item => item.value === id_type.value)?.label || id_type_options[0].label; 88 + return (
75 -}); 89 + id_type_options.find(item => item.value === id_type.value)?.label || id_type_options[0].label
76 -const id_number_type = computed(() => (id_type.value === 1 ? 'idcard' : 'text')); 90 + )
91 +})
92 +const id_number_type = computed(() => (id_type.value === 1 ? 'idcard' : 'text'))
77 93
78 const open_id_type_picker = () => { 94 const open_id_type_picker = () => {
79 - id_type_picker_value.value = [String(id_type.value)]; 95 + id_type_picker_value.value = [String(id_type.value)]
80 - show_id_type_picker.value = true; 96 + show_id_type_picker.value = true
81 } 97 }
82 98
83 const on_id_type_confirm = ({ selectedValue }) => { 99 const on_id_type_confirm = ({ selectedValue }) => {
84 - const value = selectedValue?.[0]; 100 + const value = selectedValue?.[0]
85 - id_type.value = Number(value) || 1; 101 + id_type.value = Number(value) || 1
86 - show_id_type_picker.value = false; 102 + show_id_type_picker.value = false
87 } 103 }
88 104
89 // 身份证校验 105 // 身份证校验
90 -const checkIDCard = (idcode) => { 106 +const checkIDCard = idcode => {
91 // 1. 基础格式校验 (18位) 107 // 1. 基础格式校验 (18位)
92 - if (!idcode || !/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(idcode)) { 108 + if (
93 - return false; 109 + !idcode ||
110 + !/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(
111 + idcode
112 + )
113 + ) {
114 + return false
94 } 115 }
95 116
96 // 2. 地区码校验 117 // 2. 地区码校验
97 const cityMap = { 118 const cityMap = {
98 - 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 119 + 11: '北京',
99 - 21: "辽宁", 22: "吉林", 23: "黑龙江", 120 + 12: '天津',
100 - 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 121 + 13: '河北',
101 - 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 122 + 14: '山西',
102 - 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 123 + 15: '内蒙古',
103 - 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", 124 + 21: '辽宁',
104 - 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" 125 + 22: '吉林',
105 - }; 126 + 23: '黑龙江',
127 + 31: '上海',
128 + 32: '江苏',
129 + 33: '浙江',
130 + 34: '安徽',
131 + 35: '福建',
132 + 36: '江西',
133 + 37: '山东',
134 + 41: '河南',
135 + 42: '湖北',
136 + 43: '湖南',
137 + 44: '广东',
138 + 45: '广西',
139 + 46: '海南',
140 + 50: '重庆',
141 + 51: '四川',
142 + 52: '贵州',
143 + 53: '云南',
144 + 54: '西藏',
145 + 61: '陕西',
146 + 62: '甘肃',
147 + 63: '青海',
148 + 64: '宁夏',
149 + 65: '新疆',
150 + 71: '台湾',
151 + 81: '香港',
152 + 82: '澳门',
153 + 91: '国外'
154 + }
106 if (!cityMap[idcode.substr(0, 2)]) { 155 if (!cityMap[idcode.substr(0, 2)]) {
107 - return false; 156 + return false
108 } 157 }
109 158
110 // 3. 出生日期校验 159 // 3. 出生日期校验
111 - const birthday = idcode.substr(6, 8); 160 + const birthday = idcode.substr(6, 8)
112 - const year = parseInt(birthday.substr(0, 4)); 161 + const year = parseInt(birthday.substr(0, 4))
113 - const month = parseInt(birthday.substr(4, 2)); 162 + const month = parseInt(birthday.substr(4, 2))
114 - const day = parseInt(birthday.substr(6, 2)); 163 + const day = parseInt(birthday.substr(6, 2))
115 - const date = new Date(year, month - 1, day); 164 + const date = new Date(year, month - 1, day)
116 165
117 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 166 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
118 - return false; 167 + return false
119 } 168 }
120 169
121 // 校验日期不能超过当前时间 170 // 校验日期不能超过当前时间
122 if (date > new Date()) { 171 if (date > new Date()) {
123 - return false; 172 + return false
124 } 173 }
125 174
126 // 4. 校验码计算 175 // 4. 校验码计算
127 // 加权因子 176 // 加权因子
128 - const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; 177 + const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
129 // 校验位对应值 178 // 校验位对应值
130 - const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; 179 + const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
131 180
132 - let sum = 0; 181 + let sum = 0
133 - const codeArr = idcode.split(""); 182 + const codeArr = idcode.split('')
134 // 计算加权和 183 // 计算加权和
135 for (let i = 0; i < 17; i++) { 184 for (let i = 0; i < 17; i++) {
136 - sum += codeArr[i] * factor[i]; 185 + sum += codeArr[i] * factor[i]
137 } 186 }
138 // 取模 187 // 取模
139 - const mod = sum % 11; 188 + const mod = sum % 11
140 // 获取校验位 189 // 获取校验位
141 - const last = parity[mod]; 190 + const last = parity[mod]
142 191
143 // 对比最后一位 (统一转大写比较) 192 // 对比最后一位 (统一转大写比较)
144 - return last === codeArr[17].toUpperCase(); 193 + return last === codeArr[17].toUpperCase()
145 } 194 }
146 195
147 const save = async () => { 196 const save = async () => {
148 if (!name.value) { 197 if (!name.value) {
149 - Taro.showToast({ title: '请输入姓名', icon: 'none' }); 198 + Taro.showToast({ title: '请输入姓名', icon: 'none' })
150 - return; 199 + return
151 } 200 }
152 if (!id_number.value) { 201 if (!id_number.value) {
153 - Taro.showToast({ title: '请输入证件号码', icon: 'none' }); 202 + Taro.showToast({ title: '请输入证件号码', icon: 'none' })
154 - return; 203 + return
155 } 204 }
156 if (id_type.value === 1 && !checkIDCard(id_number.value)) { 205 if (id_type.value === 1 && !checkIDCard(id_number.value)) {
157 - Taro.showToast({ title: '请输入正确的身份证号', icon: 'none' }); 206 + Taro.showToast({ title: '请输入正确的身份证号', icon: 'none' })
158 - return; 207 + return
159 } 208 }
160 209
161 - Taro.showLoading({ title: '保存中' }); 210 + Taro.showLoading({ title: '保存中' })
162 const { code, msg } = await addPersonAPI({ 211 const { code, msg } = await addPersonAPI({
163 name: name.value, 212 name: name.value,
164 id_type: id_type.value, 213 id_type: id_type.value,
165 id_number: id_number.value 214 id_number: id_number.value
166 - }); 215 + })
167 - Taro.hideLoading(); 216 + Taro.hideLoading()
168 217
169 if (code) { 218 if (code) {
170 - Taro.showToast({ title: '添加成功' }); 219 + Taro.showToast({ title: '添加成功' })
171 - name.value = ''; 220 + name.value = ''
172 - id_number.value = ''; 221 + id_number.value = ''
173 - Taro.navigateBack(); 222 + Taro.navigateBack()
174 } else { 223 } else {
175 - Taro.showToast({ title: msg || '添加失败', icon: 'none' }); 224 + Taro.showToast({ title: msg || '添加失败', icon: 'none' })
176 } 225 }
177 } 226 }
178 </script> 227 </script>
...@@ -180,7 +229,7 @@ const save = async () => { ...@@ -180,7 +229,7 @@ const save = async () => {
180 <style lang="less"> 229 <style lang="less">
181 .add-visitor-page { 230 .add-visitor-page {
182 min-height: 100vh; 231 min-height: 100vh;
183 - background-color: #F6F6F6; 232 + background-color: #f6f6f6;
184 padding-top: 2rpx; 233 padding-top: 2rpx;
185 234
186 .content { 235 .content {
...@@ -189,7 +238,7 @@ const save = async () => { ...@@ -189,7 +238,7 @@ const save = async () => {
189 } 238 }
190 239
191 .form-card { 240 .form-card {
192 - background-color: #FFF; 241 + background-color: #fff;
193 border-radius: 16rpx; 242 border-radius: 16rpx;
194 overflow: hidden; 243 overflow: hidden;
195 } 244 }
...@@ -201,7 +250,7 @@ const save = async () => { ...@@ -201,7 +250,7 @@ const save = async () => {
201 height: 112rpx; 250 height: 112rpx;
202 251
203 &:not(:last-child) { 252 &:not(:last-child) {
204 - border-bottom: 2rpx solid #F2F2F2; 253 + border-bottom: 2rpx solid #f2f2f2;
205 } 254 }
206 255
207 .label { 256 .label {
...@@ -230,7 +279,7 @@ const save = async () => { ...@@ -230,7 +279,7 @@ const save = async () => {
230 279
231 .picker-arrow { 280 .picker-arrow {
232 margin-left: 10rpx; 281 margin-left: 10rpx;
233 - color: #BBB; 282 + color: #bbb;
234 font-size: 28rpx; 283 font-size: 28rpx;
235 } 284 }
236 } 285 }
...@@ -239,7 +288,7 @@ const save = async () => { ...@@ -239,7 +288,7 @@ const save = async () => {
239 margin-top: 28rpx; 288 margin-top: 28rpx;
240 display: flex; 289 display: flex;
241 align-items: center; 290 align-items: center;
242 - color: #C7A46D; 291 + color: #c7a46d;
243 font-size: 24rpx; 292 font-size: 24rpx;
244 293
245 .tip-text { 294 .tip-text {
...@@ -253,18 +302,18 @@ const save = async () => { ...@@ -253,18 +302,18 @@ const save = async () => {
253 right: 0; 302 right: 0;
254 bottom: 0; 303 bottom: 0;
255 padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom)); 304 padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
256 - background-color: #F6F6F6; 305 + background-color: #f6f6f6;
257 } 306 }
258 307
259 .save-btn { 308 .save-btn {
260 width: 686rpx; 309 width: 686rpx;
261 height: 96rpx; 310 height: 96rpx;
262 - background-color: #A67939; 311 + background-color: #a67939;
263 border-radius: 12rpx; 312 border-radius: 12rpx;
264 display: flex; 313 display: flex;
265 align-items: center; 314 align-items: center;
266 justify-content: center; 315 justify-content: center;
267 - color: #FFF; 316 + color: #fff;
268 font-size: 34rpx; 317 font-size: 34rpx;
269 font-weight: 600; 318 font-weight: 600;
270 } 319 }
......
1 export default { 1 export default {
2 navigationBarTitleText: '授权页', 2 navigationBarTitleText: '授权页',
3 - usingComponents: { 3 + usingComponents: {}
4 - },
5 } 4 }
......
...@@ -22,9 +22,13 @@ let has_shown_fail_modal = false ...@@ -22,9 +22,13 @@ let has_shown_fail_modal = false
22 let has_failed = false 22 let has_failed = false
23 23
24 useDidShow(() => { 24 useDidShow(() => {
25 - if (has_failed) return 25 + if (has_failed) {
26 + return
27 + }
26 const now = Date.now() 28 const now = Date.now()
27 - if (now - last_try_at < 1200) return 29 + if (now - last_try_at < 1200) {
30 + return
31 + }
28 last_try_at = now 32 last_try_at = now
29 33
30 /** 34 /**
...@@ -34,15 +38,17 @@ useDidShow(() => { ...@@ -34,15 +38,17 @@ useDidShow(() => {
34 */ 38 */
35 silentAuth() 39 silentAuth()
36 .then(() => returnToOriginalPage()) 40 .then(() => returnToOriginalPage())
37 - .catch(async (error) => { 41 + .catch(async error => {
38 has_failed = true 42 has_failed = true
39 - if (has_shown_fail_modal) return 43 + if (has_shown_fail_modal) {
44 + return
45 + }
40 has_shown_fail_modal = true 46 has_shown_fail_modal = true
41 await Taro.showModal({ 47 await Taro.showModal({
42 title: '提示', 48 title: '提示',
43 content: error?.message || '授权失败,请稍后再尝试', 49 content: error?.message || '授权失败,请稍后再尝试',
44 showCancel: false, 50 showCancel: false,
45 - confirmText: '我知道了', 51 + confirmText: '我知道了'
46 }) 52 })
47 }) 53 })
48 }) 54 })
......
This diff is collapsed. Click to expand it.
...@@ -7,12 +7,14 @@ ...@@ -7,12 +7,14 @@
7 --> 7 -->
8 <template> 8 <template>
9 <view class="booking-code-page"> 9 <view class="booking-code-page">
10 - <view style="padding: 32rpx;"> 10 + <view style="padding: 32rpx">
11 <qrCode ref="qr_code_ref"></qrCode> 11 <qrCode ref="qr_code_ref"></qrCode>
12 <view class="warning"> 12 <view class="warning">
13 - <view style="display: flex; align-items: center; justify-content: center;"><IconFont name="tips" /><text style="margin-left: 10rpx;">温馨提示</text></view> 13 + <view style="display: flex; align-items: center; justify-content: center"
14 - <view style="margin-top: 16rpx;">一人一码,扫码或识别身份证成功后进入</view> 14 + ><IconFont name="tips" /><text style="margin-left: 10rpx">温馨提示</text></view
15 - <view style="height: 256rpx;"></view> 15 + >
16 + <view style="margin-top: 16rpx">一人一码,扫码或识别身份证成功后进入</view>
17 + <view style="height: 256rpx"></view>
16 </view> 18 </view>
17 </view> 19 </view>
18 <indexNav 20 <indexNav
...@@ -28,7 +30,7 @@ ...@@ -28,7 +30,7 @@
28 <script setup> 30 <script setup>
29 import { ref } from 'vue' 31 import { ref } from 'vue'
30 import Taro, { useDidShow, useDidHide } from '@tarojs/taro' 32 import Taro, { useDidShow, useDidHide } from '@tarojs/taro'
31 -import qrCode from '@/components/qrCode'; 33 +import qrCode from '@/components/qrCode'
32 import { IconFont } from '@nutui/icons-vue-taro' 34 import { IconFont } from '@nutui/icons-vue-taro'
33 import indexNav from '@/components/indexNav.vue' 35 import indexNav from '@/components/indexNav.vue'
34 import icon_3 from '@/assets/images/首页01@2x.png' 36 import icon_3 from '@/assets/images/首页01@2x.png'
...@@ -44,9 +46,11 @@ const qr_code_ref = ref(null) ...@@ -44,9 +46,11 @@ const qr_code_ref = ref(null)
44 useDidShow(() => { 46 useDidShow(() => {
45 qr_code_ref.value?.start_polling?.() 47 qr_code_ref.value?.start_polling?.()
46 Taro.getNetworkType({ 48 Taro.getNetworkType({
47 - success: async (res) => { 49 + success: async res => {
48 - const isConnected = is_usable_network(res.networkType); 50 + const isConnected = is_usable_network(res.networkType)
49 - if (isConnected) return 51 + if (isConnected) {
52 + return
53 + }
50 54
51 if (has_offline_booking_cache()) { 55 if (has_offline_booking_cache()) {
52 Taro.redirectTo({ url: '/pages/offlineBookingList/index' }) 56 Taro.redirectTo({ url: '/pages/offlineBookingList/index' })
...@@ -72,19 +76,21 @@ useDidShow(() => { ...@@ -72,19 +76,21 @@ useDidShow(() => {
72 } 76 }
73 Taro.redirectTo({ url: '/pages/index/index' }) 77 Taro.redirectTo({ url: '/pages/index/index' })
74 } 78 }
75 - }); 79 + })
76 }) 80 })
77 81
78 useDidHide(() => { 82 useDidHide(() => {
79 qr_code_ref.value?.stop_polling?.() 83 qr_code_ref.value?.stop_polling?.()
80 }) 84 })
81 85
82 -const toMy = () => { // 跳转到我的 86 +const toMy = () => {
87 + // 跳转到我的
83 Taro.redirectTo({ 88 Taro.redirectTo({
84 url: '/pages/me/index' 89 url: '/pages/me/index'
85 }) 90 })
86 } 91 }
87 -const toHome = () => { // 跳转到首页 92 +const toHome = () => {
93 + // 跳转到首页
88 Taro.redirectTo({ 94 Taro.redirectTo({
89 url: '/pages/index/index' 95 url: '/pages/index/index'
90 }) 96 })
...@@ -92,22 +98,25 @@ const toHome = () => { // 跳转到首页 ...@@ -92,22 +98,25 @@ const toHome = () => { // 跳转到首页
92 98
93 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 } 99 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
94 100
95 -const on_nav_select = (key) => { 101 +const on_nav_select = key => {
96 - if (key === 'home') return toHome() 102 + if (key === 'home') {
97 - if (key === 'me') return toMy() 103 + return toHome()
104 + }
105 + if (key === 'me') {
106 + return toMy()
107 + }
98 } 108 }
99 -
100 </script> 109 </script>
101 110
102 <style lang="less"> 111 <style lang="less">
103 .booking-code-page { 112 .booking-code-page {
104 position: relative; 113 position: relative;
105 min-height: 100vh; 114 min-height: 100vh;
106 - background-color: #F6F6F6; 115 + background-color: #f6f6f6;
107 116
108 .warning { 117 .warning {
109 text-align: center; 118 text-align: center;
110 - color: #A67939; 119 + color: #a67939;
111 margin-top: 32rpx; 120 margin-top: 32rpx;
112 } 121 }
113 } 122 }
......
...@@ -34,9 +34,12 @@ ...@@ -34,9 +34,12 @@
34 <view>{{ qrCodeStatusText }}</view> 34 <view>{{ qrCodeStatusText }}</view>
35 </view> 35 </view>
36 </view> 36 </view>
37 - <view style="height: 160rpx;"></view> 37 + <view style="height: 160rpx"></view>
38 - <view v-if="billInfo.status === CodeStatus.SUCCESS && billInfo.show_cancel_reserve === 1" class="cancel-wrapper"> 38 + <view
39 - <view @tap="cancelBooking" class="cancel-btn ">取消预约</view> 39 + v-if="billInfo.status === CodeStatus.SUCCESS && billInfo.show_cancel_reserve === 1"
40 + class="cancel-wrapper"
41 + >
42 + <view @tap="cancelBooking" class="cancel-btn">取消预约</view>
40 </view> 43 </view>
41 </view> 44 </view>
42 </template> 45 </template>
...@@ -44,16 +47,16 @@ ...@@ -44,16 +47,16 @@
44 <script setup> 47 <script setup>
45 import { ref, computed } from 'vue' 48 import { ref, computed } from 'vue'
46 import Taro, { useDidShow, useDidHide, useRouter as useTaroRouter } from '@tarojs/taro' 49 import Taro, { useDidShow, useDidHide, useRouter as useTaroRouter } from '@tarojs/taro'
47 -import qrCode from '@/components/qrCode'; 50 +import qrCode from '@/components/qrCode'
48 import { billInfoAPI, icbcRefundAPI } from '@/api/index' 51 import { billInfoAPI, icbcRefundAPI } from '@/api/index'
49 -import { formatDatetime, get_bill_status_text } from '@/utils/tools'; 52 +import { formatDatetime, get_bill_status_text } from '@/utils/tools'
50 import { refresh_offline_booking_cache } from '@/composables/useOfflineBookingCache' 53 import { refresh_offline_booking_cache } from '@/composables/useOfflineBookingCache'
51 54
52 -const router = useTaroRouter(); 55 +const router = useTaroRouter()
53 56
54 -const pay_id = ref(''); 57 +const pay_id = ref('')
55 -const qrCodeStatus = ref(''); 58 +const qrCodeStatus = ref('')
56 -const billInfo = ref({}); 59 +const billInfo = ref({})
57 const qr_code_ref = ref(null) 60 const qr_code_ref = ref(null)
58 61
59 /** 62 /**
...@@ -88,33 +91,33 @@ const cancelBooking = async () => { ...@@ -88,33 +91,33 @@ const cancelBooking = async () => {
88 title: '温馨提示', 91 title: '温馨提示',
89 content: '是否取消预约?', 92 content: '是否取消预约?',
90 confirmColor: '#A67939' 93 confirmColor: '#A67939'
91 - }); 94 + })
92 95
93 if (confirm) { 96 if (confirm) {
94 - Taro.showLoading({ title: '取消中...' }); 97 + Taro.showLoading({ title: '取消中...' })
95 - const { code, data } = await icbcRefundAPI({ pay_id: pay_id.value }); 98 + const { code, data } = await icbcRefundAPI({ pay_id: pay_id.value })
96 - Taro.hideLoading(); 99 + Taro.hideLoading()
97 if (code) { 100 if (code) {
98 - Taro.showToast({ title: '取消成功' }); 101 + Taro.showToast({ title: '取消成功' })
99 try { 102 try {
100 await refresh_offline_booking_cache({ force: true }) 103 await refresh_offline_booking_cache({ force: true })
101 } catch (e) {} 104 } catch (e) {}
102 - Taro.navigateBack(); 105 + Taro.navigateBack()
103 } else { 106 } else {
104 - Taro.showToast({ title: '取消失败', icon: 'none' }); 107 + Taro.showToast({ title: '取消失败', icon: 'none' })
105 } 108 }
106 } 109 }
107 } 110 }
108 111
109 useDidShow(async () => { 112 useDidShow(async () => {
110 qr_code_ref.value?.start_polling?.() 113 qr_code_ref.value?.start_polling?.()
111 - pay_id.value = router.params.pay_id; 114 + pay_id.value = router.params.pay_id
112 if (pay_id.value) { 115 if (pay_id.value) {
113 - const { code, data } = await billInfoAPI({ pay_id: pay_id.value }); 116 + const { code, data } = await billInfoAPI({ pay_id: pay_id.value })
114 if (code) { 117 if (code) {
115 - data.datetime = data && formatDatetime(data); 118 + data.datetime = data && formatDatetime(data)
116 - data.order_time = data.created_time ? data.created_time.slice(0, -3) : ''; 119 + data.order_time = data.created_time ? data.created_time.slice(0, -3) : ''
117 - billInfo.value = data; 120 + billInfo.value = data
118 } 121 }
119 } 122 }
120 }) 123 })
...@@ -127,15 +130,15 @@ useDidHide(() => { ...@@ -127,15 +130,15 @@ useDidHide(() => {
127 <style lang="less"> 130 <style lang="less">
128 .booking-detail-page { 131 .booking-detail-page {
129 min-height: 100vh; 132 min-height: 100vh;
130 - background-color: #F6F6F6; 133 + background-color: #f6f6f6;
131 padding: 32rpx; 134 padding: 32rpx;
132 135
133 .detail-wrapper { 136 .detail-wrapper {
134 - background-color: #FFF; 137 + background-color: #fff;
135 border-radius: 16rpx; 138 border-radius: 16rpx;
136 padding: 32rpx; 139 padding: 32rpx;
137 margin-top: 32rpx; 140 margin-top: 32rpx;
138 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.1); 141 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.1);
139 142
140 .detail-item { 143 .detail-item {
141 display: flex; 144 display: flex;
...@@ -164,14 +167,14 @@ useDidHide(() => { ...@@ -164,14 +167,14 @@ useDidHide(() => {
164 bottom: 0; 167 bottom: 0;
165 left: 0; 168 left: 0;
166 width: 750rpx; 169 width: 750rpx;
167 - background-color: #FFF; 170 + background-color: #fff;
168 padding: 32rpx; 171 padding: 32rpx;
169 box-sizing: border-box; 172 box-sizing: border-box;
170 173
171 .cancel-btn { 174 .cancel-btn {
172 - background-color: #FFF; 175 + background-color: #fff;
173 - color: #A67939; 176 + color: #a67939;
174 - border: 2rpx solid #A67939; 177 + border: 2rpx solid #a67939;
175 text-align: center; 178 text-align: center;
176 padding: 26rpx 0; 179 padding: 26rpx 0;
177 border-radius: 16rpx; 180 border-radius: 16rpx;
......
...@@ -11,11 +11,18 @@ ...@@ -11,11 +11,18 @@
11 <reserveCard :data="item" /> 11 <reserveCard :data="item" />
12 </view> 12 </view>
13 13
14 - <view v-if="loading" style="text-align: center; color: #999; padding: 20rpx;">加载中...</view> 14 + <view v-if="loading" style="text-align: center; color: #999; padding: 20rpx">加载中...</view>
15 - <view v-if="finished && bookingList.length > 0" style="text-align: center; color: #999; padding: 20rpx;">没有更多了</view> 15 + <view
16 + v-if="finished && bookingList.length > 0"
17 + style="text-align: center; color: #999; padding: 20rpx"
18 + >没有更多了</view
19 + >
16 20
17 <view v-if="!bookingList.length && finished" class="no-qrcode"> 21 <view v-if="!bookingList.length && finished" class="no-qrcode">
18 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png" style="width: 320rpx; height: 320rpx;" /> 22 + <image
23 + src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png"
24 + style="width: 320rpx; height: 320rpx"
25 + />
19 <view class="no-qrcode-title">您还没有预约过参观</view> 26 <view class="no-qrcode-title">您还没有预约过参观</view>
20 </view> 27 </view>
21 </view> 28 </view>
...@@ -25,14 +32,14 @@ ...@@ -25,14 +32,14 @@
25 import { ref } from 'vue' 32 import { ref } from 'vue'
26 import { useDidShow, useReachBottom } from '@tarojs/taro' 33 import { useDidShow, useReachBottom } from '@tarojs/taro'
27 import { billListAPI } from '@/api/index' 34 import { billListAPI } from '@/api/index'
28 -import { formatDatetime } from '@/utils/tools'; 35 +import { formatDatetime } from '@/utils/tools'
29 import reserveCard from '@/components/reserveCard.vue' 36 import reserveCard from '@/components/reserveCard.vue'
30 37
31 -const page = ref(1); 38 +const page = ref(1)
32 -const limit = ref(5); 39 +const limit = ref(5)
33 -const bookingList = ref([]); 40 +const bookingList = ref([])
34 -const loading = ref(false); 41 +const loading = ref(false)
35 -const finished = ref(false); 42 +const finished = ref(false)
36 43
37 /** 44 /**
38 * @description 加载预约记录列表(分页) 45 * @description 加载预约记录列表(分页)
...@@ -40,52 +47,54 @@ const finished = ref(false); ...@@ -40,52 +47,54 @@ const finished = ref(false);
40 * @returns {Promise<void>} 无返回值 47 * @returns {Promise<void>} 无返回值
41 */ 48 */
42 const loadData = async (isRefresh = false) => { 49 const loadData = async (isRefresh = false) => {
43 - if (loading.value || (finished.value && !isRefresh)) return; 50 + if (loading.value || (finished.value && !isRefresh)) {
51 + return
52 + }
44 53
45 - loading.value = true; 54 + loading.value = true
46 if (isRefresh) { 55 if (isRefresh) {
47 - page.value = 1; 56 + page.value = 1
48 - finished.value = false; 57 + finished.value = false
49 } 58 }
50 59
51 - const { code, data } = await billListAPI({ page: page.value, row_num: limit.value }); 60 + const { code, data } = await billListAPI({ page: page.value, row_num: limit.value })
52 - loading.value = false; 61 + loading.value = false
53 62
54 if (code) { 63 if (code) {
55 - const list = data || []; 64 + const list = data || []
56 list.forEach(item => { 65 list.forEach(item => {
57 - item.booking_time = item && formatDatetime(item); 66 + item.booking_time = item && formatDatetime(item)
58 - item.order_time = item.created_time ? item.created_time.slice(0, -3) : ''; 67 + item.order_time = item.created_time ? item.created_time.slice(0, -3) : ''
59 - }); 68 + })
60 69
61 if (isRefresh) { 70 if (isRefresh) {
62 - bookingList.value = list; 71 + bookingList.value = list
63 } else { 72 } else {
64 - bookingList.value = bookingList.value.concat(list); 73 + bookingList.value = bookingList.value.concat(list)
65 } 74 }
66 75
67 if (list.length < limit.value) { 76 if (list.length < limit.value) {
68 - finished.value = true; 77 + finished.value = true
69 } else { 78 } else {
70 - page.value++; 79 + page.value++
71 } 80 }
72 } 81 }
73 } 82 }
74 83
75 useDidShow(() => { 84 useDidShow(() => {
76 - loadData(true); 85 + loadData(true)
77 -}); 86 +})
78 87
79 useReachBottom(() => { 88 useReachBottom(() => {
80 - loadData(); 89 + loadData()
81 -}); 90 +})
82 </script> 91 </script>
83 92
84 <style lang="less"> 93 <style lang="less">
85 .booking-list-page { 94 .booking-list-page {
86 padding: 32rpx; 95 padding: 32rpx;
87 min-height: 100vh; 96 min-height: 100vh;
88 - background-color: #F6F6F6; 97 + background-color: #f6f6f6;
89 98
90 .no-qrcode { 99 .no-qrcode {
91 display: flex; 100 display: flex;
...@@ -95,7 +104,7 @@ useReachBottom(() => { ...@@ -95,7 +104,7 @@ useReachBottom(() => {
95 padding-top: 160rpx; 104 padding-top: 160rpx;
96 105
97 .no-qrcode-title { 106 .no-qrcode-title {
98 - color: #A67939; 107 + color: #a67939;
99 font-size: 34rpx; 108 font-size: 34rpx;
100 margin-top: 32rpx; 109 margin-top: 32rpx;
101 } 110 }
......
...@@ -2,19 +2,33 @@ ...@@ -2,19 +2,33 @@
2 <view class="callback-page"> 2 <view class="callback-page">
3 <view> 3 <view>
4 <view v-if="pay_status === PAY_STATUS.FAIL" class="text-prompts"> 4 <view v-if="pay_status === PAY_STATUS.FAIL" class="text-prompts">
5 - <image src="https://cdn.ipadbiz.cn/xys/booking/shibai.png" mode="widthFix" class="status-icon"/> 5 + <image
6 + src="https://cdn.ipadbiz.cn/xys/booking/shibai.png"
7 + mode="widthFix"
8 + class="status-icon"
9 + />
6 <view class="text">支付失败</view> 10 <view class="text">支付失败</view>
7 </view> 11 </view>
8 <view v-else class="text-prompts"> 12 <view v-else class="text-prompts">
9 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E6%88%90%E5%8A%9F@2x.png?imageMogr2/thumbnail/200x/strip/quality/70" mode="widthFix" class="status-icon"/> 13 + <image
14 + src="https://cdn.ipadbiz.cn/xys/booking/%E6%88%90%E5%8A%9F@2x.png?imageMogr2/thumbnail/200x/strip/quality/70"
15 + mode="widthFix"
16 + class="status-icon"
17 + />
10 <!-- <view class="text">支付完成</view> --> 18 <!-- <view class="text">支付完成</view> -->
11 </view> 19 </view>
12 <view class="appointment-information"> 20 <view class="appointment-information">
13 - <view class="info-item">参观人数:<text>{{ billInfo?.total_qty || 0 }} 人</text></view> 21 + <view class="info-item"
14 - <view class="info-item">参访时间:<text>{{ billInfo?.datetime || '--' }}</text></view> 22 + >参观人数:<text>{{ billInfo?.total_qty || 0 }} 人</text></view
15 - <view class="info-item">支付金额:<text>¥ {{ billInfo?.total_amt || 0 }}</text></view> 23 + >
24 + <view class="info-item"
25 + >参访时间:<text>{{ billInfo?.datetime || '--' }}</text></view
26 + >
27 + <view class="info-item"
28 + >支付金额:<text>¥ {{ billInfo?.total_amt || 0 }}</text></view
29 + >
16 </view> 30 </view>
17 - <view style="padding: 16rpx; display: flex; justify-content: center; margin-top: 32rpx;"> 31 + <view style="padding: 16rpx; display: flex; justify-content: center; margin-top: 32rpx">
18 <nut-button color="#A67939" size="small" @click="returnMerchant">返回首页</nut-button> 32 <nut-button color="#A67939" size="small" @click="returnMerchant">返回首页</nut-button>
19 </view> 33 </view>
20 </view> 34 </view>
...@@ -35,14 +49,16 @@ const billInfo = ref({}) ...@@ -35,14 +49,16 @@ const billInfo = ref({})
35 const PAY_STATUS = { 49 const PAY_STATUS = {
36 SUCCESS: '0', 50 SUCCESS: '0',
37 FAIL: '1', 51 FAIL: '1',
38 - UNKNOWN: '2', 52 + UNKNOWN: '2'
39 } 53 }
40 const pay_status = ref('0') // Default to success as per logic 54 const pay_status = ref('0') // Default to success as per logic
41 55
42 const out_trade_no = router.params.out_trade_no 56 const out_trade_no = router.params.out_trade_no
43 57
44 const getBillInfo = async () => { 58 const getBillInfo = async () => {
45 - if (!out_trade_no) return 59 + if (!out_trade_no) {
60 + return
61 + }
46 62
47 try { 63 try {
48 // Get order details 64 // Get order details
......
1 export default { 1 export default {
2 navigationBarTitleText: 'demo', 2 navigationBarTitleText: 'demo',
3 - usingComponents: { 3 + usingComponents: {}
4 - },
5 } 4 }
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
11 11
12 <script setup> 12 <script setup>
13 import '@tarojs/taro/html.css' 13 import '@tarojs/taro/html.css'
14 -import { ref } from "vue"; 14 +import { ref } from 'vue'
15 -import "./index.less"; 15 +import './index.less'
16 16
17 // 定义响应式数据 17 // 定义响应式数据
18 const str = ref('Demo页面') 18 const str = ref('Demo页面')
...@@ -20,6 +20,6 @@ const str = ref('Demo页面') ...@@ -20,6 +20,6 @@ const str = ref('Demo页面')
20 20
21 <script> 21 <script>
22 export default { 22 export default {
23 - name: "demoPage", 23 + name: 'demoPage'
24 -}; 24 +}
25 </script> 25 </script>
......
...@@ -15,10 +15,17 @@ ...@@ -15,10 +15,17 @@
15 <view class="mt-1 text-sm opacity-80">{{ weak_network_banner_desc }}</view> 15 <view class="mt-1 text-sm opacity-80">{{ weak_network_banner_desc }}</view>
16 </view> 16 </view>
17 <view class="index-content"> 17 <view class="index-content">
18 - <view style="height: 28vh;"> 18 + <view style="height: 28vh">
19 - <swiper class="my-swipe" :autoplay="true" :interval="3000" indicator-dots indicator-color="white" :circular="true"> 19 + <swiper
20 + class="my-swipe"
21 + :autoplay="true"
22 + :interval="3000"
23 + indicator-dots
24 + indicator-color="white"
25 + :circular="true"
26 + >
20 <swiper-item> 27 <swiper-item>
21 - <image style="height: 28vh; width: 100vw;" :src="banner_url" /> 28 + <image style="height: 28vh; width: 100vw" :src="banner_url" />
22 </swiper-item> 29 </swiper-item>
23 </swiper> 30 </swiper>
24 </view> 31 </view>
...@@ -26,8 +33,8 @@ ...@@ -26,8 +33,8 @@
26 <view ref="root" class="index-circular"> 33 <view ref="root" class="index-circular">
27 <view class="booking-wrapper"> 34 <view class="booking-wrapper">
28 <view class="booking" @tap="toBooking"> 35 <view class="booking" @tap="toBooking">
29 - <view><image :src="icon_1" style="width: 96rpx; height: 96rpx;" /></view> 36 + <view><image :src="icon_1" style="width: 96rpx; height: 96rpx" /></view>
30 - <view style="color: #FFF;">开始预约</view> 37 + <view style="color: #fff">开始预约</view>
31 </view> 38 </view>
32 </view> 39 </view>
33 </view> 40 </view>
...@@ -57,7 +64,7 @@ import icon_3 from '@/assets/images/首页02@2x.png' ...@@ -57,7 +64,7 @@ import icon_3 from '@/assets/images/首页02@2x.png'
57 import icon_4 from '@/assets/images/二维码icon.png' 64 import icon_4 from '@/assets/images/二维码icon.png'
58 import icon_5 from '@/assets/images/我的01@2x.png' 65 import icon_5 from '@/assets/images/我的01@2x.png'
59 66
60 -const go = useGo(); 67 +const go = useGo()
61 const is_offline = ref(false) 68 const is_offline = ref(false)
62 const weak_network_banner_desc = weak_network_text.banner_desc 69 const weak_network_banner_desc = weak_network_text.banner_desc
63 // 背景图版本号, 用于刷新背景图 70 // 背景图版本号, 用于刷新背景图
...@@ -66,10 +73,12 @@ const bg_version = ref(Number.isFinite(initial_t) ? initial_t : 0) ...@@ -66,10 +73,12 @@ const bg_version = ref(Number.isFinite(initial_t) ? initial_t : 0)
66 let is_reloading = false 73 let is_reloading = false
67 74
68 const reload_page = () => { 75 const reload_page = () => {
69 - if (is_reloading) return 76 + if (is_reloading) {
77 + return
78 + }
70 is_reloading = true 79 is_reloading = true
71 Taro.reLaunch({ 80 Taro.reLaunch({
72 - url: `/pages/index/index?_t=${Date.now()}`, 81 + url: `/pages/index/index?_t=${Date.now()}`
73 }) 82 })
74 } 83 }
75 84
...@@ -93,18 +102,18 @@ const page_style = computed(() => { ...@@ -93,18 +102,18 @@ const page_style = computed(() => {
93 if (is_offline.value) { 102 if (is_offline.value) {
94 return { 103 return {
95 backgroundColor: '#F3EEE3', 104 backgroundColor: '#F3EEE3',
96 - backgroundImage: `linear-gradient(180deg, rgba(166, 121, 57, 0.10) 0%, rgba(255, 255, 255, 0.90) 60%, rgba(243, 238, 227, 1) 100%), url('${normal_bg_url.value}')`, 105 + backgroundImage: `linear-gradient(180deg, rgba(166, 121, 57, 0.10) 0%, rgba(255, 255, 255, 0.90) 60%, rgba(243, 238, 227, 1) 100%), url('${normal_bg_url.value}')`
97 } 106 }
98 } 107 }
99 return { 108 return {
100 backgroundColor: '#F3EEE3', 109 backgroundColor: '#F3EEE3',
101 - backgroundImage: `url('${normal_bg_url.value}')`, 110 + backgroundImage: `url('${normal_bg_url.value}')`
102 } 111 }
103 }) 112 })
104 113
105 const logo_style = computed(() => { 114 const logo_style = computed(() => {
106 return { 115 return {
107 - backgroundImage: `url('${logo_url.value}')`, 116 + backgroundImage: `url('${logo_url.value}')`
108 } 117 }
109 }) 118 })
110 119
...@@ -114,7 +123,7 @@ const logo_style = computed(() => { ...@@ -114,7 +123,7 @@ const logo_style = computed(() => {
114 * - 更新 is_offline 状态 123 * - 更新 is_offline 状态
115 */ 124 */
116 125
117 -const apply_offline_state = (next_offline) => { 126 +const apply_offline_state = next_offline => {
118 if (is_offline.value === true && next_offline === false) { 127 if (is_offline.value === true && next_offline === false) {
119 reload_page() 128 reload_page()
120 return true 129 return true
...@@ -147,9 +156,11 @@ let network_listener = null ...@@ -147,9 +156,11 @@ let network_listener = null
147 */ 156 */
148 157
149 const setup_network_listener = () => { 158 const setup_network_listener = () => {
150 - if (has_network_listener) return 159 + if (has_network_listener) {
160 + return
161 + }
151 has_network_listener = true 162 has_network_listener = true
152 - network_listener = (res) => { 163 + network_listener = res => {
153 try { 164 try {
154 const is_connected = res?.isConnected !== false 165 const is_connected = res?.isConnected !== false
155 const network_type = res?.networkType 166 const network_type = res?.networkType
...@@ -158,7 +169,9 @@ const setup_network_listener = () => { ...@@ -158,7 +169,9 @@ const setup_network_listener = () => {
158 const next_offline = !(is_connected && is_usable_network(network_type)) 169 const next_offline = !(is_connected && is_usable_network(network_type))
159 // 检查是否需要刷新 170 // 检查是否需要刷新
160 const is_handled = apply_offline_state(next_offline) 171 const is_handled = apply_offline_state(next_offline)
161 - if (is_handled) return 172 + if (is_handled) {
173 + return
174 + }
162 } 175 }
163 // 还没有网, 再次刷新 176 // 还没有网, 再次刷新
164 refresh_offline_state() 177 refresh_offline_state()
...@@ -175,7 +188,9 @@ const setup_network_listener = () => { ...@@ -175,7 +188,9 @@ const setup_network_listener = () => {
175 */ 188 */
176 189
177 const teardown_network_listener = () => { 190 const teardown_network_listener = () => {
178 - if (!has_network_listener) return 191 + if (!has_network_listener) {
192 + return
193 + }
179 has_network_listener = false 194 has_network_listener = false
180 if (network_listener && typeof Taro.offNetworkStatusChange === 'function') { 195 if (network_listener && typeof Taro.offNetworkStatusChange === 'function') {
181 try { 196 try {
...@@ -199,7 +214,8 @@ onUnmounted(() => { ...@@ -199,7 +214,8 @@ onUnmounted(() => {
199 teardown_network_listener() 214 teardown_network_listener()
200 }) 215 })
201 216
202 -const toBooking = () => { // 跳转到预约须知 217 +const toBooking = () => {
218 + // 跳转到预约须知
203 // 如果是离线模式,不跳转 219 // 如果是离线模式,不跳转
204 if (is_offline.value) { 220 if (is_offline.value) {
205 Taro.showToast({ 221 Taro.showToast({
...@@ -208,16 +224,18 @@ const toBooking = () => { // 跳转到预约须知 ...@@ -208,16 +224,18 @@ const toBooking = () => { // 跳转到预约须知
208 }) 224 })
209 return 225 return
210 } 226 }
211 - go('/notice'); 227 + go('/notice')
212 } 228 }
213 229
214 -const toCode = () => { // 跳转到预约码 230 +const toCode = () => {
231 + // 跳转到预约码
215 Taro.redirectTo({ 232 Taro.redirectTo({
216 url: '/pages/bookingCode/index' 233 url: '/pages/bookingCode/index'
217 }) 234 })
218 } 235 }
219 236
220 -const toMy = () => { // 跳转到我的 237 +const toMy = () => {
238 + // 跳转到我的
221 Taro.redirectTo({ 239 Taro.redirectTo({
222 url: '/pages/me/index' 240 url: '/pages/me/index'
223 }) 241 })
...@@ -225,9 +243,13 @@ const toMy = () => { // 跳转到我的 ...@@ -225,9 +243,13 @@ const toMy = () => { // 跳转到我的
225 243
226 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 } 244 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
227 245
228 -const on_nav_select = (key) => { 246 +const on_nav_select = key => {
229 - if (key === 'code') return toCode() 247 + if (key === 'code') {
230 - if (key === 'me') return toMy() 248 + return toCode()
249 + }
250 + if (key === 'me') {
251 + return toMy()
252 + }
231 } 253 }
232 254
233 useShareAppMessage(() => { 255 useShareAppMessage(() => {
...@@ -236,7 +258,6 @@ useShareAppMessage(() => { ...@@ -236,7 +258,6 @@ useShareAppMessage(() => {
236 path: '/pages/index/index' 258 path: '/pages/index/index'
237 } 259 }
238 }) 260 })
239 -
240 </script> 261 </script>
241 262
242 <style lang="less"> 263 <style lang="less">
...@@ -248,7 +269,7 @@ useShareAppMessage(() => { ...@@ -248,7 +269,7 @@ useShareAppMessage(() => {
248 background-size: cover; /* 确保背景覆盖 */ 269 background-size: cover; /* 确保背景覆盖 */
249 270
250 &.is-offline { 271 &.is-offline {
251 - background-color: #F3EEE3; 272 + background-color: #f3eee3;
252 } 273 }
253 274
254 .offline-banner { 275 .offline-banner {
...@@ -258,7 +279,7 @@ useShareAppMessage(() => { ...@@ -258,7 +279,7 @@ useShareAppMessage(() => {
258 right: 24rpx; 279 right: 24rpx;
259 z-index: 10; 280 z-index: 10;
260 background: rgba(255, 255, 255, 0.88); 281 background: rgba(255, 255, 255, 0.88);
261 - color: #A67939; 282 + color: #a67939;
262 border: 2rpx solid rgba(166, 121, 57, 0.25); 283 border: 2rpx solid rgba(166, 121, 57, 0.25);
263 box-shadow: 0 12rpx 30rpx rgba(166, 121, 57, 0.12); 284 box-shadow: 0 12rpx 30rpx rgba(166, 121, 57, 0.12);
264 backdrop-filter: blur(6px); 285 backdrop-filter: blur(6px);
...@@ -279,30 +300,30 @@ useShareAppMessage(() => { ...@@ -279,30 +300,30 @@ useShareAppMessage(() => {
279 display: flex; 300 display: flex;
280 justify-content: center; 301 justify-content: center;
281 align-items: center; 302 align-items: center;
282 - background-color: #A67939; 303 + background-color: #a67939;
283 border-radius: 14rpx; 304 border-radius: 14rpx;
284 - color: #FFFFFF; 305 + color: #ffffff;
285 padding: 22rpx 128rpx; 306 padding: 22rpx 128rpx;
286 - border: 2rpx solid #A67939; 307 + border: 2rpx solid #a67939;
287 } 308 }
288 .record { 309 .record {
289 display: flex; 310 display: flex;
290 justify-content: center; 311 justify-content: center;
291 align-items: center; 312 align-items: center;
292 - color: #A67939; 313 + color: #a67939;
293 border-radius: 14rpx; 314 border-radius: 14rpx;
294 padding: 22rpx 128rpx; 315 padding: 22rpx 128rpx;
295 - border: 2rpx solid #A67939; 316 + border: 2rpx solid #a67939;
296 margin-top: 48rpx; 317 margin-top: 48rpx;
297 } 318 }
298 .search { 319 .search {
299 display: flex; 320 display: flex;
300 justify-content: center; 321 justify-content: center;
301 align-items: center; 322 align-items: center;
302 - color: #A67939; 323 + color: #a67939;
303 border-radius: 14rpx; 324 border-radius: 14rpx;
304 padding: 22rpx 128rpx; 325 padding: 22rpx 128rpx;
305 - border: 2rpx solid #A67939; 326 + border: 2rpx solid #a67939;
306 margin-top: 48rpx; 327 margin-top: 48rpx;
307 } 328 }
308 } 329 }
...@@ -327,7 +348,7 @@ useShareAppMessage(() => { ...@@ -327,7 +348,7 @@ useShareAppMessage(() => {
327 height: 230rpx; 348 height: 230rpx;
328 width: 230rpx; 349 width: 230rpx;
329 border-radius: 50%; 350 border-radius: 50%;
330 - background-color: #A67939; 351 + background-color: #a67939;
331 display: flex; 352 display: flex;
332 align-items: center; 353 align-items: center;
333 justify-content: center; 354 justify-content: center;
...@@ -348,7 +369,8 @@ useShareAppMessage(() => { ...@@ -348,7 +369,8 @@ useShareAppMessage(() => {
348 } 369 }
349 .my-swipe { 370 .my-swipe {
350 height: 400rpx; 371 height: 400rpx;
351 - swiper-item { /* Taro swiper-item 编译后 */ 372 + swiper-item {
373 + /* Taro swiper-item 编译后 */
352 height: 400rpx; 374 height: 400rpx;
353 width: 750rpx; 375 width: 750rpx;
354 background-size: cover; 376 background-size: cover;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 <view class="my-page"> 2 <view class="my-page">
3 <view v-for="(item, index) in menu_list" :key="index" class="my-item" @tap="on_menu_tap(item)"> 3 <view v-for="(item, index) in menu_list" :key="index" class="my-item" @tap="on_menu_tap(item)">
4 <view class="left"> 4 <view class="left">
5 - <image :src="item.icon" style="width: 38rpx; height: 38rpx; margin-right: 16rpx;" /> 5 + <image :src="item.icon" style="width: 38rpx; height: 38rpx; margin-right: 16rpx" />
6 {{ item.name }} 6 {{ item.name }}
7 </view> 7 </view>
8 <view> 8 <view>
...@@ -34,12 +34,17 @@ import { is_usable_network, get_network_type } from '@/utils/network' ...@@ -34,12 +34,17 @@ import { is_usable_network, get_network_type } from '@/utils/network'
34 import icon_booking from '@/assets/images/预约记录@2x.png' 34 import icon_booking from '@/assets/images/预约记录@2x.png'
35 import icon_visitor from '@/assets/images/我的01@2x.png' 35 import icon_visitor from '@/assets/images/我的01@2x.png'
36 import icon_invite from '@/assets/images/二维码@2x2.png' 36 import icon_invite from '@/assets/images/二维码@2x2.png'
37 -import { weak_network_text, get_weak_network_modal_go_offline_records_options } from '@/utils/uiText' 37 +import {
38 + weak_network_text,
39 + get_weak_network_modal_go_offline_records_options
40 +} from '@/utils/uiText'
38 41
39 -const go = useGo(); 42 +const go = useGo()
40 43
41 -const on_menu_tap = async (item) => { 44 +const on_menu_tap = async item => {
42 - if (!item?.to) return 45 + if (!item?.to) {
46 + return
47 + }
43 48
44 if (item.to === '/pages/bookingList/index') { 49 if (item.to === '/pages/bookingList/index') {
45 const network_type = await get_network_type() 50 const network_type = await get_network_type()
...@@ -60,12 +65,14 @@ const on_menu_tap = async (item) => { ...@@ -60,12 +65,14 @@ const on_menu_tap = async (item) => {
60 go(item.to) 65 go(item.to)
61 } 66 }
62 67
63 -const toCode = () => { // 跳转到预约码 68 +const toCode = () => {
69 + // 跳转到预约码
64 Taro.redirectTo({ 70 Taro.redirectTo({
65 url: '/pages/bookingCode/index' 71 url: '/pages/bookingCode/index'
66 }) 72 })
67 } 73 }
68 -const toHome = () => { // 跳转到首页 74 +const toHome = () => {
75 + // 跳转到首页
69 Taro.redirectTo({ 76 Taro.redirectTo({
70 url: '/pages/index/index' 77 url: '/pages/index/index'
71 }) 78 })
...@@ -73,43 +80,51 @@ const toHome = () => { // 跳转到首页 ...@@ -73,43 +80,51 @@ const toHome = () => { // 跳转到首页
73 80
74 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 } 81 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
75 82
76 -const on_nav_select = (key) => { 83 +const on_nav_select = key => {
77 - if (key === 'home') return toHome() 84 + if (key === 'home') {
78 - if (key === 'code') return toCode() 85 + return toHome()
86 + }
87 + if (key === 'code') {
88 + return toCode()
89 + }
79 } 90 }
80 91
81 -const menu_list = [{ 92 +const menu_list = [
93 + {
82 icon: icon_booking, 94 icon: icon_booking,
83 name: '预约记录', 95 name: '预约记录',
84 to: '/pages/bookingList/index' 96 to: '/pages/bookingList/index'
85 -}, { 97 + },
98 + {
86 icon: icon_visitor, 99 icon: icon_visitor,
87 name: '参观者', 100 name: '参观者',
88 to: '/pages/visitorList/index' 101 to: '/pages/visitorList/index'
89 -}, { 102 + },
103 + {
90 icon: icon_invite, 104 icon: icon_invite,
91 name: '邀请码', 105 name: '邀请码',
92 to: '/pages/search/index' 106 to: '/pages/search/index'
93 -}] 107 + }
108 +]
94 </script> 109 </script>
95 110
96 <style lang="less"> 111 <style lang="less">
97 .my-page { 112 .my-page {
98 position: relative; 113 position: relative;
99 min-height: 100vh; 114 min-height: 100vh;
100 - background-color: #F6F6F6; 115 + background-color: #f6f6f6;
101 padding: 32rpx; 116 padding: 32rpx;
102 117
103 .my-item { 118 .my-item {
104 padding: 32rpx; 119 padding: 32rpx;
105 display: flex; 120 display: flex;
106 - justify-content:space-between; 121 + justify-content: space-between;
107 align-items: center; 122 align-items: center;
108 margin-bottom: 32rpx; 123 margin-bottom: 32rpx;
109 - background-color: #FFF; 124 + background-color: #fff;
110 border-radius: 10rpx; 125 border-radius: 10rpx;
111 .left { 126 .left {
112 - color: #A67939; 127 + color: #a67939;
113 display: flex; 128 display: flex;
114 align-items: center; 129 align-items: center;
115 } 130 }
......
1 export default { 1 export default {
2 - navigationBarTitleText: 'NFC测试', 2 + navigationBarTitleText: 'NFC测试'
3 } 3 }
......
This diff is collapsed. Click to expand it.
...@@ -8,12 +8,14 @@ ...@@ -8,12 +8,14 @@
8 <template> 8 <template>
9 <view class="notice-page"> 9 <view class="notice-page">
10 <view class="content"> 10 <view class="content">
11 - <view style="text-align: center; font-size: 35rpx; margin-bottom: 16rpx;">温馨提示</view> 11 + <view style="text-align: center; font-size: 35rpx; margin-bottom: 16rpx">温馨提示</view>
12 <view> 12 <view>
13 为了您和他人的健康与安全,维护清净庄严的寺院环境,营造一个喜悦而祥和的节日氛围,请您留意并遵守以下注意事项: 13 为了您和他人的健康与安全,维护清净庄严的寺院环境,营造一个喜悦而祥和的节日氛围,请您留意并遵守以下注意事项:
14 </view> 14 </view>
15 - <view v-for="(item, index) in note_text" :key="index" style="margin-top: 16rpx;">{{ item }}</view> 15 + <view v-for="(item, index) in note_text" :key="index" style="margin-top: 16rpx">{{
16 - <view style="margin-top: 16rpx;">谢谢您的支持与配合。祝您新春吉祥、万事如意。</view> 16 + item
17 + }}</view>
18 + <view style="margin-top: 16rpx">谢谢您的支持与配合。祝您新春吉祥、万事如意。</view>
17 </view> 19 </view>
18 <view style="height: 256rpx"></view> 20 <view style="height: 256rpx"></view>
19 <view class="footer"> 21 <view class="footer">
...@@ -28,11 +30,11 @@ ...@@ -28,11 +30,11 @@
28 </template> 30 </template>
29 31
30 <script setup> 32 <script setup>
31 -import { ref } from "vue"; 33 +import { ref } from 'vue'
32 import Taro, { useDidShow } from '@tarojs/taro' 34 import Taro, { useDidShow } from '@tarojs/taro'
33 -import { useGo } from "@/hooks/useGo"; 35 +import { useGo } from '@/hooks/useGo'
34 36
35 -const go = useGo(); 37 +const go = useGo()
36 const note_text = [ 38 const note_text = [
37 '1、敬香贵在心诚,不在数量多少。三支清香,可表心诚。请带着虔诚心、恭敬心和清净心敬香礼佛。', 39 '1、敬香贵在心诚,不在数量多少。三支清香,可表心诚。请带着虔诚心、恭敬心和清净心敬香礼佛。',
38 '2、请不要自带香烛进寺院。山门殿两侧设有赠香处,凭香花券可免费领取三支清香。', 40 '2、请不要自带香烛进寺院。山门殿两侧设有赠香处,凭香花券可免费领取三支清香。',
...@@ -43,8 +45,8 @@ const note_text = [ ...@@ -43,8 +45,8 @@ const note_text = [
43 '7、请保管好自己随身携带的钱物,以免丢失给您带来麻烦。', 45 '7、请保管好自己随身携带的钱物,以免丢失给您带来麻烦。',
44 '8、您若有任何问题和困难,请向身边的法师或义工咨询、求助,或直接与客堂联系。电话:0512-65349545。', 46 '8、您若有任何问题和困难,请向身边的法师或义工咨询、求助,或直接与客堂联系。电话:0512-65349545。',
45 '9、预约如需退款,请在初七之后,到客堂办理。' 47 '9、预约如需退款,请在初七之后,到客堂办理。'
46 -]; 48 +]
47 -const checked = ref([]); 49 +const checked = ref([])
48 50
49 /** 51 /**
50 * @description 点击确认进入下一步 52 * @description 点击确认进入下一步
...@@ -52,19 +54,19 @@ const checked = ref([]); ...@@ -52,19 +54,19 @@ const checked = ref([]);
52 * @returns {void} 无返回值 54 * @returns {void} 无返回值
53 */ 55 */
54 const confirmBtn = () => { 56 const confirmBtn = () => {
55 - if (checked.value.includes("1")) { 57 + if (checked.value.includes('1')) {
56 - go("/booking"); 58 + go('/booking')
57 } else { 59 } else {
58 - Taro.showToast({ title: "请勾选同意须知", icon: "none" }); 60 + Taro.showToast({ title: '请勾选同意须知', icon: 'none' })
59 } 61 }
60 -}; 62 +}
61 </script> 63 </script>
62 64
63 <style lang="less"> 65 <style lang="less">
64 .notice-page { 66 .notice-page {
65 position: relative; 67 position: relative;
66 min-height: 100vh; 68 min-height: 100vh;
67 - background-color: #F6F6F6; 69 + background-color: #f6f6f6;
68 padding-top: 2rpx; // 防止 margin collapse 70 padding-top: 2rpx; // 防止 margin collapse
69 .content { 71 .content {
70 margin: 32rpx; 72 margin: 32rpx;
...@@ -79,16 +81,16 @@ const confirmBtn = () => { ...@@ -79,16 +81,16 @@ const confirmBtn = () => {
79 position: fixed; 81 position: fixed;
80 bottom: 0; 82 bottom: 0;
81 width: 750rpx; 83 width: 750rpx;
82 - background-color: #FFF; 84 + background-color: #fff;
83 display: flex; 85 display: flex;
84 flex-direction: column; 86 flex-direction: column;
85 padding: 32rpx; 87 padding: 32rpx;
86 box-sizing: border-box; 88 box-sizing: border-box;
87 - box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.12); 89 + box-shadow: 0 -10rpx 8rpx 0 rgba(0, 0, 0, 0.12);
88 90
89 .confirm-btn { 91 .confirm-btn {
90 - background-color: #A67939; 92 + background-color: #a67939;
91 - color: #FFF; 93 + color: #fff;
92 text-align: center; 94 text-align: center;
93 padding: 26rpx 0; 95 padding: 26rpx 0;
94 border-radius: 16rpx; 96 border-radius: 16rpx;
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.