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 3648 additions and 1601 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"
......
...@@ -108,6 +108,9 @@ importers: ...@@ -108,6 +108,9 @@ importers:
108 '@vue/compiler-sfc': 108 '@vue/compiler-sfc':
109 specifier: ^3.0.0 109 specifier: ^3.0.0
110 version: 3.5.26 110 version: 3.5.26
111 + '@vue/eslint-config-prettier':
112 + specifier: ^10.2.0
113 + version: 10.2.0(@types/eslint@9.6.1)(eslint@8.57.1)(prettier@3.8.1)
111 autoprefixer: 114 autoprefixer:
112 specifier: ^10.4.21 115 specifier: ^10.4.21
113 version: 10.4.23(postcss@8.5.6) 116 version: 10.4.23(postcss@8.5.6)
...@@ -122,13 +125,25 @@ importers: ...@@ -122,13 +125,25 @@ importers:
122 version: 8.57.1 125 version: 8.57.1
123 eslint-config-taro: 126 eslint-config-taro:
124 specifier: 4.1.9 127 specifier: 4.1.9
125 - version: 4.1.9(@babel/core@7.28.5)(eslint@8.57.1)(typescript@5.9.3) 128 + version: 4.1.9(@babel/core@7.28.5)(eslint-plugin-vue@10.7.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(vue-eslint-parser@10.2.0(eslint@8.57.1)))(eslint@8.57.1)(typescript@5.9.3)
129 + eslint-plugin-vue:
130 + specifier: ^10.7.0
131 + version: 10.7.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(vue-eslint-parser@10.2.0(eslint@8.57.1))
132 + husky:
133 + specifier: ^9.1.7
134 + version: 9.1.7
126 less: 135 less:
127 specifier: ^4.2.0 136 specifier: ^4.2.0
128 version: 4.5.1 137 version: 4.5.1
138 + lint-staged:
139 + specifier: ^16.2.7
140 + version: 16.2.7
129 postcss: 141 postcss:
130 specifier: ^8.5.6 142 specifier: ^8.5.6
131 version: 8.5.6 143 version: 8.5.6
144 + prettier:
145 + specifier: ^3.8.1
146 + version: 3.8.1
132 sass: 147 sass:
133 specifier: ^1.78.0 148 specifier: ^1.78.0
134 version: 1.97.2 149 version: 1.97.2
...@@ -141,6 +156,9 @@ importers: ...@@ -141,6 +156,9 @@ importers:
141 unplugin-vue-components: 156 unplugin-vue-components:
142 specifier: ^0.26.0 157 specifier: ^0.26.0
143 version: 0.26.0(@babel/parser@7.28.5)(rollup@3.29.5)(vue@3.5.26(typescript@5.9.3)) 158 version: 0.26.0(@babel/parser@7.28.5)(rollup@3.29.5)(vue@3.5.26(typescript@5.9.3))
159 + vue-eslint-parser:
160 + specifier: ^10.2.0
161 + version: 10.2.0(eslint@8.57.1)
144 vue-loader: 162 vue-loader:
145 specifier: ^17.0.0 163 specifier: ^17.0.0
146 version: 17.4.2(@vue/compiler-sfc@3.5.26)(vue@3.5.26(typescript@5.9.3))(webpack@5.91.0(@swc/core@1.3.96)) 164 version: 17.4.2(@vue/compiler-sfc@3.5.26)(vue@3.5.26(typescript@5.9.3))(webpack@5.91.0(@swc/core@1.3.96))
...@@ -1535,6 +1553,10 @@ packages: ...@@ -1535,6 +1553,10 @@ packages:
1535 resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 1553 resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
1536 engines: {node: '>=14'} 1554 engines: {node: '>=14'}
1537 1555
1556 + '@pkgr/core@0.2.9':
1557 + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
1558 + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
1559 +
1538 '@rnx-kit/babel-preset-metro-react-native@1.1.8': 1560 '@rnx-kit/babel-preset-metro-react-native@1.1.8':
1539 resolution: {integrity: sha512-8DotuBK1ZgV0H/tmCmtW/3ofA7JR/8aPqSu9lKnuqwBfq4bxz+w1sMyfFl89m4teWlkhgyczWBGD6NCLqTgi9A==} 1561 resolution: {integrity: sha512-8DotuBK1ZgV0H/tmCmtW/3ofA7JR/8aPqSu9lKnuqwBfq4bxz+w1sMyfFl89m4teWlkhgyczWBGD6NCLqTgi9A==}
1540 peerDependencies: 1562 peerDependencies:
...@@ -2225,6 +2247,12 @@ packages: ...@@ -2225,6 +2247,12 @@ packages:
2225 '@vue/devtools-shared@7.7.9': 2247 '@vue/devtools-shared@7.7.9':
2226 resolution: {integrity: sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==} 2248 resolution: {integrity: sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==}
2227 2249
2250 + '@vue/eslint-config-prettier@10.2.0':
2251 + resolution: {integrity: sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==}
2252 + peerDependencies:
2253 + eslint: '>= 8.21.0'
2254 + prettier: '>= 3.0.0'
2255 +
2228 '@vue/reactivity@3.5.26': 2256 '@vue/reactivity@3.5.26':
2229 resolution: {integrity: sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==} 2257 resolution: {integrity: sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==}
2230 2258
...@@ -2385,6 +2413,10 @@ packages: ...@@ -2385,6 +2413,10 @@ packages:
2385 resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} 2413 resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
2386 engines: {node: '>=8'} 2414 engines: {node: '>=8'}
2387 2415
2416 + ansi-escapes@7.2.0:
2417 + resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==}
2418 + engines: {node: '>=18'}
2419 +
2388 ansi-html-community@0.0.8: 2420 ansi-html-community@0.0.8:
2389 resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} 2421 resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==}
2390 engines: {'0': node >= 0.8.0} 2422 engines: {'0': node >= 0.8.0}
...@@ -2741,6 +2773,10 @@ packages: ...@@ -2741,6 +2773,10 @@ packages:
2741 resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} 2773 resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
2742 engines: {node: '>=8'} 2774 engines: {node: '>=8'}
2743 2775
2776 + cli-cursor@5.0.0:
2777 + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
2778 + engines: {node: '>=18'}
2779 +
2744 cli-highlight@2.1.11: 2780 cli-highlight@2.1.11:
2745 resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} 2781 resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==}
2746 engines: {node: '>=8.0.0', npm: '>=5.0.0'} 2782 engines: {node: '>=8.0.0', npm: '>=5.0.0'}
...@@ -2750,6 +2786,10 @@ packages: ...@@ -2750,6 +2786,10 @@ packages:
2750 resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} 2786 resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
2751 engines: {node: '>=6'} 2787 engines: {node: '>=6'}
2752 2788
2789 + cli-truncate@5.1.1:
2790 + resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==}
2791 + engines: {node: '>=20'}
2792 +
2753 cli-width@3.0.0: 2793 cli-width@3.0.0:
2754 resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} 2794 resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==}
2755 engines: {node: '>= 10'} 2795 engines: {node: '>= 10'}
...@@ -2791,6 +2831,10 @@ packages: ...@@ -2791,6 +2831,10 @@ packages:
2791 resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 2831 resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
2792 engines: {node: '>= 0.8'} 2832 engines: {node: '>= 0.8'}
2793 2833
2834 + commander@14.0.2:
2835 + resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==}
2836 + engines: {node: '>=20'}
2837 +
2794 commander@2.20.3: 2838 commander@2.20.3:
2795 resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 2839 resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
2796 2840
...@@ -3285,6 +3329,9 @@ packages: ...@@ -3285,6 +3329,9 @@ packages:
3285 electron-to-chromium@1.5.267: 3329 electron-to-chromium@1.5.267:
3286 resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} 3330 resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
3287 3331
3332 + emoji-regex@10.6.0:
3333 + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
3334 +
3288 emoji-regex@8.0.0: 3335 emoji-regex@8.0.0:
3289 resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 3336 resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
3290 3337
...@@ -3330,6 +3377,10 @@ packages: ...@@ -3330,6 +3377,10 @@ packages:
3330 engines: {node: '>=4'} 3377 engines: {node: '>=4'}
3331 hasBin: true 3378 hasBin: true
3332 3379
3380 + environment@1.1.0:
3381 + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
3382 + engines: {node: '>=18'}
3383 +
3333 errno@0.1.8: 3384 errno@0.1.8:
3334 resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} 3385 resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==}
3335 hasBin: true 3386 hasBin: true
...@@ -3401,6 +3452,12 @@ packages: ...@@ -3401,6 +3452,12 @@ packages:
3401 resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 3452 resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
3402 engines: {node: '>=10'} 3453 engines: {node: '>=10'}
3403 3454
3455 + eslint-config-prettier@10.1.8:
3456 + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
3457 + hasBin: true
3458 + peerDependencies:
3459 + eslint: '>=7.0.0'
3460 +
3404 eslint-config-taro@4.1.9: 3461 eslint-config-taro@4.1.9:
3405 resolution: {integrity: sha512-vPtiWIIb4P2RxuGpTQvRiWNrxuKZvhVl/eSHCyxa6IXo26bTOLcg3Hv5imaDi8NRshqLT0jqcf85dWWBYxBxpw==} 3462 resolution: {integrity: sha512-vPtiWIIb4P2RxuGpTQvRiWNrxuKZvhVl/eSHCyxa6IXo26bTOLcg3Hv5imaDi8NRshqLT0jqcf85dWWBYxBxpw==}
3406 engines: {node: '>= 18'} 3463 engines: {node: '>= 18'}
...@@ -3451,6 +3508,34 @@ packages: ...@@ -3451,6 +3508,34 @@ packages:
3451 '@typescript-eslint/parser': 3508 '@typescript-eslint/parser':
3452 optional: true 3509 optional: true
3453 3510
3511 + eslint-plugin-prettier@5.5.5:
3512 + resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==}
3513 + engines: {node: ^14.18.0 || >=16.0.0}
3514 + peerDependencies:
3515 + '@types/eslint': '>=8.0.0'
3516 + eslint: '>=8.0.0'
3517 + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0'
3518 + prettier: '>=3.0.0'
3519 + peerDependenciesMeta:
3520 + '@types/eslint':
3521 + optional: true
3522 + eslint-config-prettier:
3523 + optional: true
3524 +
3525 + eslint-plugin-vue@10.7.0:
3526 + resolution: {integrity: sha512-r2XFCK4qlo1sxEoAMIoTTX0PZAdla0JJDt1fmYiworZUX67WeEGqm+JbyAg3M+pGiJ5U6Mp5WQbontXWtIW7TA==}
3527 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
3528 + peerDependencies:
3529 + '@stylistic/eslint-plugin': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
3530 + '@typescript-eslint/parser': ^7.0.0 || ^8.0.0
3531 + eslint: ^8.57.0 || ^9.0.0
3532 + vue-eslint-parser: ^10.0.0
3533 + peerDependenciesMeta:
3534 + '@stylistic/eslint-plugin':
3535 + optional: true
3536 + '@typescript-eslint/parser':
3537 + optional: true
3538 +
3454 eslint-scope@5.1.1: 3539 eslint-scope@5.1.1:
3455 resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} 3540 resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
3456 engines: {node: '>=8.0.0'} 3541 engines: {node: '>=8.0.0'}
...@@ -3459,6 +3544,10 @@ packages: ...@@ -3459,6 +3544,10 @@ packages:
3459 resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} 3544 resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
3460 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 3545 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
3461 3546
3547 + eslint-scope@8.4.0:
3548 + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
3549 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
3550 +
3462 eslint-visitor-keys@2.1.0: 3551 eslint-visitor-keys@2.1.0:
3463 resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} 3552 resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==}
3464 engines: {node: '>=10'} 3553 engines: {node: '>=10'}
...@@ -3467,6 +3556,10 @@ packages: ...@@ -3467,6 +3556,10 @@ packages:
3467 resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 3556 resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
3468 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 3557 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
3469 3558
3559 + eslint-visitor-keys@4.2.1:
3560 + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
3561 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
3562 +
3470 eslint@8.41.0: 3563 eslint@8.41.0:
3471 resolution: {integrity: sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==} 3564 resolution: {integrity: sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==}
3472 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 3565 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
...@@ -3479,6 +3572,10 @@ packages: ...@@ -3479,6 +3572,10 @@ packages:
3479 deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. 3572 deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
3480 hasBin: true 3573 hasBin: true
3481 3574
3575 + espree@10.4.0:
3576 + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
3577 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
3578 +
3482 espree@9.6.1: 3579 espree@9.6.1:
3483 resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} 3580 resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
3484 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 3581 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
...@@ -3513,6 +3610,9 @@ packages: ...@@ -3513,6 +3610,9 @@ packages:
3513 eventemitter3@4.0.7: 3610 eventemitter3@4.0.7:
3514 resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} 3611 resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
3515 3612
3613 + eventemitter3@5.0.4:
3614 + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
3615 +
3516 events@3.3.0: 3616 events@3.3.0:
3517 resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} 3617 resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
3518 engines: {node: '>=0.8.x'} 3618 engines: {node: '>=0.8.x'}
...@@ -3542,6 +3642,9 @@ packages: ...@@ -3542,6 +3642,9 @@ packages:
3542 fast-deep-equal@3.1.3: 3642 fast-deep-equal@3.1.3:
3543 resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 3643 resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
3544 3644
3645 + fast-diff@1.3.0:
3646 + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
3647 +
3545 fast-glob@3.3.3: 3648 fast-glob@3.3.3:
3546 resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 3649 resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
3547 engines: {node: '>=8.6.0'} 3650 engines: {node: '>=8.6.0'}
...@@ -3731,6 +3834,10 @@ packages: ...@@ -3731,6 +3834,10 @@ packages:
3731 resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 3834 resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
3732 engines: {node: 6.* || 8.* || >= 10.*} 3835 engines: {node: 6.* || 8.* || >= 10.*}
3733 3836
3837 + get-east-asian-width@1.4.0:
3838 + resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
3839 + engines: {node: '>=18'}
3840 +
3734 get-intrinsic@1.3.0: 3841 get-intrinsic@1.3.0:
3735 resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} 3842 resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
3736 engines: {node: '>= 0.4'} 3843 engines: {node: '>= 0.4'}
...@@ -3989,6 +4096,11 @@ packages: ...@@ -3989,6 +4096,11 @@ packages:
3989 resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} 4096 resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
3990 engines: {node: '>=10.17.0'} 4097 engines: {node: '>=10.17.0'}
3991 4098
4099 + husky@9.1.7:
4100 + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
4101 + engines: {node: '>=18'}
4102 + hasBin: true
4103 +
3992 iconv-lite@0.4.24: 4104 iconv-lite@0.4.24:
3993 resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 4105 resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
3994 engines: {node: '>=0.10.0'} 4106 engines: {node: '>=0.10.0'}
...@@ -4140,6 +4252,10 @@ packages: ...@@ -4140,6 +4252,10 @@ packages:
4140 resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 4252 resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
4141 engines: {node: '>=8'} 4253 engines: {node: '>=8'}
4142 4254
4255 + is-fullwidth-code-point@5.1.0:
4256 + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
4257 + engines: {node: '>=18'}
4258 +
4143 is-generator-function@1.1.2: 4259 is-generator-function@1.1.2:
4144 resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} 4260 resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
4145 engines: {node: '>= 0.4'} 4261 engines: {node: '>= 0.4'}
...@@ -4501,6 +4617,15 @@ packages: ...@@ -4501,6 +4617,15 @@ packages:
4501 lines-and-columns@1.2.4: 4617 lines-and-columns@1.2.4:
4502 resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 4618 resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
4503 4619
4620 + lint-staged@16.2.7:
4621 + resolution: {integrity: sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==}
4622 + engines: {node: '>=20.17'}
4623 + hasBin: true
4624 +
4625 + listr2@9.0.5:
4626 + resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
4627 + engines: {node: '>=20.0.0'}
4628 +
4504 loader-runner@4.3.1: 4629 loader-runner@4.3.1:
4505 resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} 4630 resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==}
4506 engines: {node: '>=6.11.5'} 4631 engines: {node: '>=6.11.5'}
...@@ -4562,6 +4687,10 @@ packages: ...@@ -4562,6 +4687,10 @@ packages:
4562 resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} 4687 resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
4563 engines: {node: '>=10'} 4688 engines: {node: '>=10'}
4564 4689
4690 + log-update@6.1.0:
4691 + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
4692 + engines: {node: '>=18'}
4693 +
4565 loglevel-plugin-prefix@0.8.4: 4694 loglevel-plugin-prefix@0.8.4:
4566 resolution: {integrity: sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==} 4695 resolution: {integrity: sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==}
4567 4696
...@@ -4676,6 +4805,10 @@ packages: ...@@ -4676,6 +4805,10 @@ packages:
4676 resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} 4805 resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
4677 engines: {node: '>=6'} 4806 engines: {node: '>=6'}
4678 4807
4808 + mimic-function@5.0.1:
4809 + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
4810 + engines: {node: '>=18'}
4811 +
4679 mimic-response@1.0.1: 4812 mimic-response@1.0.1:
4680 resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} 4813 resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
4681 engines: {node: '>=4'} 4814 engines: {node: '>=4'}
...@@ -4755,6 +4888,10 @@ packages: ...@@ -4755,6 +4888,10 @@ packages:
4755 mz@2.7.0: 4888 mz@2.7.0:
4756 resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 4889 resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
4757 4890
4891 + nano-spawn@2.0.0:
4892 + resolution: {integrity: sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==}
4893 + engines: {node: '>=20.17'}
4894 +
4758 nanoid@3.3.11: 4895 nanoid@3.3.11:
4759 resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 4896 resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
4760 engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 4897 engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
...@@ -4885,6 +5022,10 @@ packages: ...@@ -4885,6 +5022,10 @@ packages:
4885 resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} 5022 resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
4886 engines: {node: '>=6'} 5023 engines: {node: '>=6'}
4887 5024
5025 + onetime@7.0.0:
5026 + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
5027 + engines: {node: '>=18'}
5028 +
4888 open@8.4.2: 5029 open@8.4.2:
4889 resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} 5030 resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
4890 engines: {node: '>=12'} 5031 engines: {node: '>=12'}
...@@ -5063,6 +5204,11 @@ packages: ...@@ -5063,6 +5204,11 @@ packages:
5063 resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} 5204 resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
5064 engines: {node: '>=12'} 5205 engines: {node: '>=12'}
5065 5206
5207 + pidtree@0.6.0:
5208 + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
5209 + engines: {node: '>=0.10'}
5210 + hasBin: true
5211 +
5066 pify@2.3.0: 5212 pify@2.3.0:
5067 resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} 5213 resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
5068 engines: {node: '>=0.10.0'} 5214 engines: {node: '>=0.10.0'}
...@@ -5593,6 +5739,15 @@ packages: ...@@ -5593,6 +5739,15 @@ packages:
5593 resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==} 5739 resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==}
5594 engines: {node: '>=4'} 5740 engines: {node: '>=4'}
5595 5741
5742 + prettier-linter-helpers@1.0.1:
5743 + resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==}
5744 + engines: {node: '>=6.0.0'}
5745 +
5746 + prettier@3.8.1:
5747 + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==}
5748 + engines: {node: '>=14'}
5749 + hasBin: true
5750 +
5596 pretty-bytes@5.6.0: 5751 pretty-bytes@5.6.0:
5597 resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} 5752 resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
5598 engines: {node: '>=6'} 5753 engines: {node: '>=6'}
...@@ -5800,6 +5955,10 @@ packages: ...@@ -5800,6 +5955,10 @@ packages:
5800 resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} 5955 resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
5801 engines: {node: '>=8'} 5956 engines: {node: '>=8'}
5802 5957
5958 + restore-cursor@5.1.0:
5959 + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
5960 + engines: {node: '>=18'}
5961 +
5803 retry@0.13.1: 5962 retry@0.13.1:
5804 resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} 5963 resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
5805 engines: {node: '>= 4'} 5964 engines: {node: '>= 4'}
...@@ -6033,6 +6192,10 @@ packages: ...@@ -6033,6 +6192,10 @@ packages:
6033 resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} 6192 resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
6034 engines: {node: '>=14.16'} 6193 engines: {node: '>=14.16'}
6035 6194
6195 + slice-ansi@7.1.2:
6196 + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
6197 + engines: {node: '>=18'}
6198 +
6036 snake-case@3.0.4: 6199 snake-case@3.0.4:
6037 resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} 6200 resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==}
6038 6201
...@@ -6110,6 +6273,10 @@ packages: ...@@ -6110,6 +6273,10 @@ packages:
6110 resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} 6273 resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==}
6111 engines: {node: '>=0.10.0'} 6274 engines: {node: '>=0.10.0'}
6112 6275
6276 + string-argv@0.3.2:
6277 + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
6278 + engines: {node: '>=0.6.19'}
6279 +
6113 string-width@4.2.3: 6280 string-width@4.2.3:
6114 resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 6281 resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
6115 engines: {node: '>=8'} 6282 engines: {node: '>=8'}
...@@ -6118,6 +6285,14 @@ packages: ...@@ -6118,6 +6285,14 @@ packages:
6118 resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 6285 resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
6119 engines: {node: '>=12'} 6286 engines: {node: '>=12'}
6120 6287
6288 + string-width@7.2.0:
6289 + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
6290 + engines: {node: '>=18'}
6291 +
6292 + string-width@8.1.0:
6293 + resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==}
6294 + engines: {node: '>=20'}
6295 +
6121 string.fromcodepoint@0.2.1: 6296 string.fromcodepoint@0.2.1:
6122 resolution: {integrity: sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg==} 6297 resolution: {integrity: sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg==}
6123 6298
...@@ -6243,6 +6418,10 @@ packages: ...@@ -6243,6 +6418,10 @@ packages:
6243 symbol-tree@3.2.4: 6418 symbol-tree@3.2.4:
6244 resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} 6419 resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
6245 6420
6421 + synckit@0.11.12:
6422 + resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==}
6423 + engines: {node: ^14.18.0 || >=16.0.0}
6424 +
6246 tailwindcss-config@1.1.3: 6425 tailwindcss-config@1.1.3:
6247 resolution: {integrity: sha512-7AN01Cwz2vd/vl6nKwoR0y/KlgpbKBREp1Q+MHJw8QF53AueVRFgU2Cqq0yhIQ4nC2wGvEJtlBCTeKYPX3TCXQ==} 6426 resolution: {integrity: sha512-7AN01Cwz2vd/vl6nKwoR0y/KlgpbKBREp1Q+MHJw8QF53AueVRFgU2Cqq0yhIQ4nC2wGvEJtlBCTeKYPX3TCXQ==}
6248 6427
...@@ -6558,6 +6737,12 @@ packages: ...@@ -6558,6 +6737,12 @@ packages:
6558 engines: {node: '>=6.0'} 6737 engines: {node: '>=6.0'}
6559 hasBin: true 6738 hasBin: true
6560 6739
6740 + vue-eslint-parser@10.2.0:
6741 + resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==}
6742 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
6743 + peerDependencies:
6744 + eslint: ^8.57.0 || ^9.0.0
6745 +
6561 vue-loader@17.4.2: 6746 vue-loader@17.4.2:
6562 resolution: {integrity: sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==} 6747 resolution: {integrity: sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==}
6563 peerDependencies: 6748 peerDependencies:
...@@ -6726,6 +6911,10 @@ packages: ...@@ -6726,6 +6911,10 @@ packages:
6726 resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 6911 resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
6727 engines: {node: '>=12'} 6912 engines: {node: '>=12'}
6728 6913
6914 + wrap-ansi@9.0.2:
6915 + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
6916 + engines: {node: '>=18'}
6917 +
6729 wrappy@1.0.2: 6918 wrappy@1.0.2:
6730 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 6919 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
6731 6920
...@@ -6741,6 +6930,10 @@ packages: ...@@ -6741,6 +6930,10 @@ packages:
6741 utf-8-validate: 6930 utf-8-validate:
6742 optional: true 6931 optional: true
6743 6932
6933 + xml-name-validator@4.0.0:
6934 + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
6935 + engines: {node: '>=12'}
6936 +
6744 xml-name-validator@5.0.0: 6937 xml-name-validator@5.0.0:
6745 resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} 6938 resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
6746 engines: {node: '>=18'} 6939 engines: {node: '>=18'}
...@@ -8220,6 +8413,8 @@ snapshots: ...@@ -8220,6 +8413,8 @@ snapshots:
8220 '@pkgjs/parseargs@0.11.0': 8413 '@pkgjs/parseargs@0.11.0':
8221 optional: true 8414 optional: true
8222 8415
8416 + '@pkgr/core@0.2.9': {}
8417 +
8223 '@rnx-kit/babel-preset-metro-react-native@1.1.8(@babel/core@7.28.5)(@babel/plugin-transform-typescript@7.28.5(@babel/core@7.28.5))(@babel/runtime@7.28.4)': 8418 '@rnx-kit/babel-preset-metro-react-native@1.1.8(@babel/core@7.28.5)(@babel/plugin-transform-typescript@7.28.5(@babel/core@7.28.5))(@babel/runtime@7.28.4)':
8224 dependencies: 8419 dependencies:
8225 '@babel/core': 7.28.5 8420 '@babel/core': 7.28.5
...@@ -9113,6 +9308,15 @@ snapshots: ...@@ -9113,6 +9308,15 @@ snapshots:
9113 dependencies: 9308 dependencies:
9114 rfdc: 1.4.1 9309 rfdc: 1.4.1
9115 9310
9311 + '@vue/eslint-config-prettier@10.2.0(@types/eslint@9.6.1)(eslint@8.57.1)(prettier@3.8.1)':
9312 + dependencies:
9313 + eslint: 8.57.1
9314 + eslint-config-prettier: 10.1.8(eslint@8.57.1)
9315 + eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.1)
9316 + prettier: 3.8.1
9317 + transitivePeerDependencies:
9318 + - '@types/eslint'
9319 +
9116 '@vue/reactivity@3.5.26': 9320 '@vue/reactivity@3.5.26':
9117 dependencies: 9321 dependencies:
9118 '@vue/shared': 3.5.26 9322 '@vue/shared': 3.5.26
...@@ -9311,6 +9515,10 @@ snapshots: ...@@ -9311,6 +9515,10 @@ snapshots:
9311 dependencies: 9515 dependencies:
9312 type-fest: 0.21.3 9516 type-fest: 0.21.3
9313 9517
9518 + ansi-escapes@7.2.0:
9519 + dependencies:
9520 + environment: 1.1.0
9521 +
9314 ansi-html-community@0.0.8: {} 9522 ansi-html-community@0.0.8: {}
9315 9523
9316 ansi-regex@5.0.1: {} 9524 ansi-regex@5.0.1: {}
...@@ -9765,6 +9973,10 @@ snapshots: ...@@ -9765,6 +9973,10 @@ snapshots:
9765 dependencies: 9973 dependencies:
9766 restore-cursor: 3.1.0 9974 restore-cursor: 3.1.0
9767 9975
9976 + cli-cursor@5.0.0:
9977 + dependencies:
9978 + restore-cursor: 5.1.0
9979 +
9768 cli-highlight@2.1.11: 9980 cli-highlight@2.1.11:
9769 dependencies: 9981 dependencies:
9770 chalk: 4.1.2 9982 chalk: 4.1.2
...@@ -9776,6 +9988,11 @@ snapshots: ...@@ -9776,6 +9988,11 @@ snapshots:
9776 9988
9777 cli-spinners@2.9.2: {} 9989 cli-spinners@2.9.2: {}
9778 9990
9991 + cli-truncate@5.1.1:
9992 + dependencies:
9993 + slice-ansi: 7.1.2
9994 + string-width: 8.1.0
9995 +
9779 cli-width@3.0.0: {} 9996 cli-width@3.0.0: {}
9780 9997
9781 cliui@6.0.0: 9998 cliui@6.0.0:
...@@ -9820,6 +10037,8 @@ snapshots: ...@@ -9820,6 +10037,8 @@ snapshots:
9820 dependencies: 10037 dependencies:
9821 delayed-stream: 1.0.0 10038 delayed-stream: 1.0.0
9822 10039
10040 + commander@14.0.2: {}
10041 +
9823 commander@2.20.3: {} 10042 commander@2.20.3: {}
9824 10043
9825 commander@4.1.1: {} 10044 commander@4.1.1: {}
...@@ -10343,6 +10562,8 @@ snapshots: ...@@ -10343,6 +10562,8 @@ snapshots:
10343 10562
10344 electron-to-chromium@1.5.267: {} 10563 electron-to-chromium@1.5.267: {}
10345 10564
10565 + emoji-regex@10.6.0: {}
10566 +
10346 emoji-regex@8.0.0: {} 10567 emoji-regex@8.0.0: {}
10347 10568
10348 emoji-regex@9.2.2: {} 10569 emoji-regex@9.2.2: {}
...@@ -10372,6 +10593,8 @@ snapshots: ...@@ -10372,6 +10593,8 @@ snapshots:
10372 10593
10373 envinfo@7.21.0: {} 10594 envinfo@7.21.0: {}
10374 10595
10596 + environment@1.1.0: {}
10597 +
10375 errno@0.1.8: 10598 errno@0.1.8:
10376 dependencies: 10599 dependencies:
10377 prr: 1.0.1 10600 prr: 1.0.1
...@@ -10538,13 +10761,19 @@ snapshots: ...@@ -10538,13 +10761,19 @@ snapshots:
10538 10761
10539 escape-string-regexp@4.0.0: {} 10762 escape-string-regexp@4.0.0: {}
10540 10763
10541 - eslint-config-taro@4.1.9(@babel/core@7.28.5)(eslint@8.57.1)(typescript@5.9.3): 10764 + eslint-config-prettier@10.1.8(eslint@8.57.1):
10765 + dependencies:
10766 + eslint: 8.57.1
10767 +
10768 + eslint-config-taro@4.1.9(@babel/core@7.28.5)(eslint-plugin-vue@10.7.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(vue-eslint-parser@10.2.0(eslint@8.57.1)))(eslint@8.57.1)(typescript@5.9.3):
10542 dependencies: 10769 dependencies:
10543 '@babel/eslint-parser': 7.28.5(@babel/core@7.28.5)(eslint@8.57.1) 10770 '@babel/eslint-parser': 7.28.5(@babel/core@7.28.5)(eslint@8.57.1)
10544 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) 10771 '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)
10545 '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.3) 10772 '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.3)
10546 eslint: 8.57.1 10773 eslint: 8.57.1
10547 eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1) 10774 eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)
10775 + optionalDependencies:
10776 + eslint-plugin-vue: 10.7.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(vue-eslint-parser@10.2.0(eslint@8.57.1))
10548 transitivePeerDependencies: 10777 transitivePeerDependencies:
10549 - '@babel/core' 10778 - '@babel/core'
10550 - eslint-import-resolver-typescript 10779 - eslint-import-resolver-typescript
...@@ -10599,6 +10828,29 @@ snapshots: ...@@ -10599,6 +10828,29 @@ snapshots:
10599 - eslint-import-resolver-webpack 10828 - eslint-import-resolver-webpack
10600 - supports-color 10829 - supports-color
10601 10830
10831 + eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.1):
10832 + dependencies:
10833 + eslint: 8.57.1
10834 + prettier: 3.8.1
10835 + prettier-linter-helpers: 1.0.1
10836 + synckit: 0.11.12
10837 + optionalDependencies:
10838 + '@types/eslint': 9.6.1
10839 + eslint-config-prettier: 10.1.8(eslint@8.57.1)
10840 +
10841 + eslint-plugin-vue@10.7.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(vue-eslint-parser@10.2.0(eslint@8.57.1)):
10842 + dependencies:
10843 + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
10844 + eslint: 8.57.1
10845 + natural-compare: 1.4.0
10846 + nth-check: 2.1.1
10847 + postcss-selector-parser: 7.1.1
10848 + semver: 7.7.3
10849 + vue-eslint-parser: 10.2.0(eslint@8.57.1)
10850 + xml-name-validator: 4.0.0
10851 + optionalDependencies:
10852 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.3)
10853 +
10602 eslint-scope@5.1.1: 10854 eslint-scope@5.1.1:
10603 dependencies: 10855 dependencies:
10604 esrecurse: 4.3.0 10856 esrecurse: 4.3.0
...@@ -10609,10 +10861,17 @@ snapshots: ...@@ -10609,10 +10861,17 @@ snapshots:
10609 esrecurse: 4.3.0 10861 esrecurse: 4.3.0
10610 estraverse: 5.3.0 10862 estraverse: 5.3.0
10611 10863
10864 + eslint-scope@8.4.0:
10865 + dependencies:
10866 + esrecurse: 4.3.0
10867 + estraverse: 5.3.0
10868 +
10612 eslint-visitor-keys@2.1.0: {} 10869 eslint-visitor-keys@2.1.0: {}
10613 10870
10614 eslint-visitor-keys@3.4.3: {} 10871 eslint-visitor-keys@3.4.3: {}
10615 10872
10873 + eslint-visitor-keys@4.2.1: {}
10874 +
10616 eslint@8.41.0: 10875 eslint@8.41.0:
10617 dependencies: 10876 dependencies:
10618 '@eslint-community/eslint-utils': 4.9.1(eslint@8.41.0) 10877 '@eslint-community/eslint-utils': 4.9.1(eslint@8.41.0)
...@@ -10700,6 +10959,12 @@ snapshots: ...@@ -10700,6 +10959,12 @@ snapshots:
10700 transitivePeerDependencies: 10959 transitivePeerDependencies:
10701 - supports-color 10960 - supports-color
10702 10961
10962 + espree@10.4.0:
10963 + dependencies:
10964 + acorn: 8.15.0
10965 + acorn-jsx: 5.3.2(acorn@8.15.0)
10966 + eslint-visitor-keys: 4.2.1
10967 +
10703 espree@9.6.1: 10968 espree@9.6.1:
10704 dependencies: 10969 dependencies:
10705 acorn: 8.15.0 10970 acorn: 8.15.0
...@@ -10726,6 +10991,8 @@ snapshots: ...@@ -10726,6 +10991,8 @@ snapshots:
10726 10991
10727 eventemitter3@4.0.7: {} 10992 eventemitter3@4.0.7: {}
10728 10993
10994 + eventemitter3@5.0.4: {}
10995 +
10729 events@3.3.0: {} 10996 events@3.3.0: {}
10730 10997
10731 execa@5.1.1: 10998 execa@5.1.1:
...@@ -10791,6 +11058,8 @@ snapshots: ...@@ -10791,6 +11058,8 @@ snapshots:
10791 11058
10792 fast-deep-equal@3.1.3: {} 11059 fast-deep-equal@3.1.3: {}
10793 11060
11061 + fast-diff@1.3.0: {}
11062 +
10794 fast-glob@3.3.3: 11063 fast-glob@3.3.3:
10795 dependencies: 11064 dependencies:
10796 '@nodelib/fs.stat': 2.0.5 11065 '@nodelib/fs.stat': 2.0.5
...@@ -10969,6 +11238,8 @@ snapshots: ...@@ -10969,6 +11238,8 @@ snapshots:
10969 11238
10970 get-caller-file@2.0.5: {} 11239 get-caller-file@2.0.5: {}
10971 11240
11241 + get-east-asian-width@1.4.0: {}
11242 +
10972 get-intrinsic@1.3.0: 11243 get-intrinsic@1.3.0:
10973 dependencies: 11244 dependencies:
10974 call-bind-apply-helpers: 1.0.2 11245 call-bind-apply-helpers: 1.0.2
...@@ -11311,6 +11582,8 @@ snapshots: ...@@ -11311,6 +11582,8 @@ snapshots:
11311 11582
11312 human-signals@2.1.0: {} 11583 human-signals@2.1.0: {}
11313 11584
11585 + husky@9.1.7: {}
11586 +
11314 iconv-lite@0.4.24: 11587 iconv-lite@0.4.24:
11315 dependencies: 11588 dependencies:
11316 safer-buffer: 2.1.2 11589 safer-buffer: 2.1.2
...@@ -11465,6 +11738,10 @@ snapshots: ...@@ -11465,6 +11738,10 @@ snapshots:
11465 11738
11466 is-fullwidth-code-point@3.0.0: {} 11739 is-fullwidth-code-point@3.0.0: {}
11467 11740
11741 + is-fullwidth-code-point@5.1.0:
11742 + dependencies:
11743 + get-east-asian-width: 1.4.0
11744 +
11468 is-generator-function@1.1.2: 11745 is-generator-function@1.1.2:
11469 dependencies: 11746 dependencies:
11470 call-bound: 1.0.4 11747 call-bound: 1.0.4
...@@ -11816,6 +12093,25 @@ snapshots: ...@@ -11816,6 +12093,25 @@ snapshots:
11816 12093
11817 lines-and-columns@1.2.4: {} 12094 lines-and-columns@1.2.4: {}
11818 12095
12096 + lint-staged@16.2.7:
12097 + dependencies:
12098 + commander: 14.0.2
12099 + listr2: 9.0.5
12100 + micromatch: 4.0.8
12101 + nano-spawn: 2.0.0
12102 + pidtree: 0.6.0
12103 + string-argv: 0.3.2
12104 + yaml: 2.8.2
12105 +
12106 + listr2@9.0.5:
12107 + dependencies:
12108 + cli-truncate: 5.1.1
12109 + colorette: 2.0.20
12110 + eventemitter3: 5.0.4
12111 + log-update: 6.1.0
12112 + rfdc: 1.4.1
12113 + wrap-ansi: 9.0.2
12114 +
11819 loader-runner@4.3.1: {} 12115 loader-runner@4.3.1: {}
11820 12116
11821 loader-utils@1.4.2: 12117 loader-utils@1.4.2:
...@@ -11872,6 +12168,14 @@ snapshots: ...@@ -11872,6 +12168,14 @@ snapshots:
11872 chalk: 4.1.2 12168 chalk: 4.1.2
11873 is-unicode-supported: 0.1.0 12169 is-unicode-supported: 0.1.0
11874 12170
12171 + log-update@6.1.0:
12172 + dependencies:
12173 + ansi-escapes: 7.2.0
12174 + cli-cursor: 5.0.0
12175 + slice-ansi: 7.1.2
12176 + strip-ansi: 7.1.2
12177 + wrap-ansi: 9.0.2
12178 +
11875 loglevel-plugin-prefix@0.8.4: {} 12179 loglevel-plugin-prefix@0.8.4: {}
11876 12180
11877 loglevel@1.9.2: {} 12181 loglevel@1.9.2: {}
...@@ -11958,6 +12262,8 @@ snapshots: ...@@ -11958,6 +12262,8 @@ snapshots:
11958 12262
11959 mimic-fn@2.1.0: {} 12263 mimic-fn@2.1.0: {}
11960 12264
12265 + mimic-function@5.0.1: {}
12266 +
11961 mimic-response@1.0.1: {} 12267 mimic-response@1.0.1: {}
11962 12268
11963 mini-css-extract-plugin@2.9.4(webpack@5.91.0(@swc/core@1.3.96)): 12269 mini-css-extract-plugin@2.9.4(webpack@5.91.0(@swc/core@1.3.96)):
...@@ -12040,6 +12346,8 @@ snapshots: ...@@ -12040,6 +12346,8 @@ snapshots:
12040 object-assign: 4.1.1 12346 object-assign: 4.1.1
12041 thenify-all: 1.6.0 12347 thenify-all: 1.6.0
12042 12348
12349 + nano-spawn@2.0.0: {}
12350 +
12043 nanoid@3.3.11: {} 12351 nanoid@3.3.11: {}
12044 12352
12045 native-request@1.1.2: 12353 native-request@1.1.2:
...@@ -12165,6 +12473,10 @@ snapshots: ...@@ -12165,6 +12473,10 @@ snapshots:
12165 dependencies: 12473 dependencies:
12166 mimic-fn: 2.1.0 12474 mimic-fn: 2.1.0
12167 12475
12476 + onetime@7.0.0:
12477 + dependencies:
12478 + mimic-function: 5.0.1
12479 +
12168 open@8.4.2: 12480 open@8.4.2:
12169 dependencies: 12481 dependencies:
12170 define-lazy-prop: 2.0.0 12482 define-lazy-prop: 2.0.0
...@@ -12335,6 +12647,8 @@ snapshots: ...@@ -12335,6 +12647,8 @@ snapshots:
12335 12647
12336 picomatch@4.0.3: {} 12648 picomatch@4.0.3: {}
12337 12649
12650 + pidtree@0.6.0: {}
12651 +
12338 pify@2.3.0: {} 12652 pify@2.3.0: {}
12339 12653
12340 pify@3.0.0: {} 12654 pify@3.0.0: {}
...@@ -12892,6 +13206,12 @@ snapshots: ...@@ -12892,6 +13206,12 @@ snapshots:
12892 13206
12893 prepend-http@2.0.0: {} 13207 prepend-http@2.0.0: {}
12894 13208
13209 + prettier-linter-helpers@1.0.1:
13210 + dependencies:
13211 + fast-diff: 1.3.0
13212 +
13213 + prettier@3.8.1: {}
13214 +
12895 pretty-bytes@5.6.0: {} 13215 pretty-bytes@5.6.0: {}
12896 13216
12897 pretty-error@4.0.0: 13217 pretty-error@4.0.0:
...@@ -13122,6 +13442,11 @@ snapshots: ...@@ -13122,6 +13442,11 @@ snapshots:
13122 onetime: 5.1.2 13442 onetime: 5.1.2
13123 signal-exit: 3.0.7 13443 signal-exit: 3.0.7
13124 13444
13445 + restore-cursor@5.1.0:
13446 + dependencies:
13447 + onetime: 7.0.0
13448 + signal-exit: 4.1.0
13449 +
13125 retry@0.13.1: {} 13450 retry@0.13.1: {}
13126 13451
13127 reusify@1.1.0: {} 13452 reusify@1.1.0: {}
...@@ -13388,6 +13713,11 @@ snapshots: ...@@ -13388,6 +13713,11 @@ snapshots:
13388 13713
13389 slash@5.1.0: {} 13714 slash@5.1.0: {}
13390 13715
13716 + slice-ansi@7.1.2:
13717 + dependencies:
13718 + ansi-styles: 6.2.3
13719 + is-fullwidth-code-point: 5.1.0
13720 +
13391 snake-case@3.0.4: 13721 snake-case@3.0.4:
13392 dependencies: 13722 dependencies:
13393 dot-case: 3.0.4 13723 dot-case: 3.0.4
...@@ -13470,6 +13800,8 @@ snapshots: ...@@ -13470,6 +13800,8 @@ snapshots:
13470 13800
13471 strict-uri-encode@1.1.0: {} 13801 strict-uri-encode@1.1.0: {}
13472 13802
13803 + string-argv@0.3.2: {}
13804 +
13473 string-width@4.2.3: 13805 string-width@4.2.3:
13474 dependencies: 13806 dependencies:
13475 emoji-regex: 8.0.0 13807 emoji-regex: 8.0.0
...@@ -13482,6 +13814,17 @@ snapshots: ...@@ -13482,6 +13814,17 @@ snapshots:
13482 emoji-regex: 9.2.2 13814 emoji-regex: 9.2.2
13483 strip-ansi: 7.1.2 13815 strip-ansi: 7.1.2
13484 13816
13817 + string-width@7.2.0:
13818 + dependencies:
13819 + emoji-regex: 10.6.0
13820 + get-east-asian-width: 1.4.0
13821 + strip-ansi: 7.1.2
13822 +
13823 + string-width@8.1.0:
13824 + dependencies:
13825 + get-east-asian-width: 1.4.0
13826 + strip-ansi: 7.1.2
13827 +
13485 string.fromcodepoint@0.2.1: {} 13828 string.fromcodepoint@0.2.1: {}
13486 13829
13487 string.prototype.trim@1.2.10: 13830 string.prototype.trim@1.2.10:
...@@ -13616,6 +13959,10 @@ snapshots: ...@@ -13616,6 +13959,10 @@ snapshots:
13616 13959
13617 symbol-tree@3.2.4: {} 13960 symbol-tree@3.2.4: {}
13618 13961
13962 + synckit@0.11.12:
13963 + dependencies:
13964 + '@pkgr/core': 0.2.9
13965 +
13619 tailwindcss-config@1.1.3: 13966 tailwindcss-config@1.1.3:
13620 dependencies: 13967 dependencies:
13621 '@weapp-tailwindcss/shared': 1.1.1 13968 '@weapp-tailwindcss/shared': 1.1.1
...@@ -13957,6 +14304,18 @@ snapshots: ...@@ -13957,6 +14304,18 @@ snapshots:
13957 acorn: 8.15.0 14304 acorn: 8.15.0
13958 acorn-walk: 8.3.4 14305 acorn-walk: 8.3.4
13959 14306
14307 + vue-eslint-parser@10.2.0(eslint@8.57.1):
14308 + dependencies:
14309 + debug: 4.4.3
14310 + eslint: 8.57.1
14311 + eslint-scope: 8.4.0
14312 + eslint-visitor-keys: 4.2.1
14313 + espree: 10.4.0
14314 + esquery: 1.7.0
14315 + semver: 7.7.3
14316 + transitivePeerDependencies:
14317 + - supports-color
14318 +
13960 vue-loader@17.4.2(@vue/compiler-sfc@3.5.26)(vue@3.5.26(typescript@5.9.3))(webpack@5.91.0(@swc/core@1.3.96)): 14319 vue-loader@17.4.2(@vue/compiler-sfc@3.5.26)(vue@3.5.26(typescript@5.9.3))(webpack@5.91.0(@swc/core@1.3.96)):
13961 dependencies: 14320 dependencies:
13962 chalk: 4.1.2 14321 chalk: 4.1.2
...@@ -14229,10 +14588,18 @@ snapshots: ...@@ -14229,10 +14588,18 @@ snapshots:
14229 string-width: 5.1.2 14588 string-width: 5.1.2
14230 strip-ansi: 7.1.2 14589 strip-ansi: 7.1.2
14231 14590
14591 + wrap-ansi@9.0.2:
14592 + dependencies:
14593 + ansi-styles: 6.2.3
14594 + string-width: 7.2.0
14595 + strip-ansi: 7.1.2
14596 +
14232 wrappy@1.0.2: {} 14597 wrappy@1.0.2: {}
14233 14598
14234 ws@8.19.0: {} 14599 ws@8.19.0: {}
14235 14600
14601 + xml-name-validator@4.0.0: {}
14602 +
14236 xml-name-validator@5.0.0: {} 14603 xml-name-validator@5.0.0: {}
14237 14604
14238 xmlchars@2.2.0: {} 14605 xmlchars@2.2.0: {}
......
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 }
......
...@@ -16,7 +16,10 @@ ...@@ -16,7 +16,10 @@
16 </view> 16 </view>
17 <view class="center"> 17 <view class="center">
18 <image :src="currentQrCodeUrl" mode="aspectFit" /> 18 <image :src="currentQrCodeUrl" 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">二维码{{ get_qrcode_status_text(useStatus) }}</text> 24 <text class="status-text">二维码{{ get_qrcode_status_text(useStatus) }}</text>
22 </view> 25 </view>
...@@ -25,7 +28,7 @@ ...@@ -25,7 +28,7 @@
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 class="user-list"> 33 <view class="user-list">
31 <view 34 <view
...@@ -35,16 +38,24 @@ ...@@ -35,16 +38,24 @@
35 :class="[ 38 :class="[
36 'user-item', 39 'user-item',
37 select_index === index ? 'checked' : '', 40 select_index === index ? 'checked' : '',
38 - userList.length > 1 && item.sort ? 'border' : '', 41 + userList.length > 1 && item.sort ? 'border' : ''
39 - ]"> 42 + ]"
43 + >
40 {{ item.name }} 44 {{ item.name }}
41 </view> 45 </view>
42 </view> 46 </view>
43 </view> 47 </view>
44 <view v-else class="no-qrcode"> 48 <view v-else class="no-qrcode">
45 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png" style="width: 320rpx; height: 320rpx;" /> 49 + <image
50 + src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png"
51 + style="width: 320rpx; height: 320rpx"
52 + />
46 <view class="no-qrcode-title">今天没有预约记录</view> 53 <view class="no-qrcode-title">今天没有预约记录</view>
47 - <view style="text-align: center; color: #A67939; margin-top: 16rpx;">查看我的“<text @tap="toRecord" style="text-decoration: underline; color: #ED9820;">预约记录</text>”</view> 54 + <view style="text-align: center; color: #a67939; margin-top: 16rpx"
55 + >查看我的“<text @tap="toRecord" style="text-decoration: underline; color: #ed9820"
56 + >预约记录</text
57 + >”</view
58 + >
48 </view> 59 </view>
49 </view> 60 </view>
50 </template> 61 </template>
...@@ -52,12 +63,12 @@ ...@@ -52,12 +63,12 @@
52 <script setup> 63 <script setup>
53 import { ref, computed, watch, onMounted, onUnmounted } from 'vue' 64 import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
54 import Taro from '@tarojs/taro' 65 import Taro from '@tarojs/taro'
55 -import { formatDatetime, mask_id_number, get_qrcode_status_text } from '@/utils/tools'; 66 +import { formatDatetime, mask_id_number, get_qrcode_status_text } from '@/utils/tools'
56 import { qrcodeListAPI, qrcodeStatusAPI, billPersonAPI } from '@/api/index' 67 import { qrcodeListAPI, qrcodeStatusAPI, billPersonAPI } from '@/api/index'
57 import { useGo } from '@/hooks/useGo' 68 import { useGo } from '@/hooks/useGo'
58 -import BASE_URL from '@/utils/config'; 69 +import BASE_URL from '@/utils/config'
59 70
60 -const go = useGo(); 71 +const go = useGo()
61 72
62 const props = defineProps({ 73 const props = defineProps({
63 status: { 74 status: {
...@@ -68,80 +79,81 @@ const props = defineProps({ ...@@ -68,80 +79,81 @@ const props = defineProps({
68 type: String, 79 type: String,
69 default: '' 80 default: ''
70 }, 81 },
71 - payId: { // 接收 payId 82 + payId: {
83 + // 接收 payId
72 type: String, 84 type: String,
73 default: '' 85 default: ''
74 } 86 }
75 -}); 87 +})
76 88
77 -const select_index = ref(0); 89 +const select_index = ref(0)
78 -const userList = ref([]); 90 +const userList = ref([])
79 91
80 /** 92 /**
81 * @description 切换到上一张二维码(循环) 93 * @description 切换到上一张二维码(循环)
82 * @returns {void} 无返回值 94 * @returns {void} 无返回值
83 */ 95 */
84 const prevCode = () => { 96 const prevCode = () => {
85 - select_index.value = select_index.value - 1; 97 + select_index.value = select_index.value - 1
86 if (select_index.value < 0) { 98 if (select_index.value < 0) {
87 - select_index.value = userList.value.length - 1; 99 + select_index.value = userList.value.length - 1
88 } 100 }
89 -}; 101 +}
90 102
91 /** 103 /**
92 * @description 切换到下一张二维码(循环) 104 * @description 切换到下一张二维码(循环)
93 * @returns {void} 无返回值 105 * @returns {void} 无返回值
94 */ 106 */
95 const nextCode = () => { 107 const nextCode = () => {
96 - select_index.value = select_index.value + 1; 108 + select_index.value = select_index.value + 1
97 if (select_index.value > userList.value.length - 1) { 109 if (select_index.value > userList.value.length - 1) {
98 - select_index.value = 0; 110 + select_index.value = 0
99 } 111 }
100 -}; 112 +}
101 113
102 watch( 114 watch(
103 () => select_index.value, 115 () => select_index.value,
104 () => { 116 () => {
105 - refreshBtn(); 117 + refreshBtn()
106 } 118 }
107 ) 119 )
108 120
109 watch( 121 watch(
110 () => props.payId, 122 () => props.payId,
111 - (val) => { 123 + val => {
112 if (val) { 124 if (val) {
113 - init(); 125 + init()
114 } 126 }
115 }, 127 },
116 { immediate: true } 128 { immediate: true }
117 ) 129 )
118 130
119 -const formatId = (id) => mask_id_number(id) 131 +const formatId = id => mask_id_number(id)
120 132
121 const userinfo = computed(() => { 133 const userinfo = computed(() => {
122 return { 134 return {
123 name: userList.value[select_index.value]?.name, 135 name: userList.value[select_index.value]?.name,
124 id: formatId(userList.value[select_index.value]?.id_number), 136 id: formatId(userList.value[select_index.value]?.id_number),
125 - datetime: userList.value[select_index.value]?.datetime, 137 + datetime: userList.value[select_index.value]?.datetime
126 - }; 138 + }
127 -}); 139 +})
128 140
129 const currentQrCodeUrl = computed(() => { 141 const currentQrCodeUrl = computed(() => {
130 - const url = userList.value[select_index.value]?.qr_code_url; 142 + const url = userList.value[select_index.value]?.qr_code_url
131 if (url && url.startsWith('/')) { 143 if (url && url.startsWith('/')) {
132 - return BASE_URL + url; 144 + return BASE_URL + url
133 } 145 }
134 - return url; 146 + return url
135 }) 147 })
136 148
137 -const useStatus = ref('0'); 149 +const useStatus = ref('0')
138 150
139 const STATUS_CODE = { 151 const STATUS_CODE = {
140 APPLY: '1', 152 APPLY: '1',
141 SUCCESS: '3', 153 SUCCESS: '3',
142 CANCELED: '5', 154 CANCELED: '5',
143 - USED: '7', 155 + USED: '7'
144 -}; 156 +}
145 157
146 /** 158 /**
147 * @description 刷新当前选中二维码状态 159 * @description 刷新当前选中二维码状态
...@@ -149,10 +161,14 @@ const STATUS_CODE = { ...@@ -149,10 +161,14 @@ const STATUS_CODE = {
149 * @returns {Promise<void>} 无返回值 161 * @returns {Promise<void>} 无返回值
150 */ 162 */
151 const refreshBtn = async () => { 163 const refreshBtn = async () => {
152 - if (!userList.value[select_index.value]) return; 164 + if (!userList.value[select_index.value]) {
153 - const { code, data } = await qrcodeStatusAPI({ qr_code: userList.value[select_index.value].qr_code }); 165 + return
166 + }
167 + const { code, data } = await qrcodeStatusAPI({
168 + qr_code: userList.value[select_index.value].qr_code
169 + })
154 if (code) { 170 if (code) {
155 - useStatus.value = data.status; 171 + useStatus.value = data.status
156 } 172 }
157 } 173 }
158 174
...@@ -161,8 +177,8 @@ const refreshBtn = async () => { ...@@ -161,8 +177,8 @@ const refreshBtn = async () => {
161 * @param {number} index 下标 177 * @param {number} index 下标
162 * @returns {void} 无返回值 178 * @returns {void} 无返回值
163 */ 179 */
164 -const selectUser = (index) => { 180 +const selectUser = index => {
165 - select_index.value = index; 181 + select_index.value = index
166 } 182 }
167 183
168 /** 184 /**
...@@ -171,17 +187,17 @@ const selectUser = (index) => { ...@@ -171,17 +187,17 @@ const selectUser = (index) => {
171 * @param {Array<Object>} data 二维码列表 187 * @param {Array<Object>} data 二维码列表
172 * @returns {Array<Object>} 处理后的列表 188 * @returns {Array<Object>} 处理后的列表
173 */ 189 */
174 -const formatGroup = (data) => { 190 +const formatGroup = data => {
175 - let lastPayId = null; 191 + let lastPayId = null
176 for (let i = 0; i < data.length; i++) { 192 for (let i = 0; i < data.length; i++) {
177 if (data[i].pay_id !== lastPayId) { 193 if (data[i].pay_id !== lastPayId) {
178 - data[i].sort = 1; 194 + data[i].sort = 1
179 - lastPayId = data[i].pay_id; 195 + lastPayId = data[i].pay_id
180 } else { 196 } else {
181 - data[i].sort = 0; 197 + data[i].sort = 0
182 } 198 }
183 } 199 }
184 - return data; 200 + return data
185 } 201 }
186 202
187 /** 203 /**
...@@ -193,55 +209,55 @@ const formatGroup = (data) => { ...@@ -193,55 +209,55 @@ const formatGroup = (data) => {
193 const init = async () => { 209 const init = async () => {
194 if (!props.type) { 210 if (!props.type) {
195 try { 211 try {
196 - const { code, data } = await qrcodeListAPI(); 212 + const { code, data } = await qrcodeListAPI()
197 213
198 if (code) { 214 if (code) {
199 data.forEach(item => { 215 data.forEach(item => {
200 - item.qr_code_url = '/admin?m=srv&a=get_qrcode&key=' + item.qr_code; 216 + item.qr_code_url = `/admin?m=srv&a=get_qrcode&key=${item.qr_code}`
201 item.datetime = formatDatetime({ begin_time: item.begin_time, end_time: item.end_time }) 217 item.datetime = formatDatetime({ begin_time: item.begin_time, end_time: item.end_time })
202 - item.sort = 0; 218 + item.sort = 0
203 - }); 219 + })
204 // 剔除qr_code为空的二维码 220 // 剔除qr_code为空的二维码
205 - const validData = data.filter(item => item.qr_code !== ''); 221 + const validData = data.filter(item => item.qr_code !== '')
206 222
207 if (validData.length > 0) { 223 if (validData.length > 0) {
208 - userList.value = formatGroup(validData); 224 + userList.value = formatGroup(validData)
209 - refreshBtn(); 225 + refreshBtn()
210 } else { 226 } else {
211 - userList.value = []; 227 + userList.value = []
212 } 228 }
213 } 229 }
214 } catch (err) { 230 } catch (err) {
215 - console.error('Fetch QR List Failed:', err); 231 + console.error('Fetch QR List Failed:', err)
216 } 232 }
217 } else { 233 } else {
218 if (props.payId) { 234 if (props.payId) {
219 - const { code, data } = await billPersonAPI({ pay_id: props.payId }); 235 + const { code, data } = await billPersonAPI({ pay_id: props.payId })
220 if (code) { 236 if (code) {
221 data.forEach(item => { 237 data.forEach(item => {
222 - item.qr_code_url = '/admin?m=srv&a=get_qrcode&key=' + item.qr_code; 238 + item.qr_code_url = `/admin?m=srv&a=get_qrcode&key=${item.qr_code}`
223 - item.sort = 0; 239 + item.sort = 0
224 // billPersonAPI 返回的数据可能没有 datetime 字段,需要检查 240 // billPersonAPI 返回的数据可能没有 datetime 字段,需要检查
225 // 如果没有,可能需要从外部传入或者假设是当天的? 241 // 如果没有,可能需要从外部传入或者假设是当天的?
226 // H5 代码没有处理 datetime,但在 template 里用了。 242 // H5 代码没有处理 datetime,但在 template 里用了。
227 // 这里暂且不做处理,如果没有 datetime 就不显示 243 // 这里暂且不做处理,如果没有 datetime 就不显示
228 - }); 244 + })
229 - const validData = data.filter(item => item.qr_code !== ''); 245 + const validData = data.filter(item => item.qr_code !== '')
230 if (validData.length > 0) { 246 if (validData.length > 0) {
231 - userList.value = validData; 247 + userList.value = validData
232 - refreshBtn(); 248 + refreshBtn()
233 } else { 249 } else {
234 - userList.value = []; 250 + userList.value = []
235 } 251 }
236 } 252 }
237 } 253 }
238 } 254 }
239 -}; 255 +}
240 256
241 onMounted(() => { 257 onMounted(() => {
242 - init(); 258 + init()
243 - start_polling(); 259 + start_polling()
244 -}); 260 +})
245 261
246 /** 262 /**
247 * @description 轮询刷新二维码状态 263 * @description 轮询刷新二维码状态
...@@ -251,13 +267,15 @@ onMounted(() => { ...@@ -251,13 +267,15 @@ onMounted(() => {
251 const poll = async () => { 267 const poll = async () => {
252 if (userList.value.length && useStatus.value === STATUS_CODE.SUCCESS) { 268 if (userList.value.length && useStatus.value === STATUS_CODE.SUCCESS) {
253 if (userList.value[select_index.value]) { 269 if (userList.value[select_index.value]) {
254 - const { code, data } = await qrcodeStatusAPI({ qr_code: userList.value[select_index.value].qr_code }); 270 + const { code, data } = await qrcodeStatusAPI({
271 + qr_code: userList.value[select_index.value].qr_code
272 + })
255 if (code) { 273 if (code) {
256 - useStatus.value = data.status; 274 + useStatus.value = data.status
257 } 275 }
258 } 276 }
259 } 277 }
260 -}; 278 +}
261 279
262 const interval_id = ref(null) 280 const interval_id = ref(null)
263 /** 281 /**
...@@ -267,7 +285,9 @@ const interval_id = ref(null) ...@@ -267,7 +285,9 @@ const interval_id = ref(null)
267 */ 285 */
268 286
269 const start_polling = () => { 287 const start_polling = () => {
270 - if (interval_id.value) return 288 + if (interval_id.value) {
289 + return
290 + }
271 interval_id.value = setInterval(poll, 3000) 291 interval_id.value = setInterval(poll, 3000)
272 } 292 }
273 293
...@@ -278,14 +298,16 @@ const start_polling = () => { ...@@ -278,14 +298,16 @@ const start_polling = () => {
278 */ 298 */
279 299
280 const stop_polling = () => { 300 const stop_polling = () => {
281 - if (!interval_id.value) return 301 + if (!interval_id.value) {
302 + return
303 + }
282 clearInterval(interval_id.value) 304 clearInterval(interval_id.value)
283 interval_id.value = null 305 interval_id.value = null
284 } 306 }
285 307
286 onUnmounted(() => { 308 onUnmounted(() => {
287 - stop_polling(); 309 + stop_polling()
288 -}); 310 +})
289 311
290 defineExpose({ start_polling, stop_polling }) 312 defineExpose({ start_polling, stop_polling })
291 313
...@@ -294,7 +316,7 @@ defineExpose({ start_polling, stop_polling }) ...@@ -294,7 +316,7 @@ defineExpose({ start_polling, stop_polling })
294 * @returns {void} 无返回值 316 * @returns {void} 无返回值
295 */ 317 */
296 const toRecord = () => { 318 const toRecord = () => {
297 - go('/bookingList'); 319 + go('/bookingList')
298 } 320 }
299 </script> 321 </script>
300 322
...@@ -306,12 +328,12 @@ const toRecord = () => { ...@@ -306,12 +328,12 @@ const toRecord = () => {
306 flex-direction: column; 328 flex-direction: column;
307 justify-content: center; 329 justify-content: center;
308 align-items: center; 330 align-items: center;
309 - background-color: #FFF; 331 + background-color: #fff;
310 border-radius: 16rpx; 332 border-radius: 16rpx;
311 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.27); 333 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.27);
312 334
313 .user-info { 335 .user-info {
314 - color: #A6A6A6; 336 + color: #a6a6a6;
315 font-size: 37rpx; 337 font-size: 37rpx;
316 margin-top: 16rpx; 338 margin-top: 16rpx;
317 margin-bottom: 16rpx; 339 margin-bottom: 16rpx;
...@@ -321,16 +343,19 @@ const toRecord = () => { ...@@ -321,16 +343,19 @@ const toRecord = () => {
321 align-items: center; 343 align-items: center;
322 .left { 344 .left {
323 image { 345 image {
324 - width: 56rpx; height: 56rpx; margin-right: 16rpx; 346 + width: 56rpx;
347 + height: 56rpx;
348 + margin-right: 16rpx;
325 } 349 }
326 } 350 }
327 .center { 351 .center {
328 - border: 2rpx solid #D1D1D1; 352 + border: 2rpx solid #d1d1d1;
329 border-radius: 40rpx; 353 border-radius: 40rpx;
330 padding: 46rpx; 354 padding: 46rpx;
331 position: relative; 355 position: relative;
332 image { 356 image {
333 - width: 400rpx; height: 400rpx; 357 + width: 400rpx;
358 + height: 400rpx;
334 } 359 }
335 .qrcode-used { 360 .qrcode-used {
336 position: absolute; 361 position: absolute;
...@@ -350,7 +375,7 @@ const toRecord = () => { ...@@ -350,7 +375,7 @@ const toRecord = () => {
350 } 375 }
351 376
352 .status-text { 377 .status-text {
353 - color: #A67939; 378 + color: #a67939;
354 position: absolute; 379 position: absolute;
355 top: 50%; 380 top: 50%;
356 left: 50%; 381 left: 50%;
...@@ -364,7 +389,8 @@ const toRecord = () => { ...@@ -364,7 +389,8 @@ const toRecord = () => {
364 } 389 }
365 .right { 390 .right {
366 image { 391 image {
367 - width: 56rpx; height: 56rpx; 392 + width: 56rpx;
393 + height: 56rpx;
368 margin-left: 16rpx; 394 margin-left: 16rpx;
369 } 395 }
370 } 396 }
...@@ -378,13 +404,13 @@ const toRecord = () => { ...@@ -378,13 +404,13 @@ const toRecord = () => {
378 .user-item { 404 .user-item {
379 position: relative; 405 position: relative;
380 padding: 8rpx 16rpx; 406 padding: 8rpx 16rpx;
381 - border: 2rpx solid #A67939; 407 + border: 2rpx solid #a67939;
382 margin: 8rpx; 408 margin: 8rpx;
383 border-radius: 10rpx; 409 border-radius: 10rpx;
384 - color: #A67939; 410 + color: #a67939;
385 &.checked { 411 &.checked {
386 - color: #FFF; 412 + color: #fff;
387 - background-color: #A67939; 413 + background-color: #a67939;
388 } 414 }
389 &.border { 415 &.border {
390 margin-right: 16rpx; 416 margin-right: 16rpx;
...@@ -394,7 +420,7 @@ const toRecord = () => { ...@@ -394,7 +420,7 @@ const toRecord = () => {
394 top: calc(50% - 16rpx); 420 top: calc(50% - 16rpx);
395 content: ''; 421 content: '';
396 height: 32rpx; 422 height: 32rpx;
397 - border-right: 2rpx solid #A67939; 423 + border-right: 2rpx solid #a67939;
398 } 424 }
399 } 425 }
400 } 426 }
...@@ -408,7 +434,7 @@ const toRecord = () => { ...@@ -408,7 +434,7 @@ const toRecord = () => {
408 margin-bottom: 32rpx; 434 margin-bottom: 32rpx;
409 435
410 .no-qrcode-title { 436 .no-qrcode-title {
411 - color: #A67939; 437 + color: #a67939;
412 font-size: 34rpx; 438 font-size: 34rpx;
413 } 439 }
414 } 440 }
......
...@@ -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 -}
......
1 <template> 1 <template>
2 - <picker mode="multiSelector" :range-key="'name'" :value="timeIndex" :range="activityArray" :disabled="disabled" 2 + <picker
3 - @change="bindMultiPickerChange" @columnChange="bindMultiPickerColumnChange"> 3 + mode="multiSelector"
4 + :range-key="'name'"
5 + :value="timeIndex"
6 + :range="activityArray"
7 + :disabled="disabled"
8 + @change="bindMultiPickerChange"
9 + @columnChange="bindMultiPickerColumnChange"
10 + >
4 <slot /> 11 <slot />
5 </picker> 12 </picker>
6 </template> 13 </template>
7 <script> 14 <script>
8 -import { dateTimePicker, dateDate } from "./dateTimePicker.js"; 15 +import { dateTimePicker, dateDate } from './dateTimePicker.js'
9 export default { 16 export default {
10 - name: "TimePickerDataPicker", 17 + name: 'TimePickerDataPicker',
11 props: { 18 props: {
12 startTime: { 19 startTime: {
13 type: [Object, Date], 20 type: [Object, Date],
14 - default: new Date(), 21 + default: new Date()
15 }, 22 },
16 endTime: { 23 endTime: {
17 type: [Object, Date], 24 type: [Object, Date],
18 - default: new Date(), 25 + default: new Date()
19 }, 26 },
20 defaultTime: { 27 defaultTime: {
21 type: [Object, Date], 28 type: [Object, Date],
22 - default: new Date(), 29 + default: new Date()
23 }, 30 },
24 disabled: { 31 disabled: {
25 type: Boolean, 32 type: Boolean,
26 - default: false, 33 + default: false
27 - }, 34 + }
28 }, 35 },
29 data() { 36 data() {
30 return { 37 return {
...@@ -35,150 +42,139 @@ export default { ...@@ -35,150 +42,139 @@ export default {
35 day: 1, 42 day: 1,
36 hour: 0, 43 hour: 0,
37 minute: 0, 44 minute: 0,
38 - datePicker: "", 45 + datePicker: '',
39 defaultIndex: [0, 0, 0, 0, 0], 46 defaultIndex: [0, 0, 0, 0, 0],
40 startIndex: [0, 0, 0, 0, 0], 47 startIndex: [0, 0, 0, 0, 0],
41 - endIndex: [0, 0, 0, 0, 0], 48 + endIndex: [0, 0, 0, 0, 0]
42 - }; 49 + }
43 }, 50 },
44 computed: { 51 computed: {
45 timeDate() { 52 timeDate() {
46 - const { startTime, endTime } = this; 53 + const { startTime, endTime } = this
47 - return { startTime, endTime }; 54 + return { startTime, endTime }
48 - }, 55 + }
49 }, 56 },
50 watch: { 57 watch: {
51 timeDate() { 58 timeDate() {
52 - this.initData(); 59 + this.initData()
53 }, 60 },
54 - defaultTime () { 61 + defaultTime() {
55 - this.initData(); 62 + this.initData()
56 } 63 }
57 }, 64 },
58 created() { 65 created() {
59 - this.initData(); 66 + this.initData()
60 }, 67 },
61 methods: { 68 methods: {
62 initData() { 69 initData() {
63 - let startTime = this.startTime; 70 + const startTime = this.startTime
64 - let endTime = this.endTime; 71 + const endTime = this.endTime
65 - this.datePicker = dateTimePicker( 72 + this.datePicker = dateTimePicker(startTime.getFullYear(), endTime.getFullYear())
66 - startTime.getFullYear(), 73 + this.setDateData(this.defaultTime)
67 - endTime.getFullYear() 74 + this.getKeyIndex(this.startTime, 'startIndex')
68 - );
69 - this.setDateData(this.defaultTime);
70 - this.getKeyIndex(this.startTime, "startIndex");
71 // 截止时间索引 75 // 截止时间索引
72 - this.getKeyIndex(this.endTime, "endIndex"); 76 + this.getKeyIndex(this.endTime, 'endIndex')
73 // 默认索引 77 // 默认索引
74 - this.getKeyIndex(this.defaultTime, "defaultIndex"); 78 + this.getKeyIndex(this.defaultTime, 'defaultIndex')
75 - this.timeIndex = this.defaultIndex; 79 + this.timeIndex = this.defaultIndex
76 // 初始时间 80 // 初始时间
77 - this.initTime(); 81 + this.initTime()
78 }, 82 },
79 getKeyIndex(time, key) { 83 getKeyIndex(time, key) {
80 - let Arr = dateDate(time); 84 + const Arr = dateDate(time)
81 - let _index = this.getIndex(Arr); 85 + const _index = this.getIndex(Arr)
82 - this[key] = _index; 86 + this[key] = _index
83 }, 87 },
84 getIndex(arr) { 88 getIndex(arr) {
85 - let timeIndex = []; 89 + const timeIndex = []
86 - let indexKey = ["year", "month", "day", "hours", "minutes"]; 90 + const indexKey = ['year', 'month', 'day', 'hours', 'minutes']
87 this.activityArray.forEach((element, index) => { 91 this.activityArray.forEach((element, index) => {
88 - let _index = element.findIndex( 92 + const _index = element.findIndex(
89 - (item) => parseInt(item.id) === parseInt(arr[indexKey[index]]) 93 + item => parseInt(item.id) === parseInt(arr[indexKey[index]])
90 - ); 94 + )
91 - timeIndex[index] = _index >= 0 ? _index : 0; 95 + timeIndex[index] = _index >= 0 ? _index : 0
92 - }); 96 + })
93 - return timeIndex; 97 + return timeIndex
94 }, 98 },
95 initTime() { 99 initTime() {
96 - let _index = this.timeIndex; 100 + const _index = this.timeIndex
97 - this.year = this.activityArray[0][_index[0]].id; 101 + this.year = this.activityArray[0][_index[0]].id
98 - this.month = this.activityArray[1].length && this.activityArray[1][_index[1]].id; 102 + this.month = this.activityArray[1].length && this.activityArray[1][_index[1]].id
99 - this.day = this.activityArray[2].length && this.activityArray[2][_index[2]].id; 103 + this.day = this.activityArray[2].length && this.activityArray[2][_index[2]].id
100 - this.hour = this.activityArray[3].length && this.activityArray[3][_index[3]].id; 104 + this.hour = this.activityArray[3].length && this.activityArray[3][_index[3]].id
101 - this.minute = this.activityArray[4].length && this.activityArray[4][_index[4]].id; 105 + this.minute = this.activityArray[4].length && this.activityArray[4][_index[4]].id
102 }, 106 },
103 setDateData(_date) { 107 setDateData(_date) {
104 - let _data = dateDate(_date); 108 + const _data = dateDate(_date)
105 - this.activityArray = this.datePicker(_data.year, _data.month); 109 + this.activityArray = this.datePicker(_data.year, _data.month)
106 }, 110 },
107 bindMultiPickerChange(e) { 111 bindMultiPickerChange(e) {
108 - console.log("picker发送选择改变,携带值为", e.detail.value); 112 + console.log('picker发送选择改变,携带值为', e.detail.value)
109 - let activityArray = JSON.parse(JSON.stringify(this.activityArray)), 113 + const activityArray = JSON.parse(JSON.stringify(this.activityArray)),
110 { value } = e.detail, 114 { value } = e.detail,
111 - _result = []; 115 + _result = []
112 for (let i = 0; i < value.length; i++) { 116 for (let i = 0; i < value.length; i++) {
113 - _result[i] = activityArray[i][value[i]].id; 117 + _result[i] = activityArray[i][value[i]].id
114 } 118 }
115 - this.$emit("result", _result); 119 + this.$emit('result', _result)
116 }, 120 },
117 bindMultiPickerColumnChange(e) { 121 bindMultiPickerColumnChange(e) {
118 - console.log("修改的列为", e.detail.column, ",值为", e.detail.value); 122 + console.log('修改的列为', e.detail.column, ',值为', e.detail.value)
119 let _data = JSON.parse(JSON.stringify(this.activityArray)), 123 let _data = JSON.parse(JSON.stringify(this.activityArray)),
120 timeIndex = JSON.parse(JSON.stringify(this.timeIndex)), 124 timeIndex = JSON.parse(JSON.stringify(this.timeIndex)),
121 { startIndex, endIndex } = this, 125 { startIndex, endIndex } = this,
122 { column, value } = e.detail, 126 { column, value } = e.detail,
123 _value = _data[column][value].id, 127 _value = _data[column][value].id,
124 _start = dateDate(this.startTime), 128 _start = dateDate(this.startTime),
125 - _end = dateDate(this.endTime); 129 + _end = dateDate(this.endTime)
126 switch (e.detail.column) { 130 switch (e.detail.column) {
127 case 0: 131 case 0:
128 if (_value <= _start.year) { 132 if (_value <= _start.year) {
129 - timeIndex = startIndex; 133 + timeIndex = startIndex
130 - this.year = _start.year; 134 + this.year = _start.year
131 - this.setDateData(this.startTime); 135 + this.setDateData(this.startTime)
132 } else if (_value >= _end.year) { 136 } else if (_value >= _end.year) {
133 - this.year = _end.year; 137 + this.year = _end.year
134 - timeIndex = [endIndex[0], 0, 0, 0, 0]; 138 + timeIndex = [endIndex[0], 0, 0, 0, 0]
135 - this.setDateData(this.endTime); 139 + this.setDateData(this.endTime)
136 } else { 140 } else {
137 - this.year = _value; 141 + this.year = _value
138 - timeIndex = [value, 0, 0, 0, 0]; 142 + timeIndex = [value, 0, 0, 0, 0]
139 - this.activityArray = this.datePicker(_value, 1); 143 + this.activityArray = this.datePicker(_value, 1)
140 } 144 }
141 - timeIndex = this.timeIndex = JSON.parse(JSON.stringify(timeIndex)); 145 + timeIndex = this.timeIndex = JSON.parse(JSON.stringify(timeIndex))
142 - this.timeIndex = timeIndex; 146 + this.timeIndex = timeIndex
143 - break; 147 + break
144 case 1: 148 case 1:
145 if (this.year == _start.year && value <= startIndex[1]) { 149 if (this.year == _start.year && value <= startIndex[1]) {
146 - timeIndex = startIndex; 150 + timeIndex = startIndex
147 - this.month = _start.month; 151 + this.month = _start.month
148 - this.setDateData(this.startTime); 152 + this.setDateData(this.startTime)
149 } else if (this.year == _end.year && value >= endIndex[1]) { 153 } else if (this.year == _end.year && value >= endIndex[1]) {
150 - timeIndex = endIndex; 154 + timeIndex = endIndex
151 - this.month = _end.month; 155 + this.month = _end.month
152 - this.setDateData(this.endTime); 156 + this.setDateData(this.endTime)
153 } else { 157 } else {
154 - this.month = _value; 158 + this.month = _value
155 - _data[2] = this.datePicker(this.year, this.month)[2]; 159 + _data[2] = this.datePicker(this.year, this.month)[2]
156 - timeIndex = [timeIndex[0], value, 0, 0, 0]; 160 + timeIndex = [timeIndex[0], value, 0, 0, 0]
157 - this.activityArray = _data; 161 + this.activityArray = _data
158 } 162 }
159 - this.timeIndex = JSON.parse(JSON.stringify(timeIndex)); 163 + this.timeIndex = JSON.parse(JSON.stringify(timeIndex))
160 - break; 164 + break
161 case 2: 165 case 2:
162 - if ( 166 + if (this.year == _start.year && this.month == _start.month && value <= startIndex[2]) {
163 - this.year == _start.year && 167 + this.day = _start.day
164 - this.month == _start.month && 168 + timeIndex = startIndex
165 - value <= startIndex[2] 169 + } else if (this.year == _end.year && this.month == _end.month && value >= endIndex[2]) {
166 - ) { 170 + this.day = _end.day
167 - this.day = _start.day; 171 + timeIndex = endIndex
168 - timeIndex = startIndex;
169 - } else if (
170 - this.year == _end.year &&
171 - this.month == _end.month &&
172 - value >= endIndex[2]
173 - ) {
174 - this.day = _end.day;
175 - timeIndex = endIndex;
176 } else { 172 } else {
177 - this.day = _value; 173 + this.day = _value
178 - timeIndex = [timeIndex[0], timeIndex[1], value, 0, 0]; 174 + timeIndex = [timeIndex[0], timeIndex[1], value, 0, 0]
179 } 175 }
180 - this.timeIndex = JSON.parse(JSON.stringify(timeIndex)); 176 + this.timeIndex = JSON.parse(JSON.stringify(timeIndex))
181 - break; 177 + break
182 case 3: 178 case 3:
183 if ( 179 if (
184 this.year == _start.year && 180 this.year == _start.year &&
...@@ -186,25 +182,25 @@ export default { ...@@ -186,25 +182,25 @@ export default {
186 this.day == _start.day && 182 this.day == _start.day &&
187 value <= startIndex[3] 183 value <= startIndex[3]
188 ) { 184 ) {
189 - this.hour = _start.hours; 185 + this.hour = _start.hours
190 - timeIndex = startIndex; 186 + timeIndex = startIndex
191 } else if ( 187 } else if (
192 this.year == _end.year && 188 this.year == _end.year &&
193 this.month == _end.month && 189 this.month == _end.month &&
194 this.day == _end.day && 190 this.day == _end.day &&
195 value >= endIndex[3] 191 value >= endIndex[3]
196 ) { 192 ) {
197 - this.hour = _end.hours; 193 + this.hour = _end.hours
198 - timeIndex = endIndex; 194 + timeIndex = endIndex
199 } else { 195 } else {
200 - this.hour = _value; 196 + this.hour = _value
201 - timeIndex[3] = value; 197 + timeIndex[3] = value
202 - timeIndex[4] = 0; 198 + timeIndex[4] = 0
203 } 199 }
204 - this.timeIndex = JSON.parse(JSON.stringify(timeIndex)); 200 + this.timeIndex = JSON.parse(JSON.stringify(timeIndex))
205 - break; 201 + break
206 case 4: 202 case 4:
207 - timeIndex[4] = value; 203 + timeIndex[4] = value
208 if ( 204 if (
209 this.year == _start.year && 205 this.year == _start.year &&
210 this.month == _start.month && 206 this.month == _start.month &&
...@@ -212,7 +208,7 @@ export default { ...@@ -212,7 +208,7 @@ export default {
212 this.hour == _start.hours && 208 this.hour == _start.hours &&
213 value <= startIndex[4] 209 value <= startIndex[4]
214 ) { 210 ) {
215 - timeIndex = startIndex; 211 + timeIndex = startIndex
216 } else if ( 212 } else if (
217 this.year == _end.year && 213 this.year == _end.year &&
218 this.month == _end.month && 214 this.month == _end.month &&
...@@ -220,12 +216,12 @@ export default { ...@@ -220,12 +216,12 @@ export default {
220 this.hour == _end.hours && 216 this.hour == _end.hours &&
221 value >= endIndex[4] 217 value >= endIndex[4]
222 ) { 218 ) {
223 - timeIndex = endIndex; 219 + timeIndex = endIndex
224 } 220 }
225 - this.timeIndex = JSON.parse(JSON.stringify(timeIndex)); 221 + this.timeIndex = JSON.parse(JSON.stringify(timeIndex))
226 - break; 222 + break
227 } 223 }
228 - }, 224 + }
229 - }, 225 + }
230 -}; 226 +}
231 </script> 227 </script>
......
...@@ -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 })
......
...@@ -18,24 +18,44 @@ ...@@ -18,24 +18,44 @@
18 </view> 18 </view>
19 <view class="weeks-wrapper"> 19 <view class="weeks-wrapper">
20 <view v-for="(week, index) in weeks" :key="index" class="weeks"> 20 <view v-for="(week, index) in weeks" :key="index" class="weeks">
21 - <view v-for="(date, dateIndex) in week" :key="dateIndex" 21 + <view
22 + v-for="(date, dateIndex) in week"
23 + :key="dateIndex"
22 @tap="chooseDay(date)" 24 @tap="chooseDay(date)"
23 - :class="[ 'item', 25 + :class="[
26 + 'item',
24 date && checked_day === findDatesInfo(date).date ? 'checked' : '', 27 date && checked_day === findDatesInfo(date).date ? 'checked' : '',
25 - date && (findDatesInfo(date).reserve_full === ReserveStatus.FULL || findDatesInfo(date).reserve_full === ReserveStatus.OVERDUE) ? 'disabled' : '' 28 + date &&
29 + (findDatesInfo(date).reserve_full === ReserveStatus.FULL ||
30 + findDatesInfo(date).reserve_full === ReserveStatus.OVERDUE)
31 + ? 'disabled'
32 + : ''
26 ]" 33 ]"
27 > 34 >
28 <view v-if="findDatesInfo(date).date"> 35 <view v-if="findDatesInfo(date).date">
29 <view class="day-lunar">{{ findDatesInfo(date).lunar_date.IDayCn }}</view> 36 <view class="day-lunar">{{ findDatesInfo(date).lunar_date.IDayCn }}</view>
30 <view class="day-text">{{ findDatesInfo(date).text }}</view> 37 <view class="day-text">{{ findDatesInfo(date).text }}</view>
31 - <view v-if="findDatesInfo(date).reserve_full === ReserveStatus.INFINITY || findDatesInfo(date).reserve_full === ReserveStatus.OVERDUE" class="day-price"></view> 38 + <view
32 - <view v-else-if="findDatesInfo(date).reserve_full === ReserveStatus.FULL" class="day-no-booking">约满</view> 39 + v-if="
40 + findDatesInfo(date).reserve_full === ReserveStatus.INFINITY ||
41 + findDatesInfo(date).reserve_full === ReserveStatus.OVERDUE
42 + "
43 + class="day-price"
44 + ></view>
45 + <view
46 + v-else-if="findDatesInfo(date).reserve_full === ReserveStatus.FULL"
47 + class="day-no-booking"
48 + >约满</view
49 + >
33 </view> 50 </view>
34 </view> 51 </view>
35 </view> 52 </view>
36 </view> 53 </view>
37 </view> 54 </view>
38 - <view v-if="checked_day && checked_day_reserve_full === ReserveStatus.AVAILABLE" class="choose-time"> 55 + <view
56 + v-if="checked_day && checked_day_reserve_full === ReserveStatus.AVAILABLE"
57 + class="choose-time"
58 + >
39 <view class="title"> 59 <view class="title">
40 <view class="text">选择参访时间段</view> 60 <view class="text">选择参访时间段</view>
41 </view> 61 </view>
...@@ -64,14 +84,14 @@ ...@@ -64,14 +84,14 @@
64 <view class="title"> 84 <view class="title">
65 <view class="text">选择参访时间段</view> 85 <view class="text">选择参访时间段</view>
66 </view> 86 </view>
67 - <view style="padding: 48rpx 24rpx; color: #A67939; text-align: center;"> 87 + <view style="padding: 48rpx 24rpx; color: #a67939; text-align: center">
68 {{ infinity_tips_text }} 88 {{ infinity_tips_text }}
69 </view> 89 </view>
70 </view> 90 </view>
71 </view> 91 </view>
72 - <view style="height: 160rpx;"></view> 92 + <view style="height: 160rpx"></view>
73 <view v-if="checked_day && checked_day_reserve_full === ReserveStatus.AVAILABLE" class="next"> 93 <view v-if="checked_day && checked_day_reserve_full === ReserveStatus.AVAILABLE" class="next">
74 - <view @tap="nextBtn" class="button" style="background-color: #A67939;">下一步</view> 94 + <view @tap="nextBtn" class="button" style="background-color: #a67939">下一步</view>
75 </view> 95 </view>
76 96
77 <!-- NutUI Popup + DatePicker --> 97 <!-- NutUI Popup + DatePicker -->
...@@ -92,31 +112,33 @@ ...@@ -92,31 +112,33 @@
92 <script setup> 112 <script setup>
93 import { ref, computed } from 'vue' 113 import { ref, computed } from 'vue'
94 import Taro, { useDidShow } from '@tarojs/taro' 114 import Taro, { useDidShow } from '@tarojs/taro'
95 -import dayjs from 'dayjs'; 115 +import dayjs from 'dayjs'
96 import { useGo } from '@/hooks/useGo' 116 import { useGo } from '@/hooks/useGo'
97 import icon_select1 from '@/assets/images/单选01@2x.png' 117 import icon_select1 from '@/assets/images/单选01@2x.png'
98 import icon_select2 from '@/assets/images/单选02@2x.png' 118 import icon_select2 from '@/assets/images/单选02@2x.png'
99 import { canReserveDateListAPI, canReserveTimeListAPI } from '@/api/index' 119 import { canReserveDateListAPI, canReserveTimeListAPI } from '@/api/index'
100 import calendar from 'xst-solar2lunar' 120 import calendar from 'xst-solar2lunar'
101 121
102 -const go = useGo(); 122 +const go = useGo()
103 123
104 -const dates_list = ref([]); // 当月日期列表信息 124 +const dates_list = ref([]) // 当月日期列表信息
105 -const dates = ref([]); // 当月日期集合 125 +const dates = ref([]) // 当月日期集合
106 126
107 useDidShow(async () => { 127 useDidShow(async () => {
108 - const raw_date = new Date(); 128 + const raw_date = new Date()
109 - const { code, data } = await canReserveDateListAPI({ month: `${raw_date.getFullYear()}-${(raw_date.getMonth() + 1).toString().padStart(2, '0')}` }); 129 + const { code, data } = await canReserveDateListAPI({
130 + month: `${raw_date.getFullYear()}-${(raw_date.getMonth() + 1).toString().padStart(2, '0')}`
131 + })
110 if (code) { 132 if (code) {
111 // 日期列表 133 // 日期列表
112 - dates_list.value = data || []; 134 + dates_list.value = data || []
113 // 今日之前都不可约 135 // 今日之前都不可约
114 - dates_list.value.forEach((date) => { 136 + dates_list.value.forEach(date => {
115 if (dayjs(date.month_date).isBefore(dayjs())) { 137 if (dayjs(date.month_date).isBefore(dayjs())) {
116 - date.reserve_full = ReserveStatus.OVERDUE; 138 + date.reserve_full = ReserveStatus.OVERDUE
117 } 139 }
118 - }); 140 + })
119 - dates.value = dates_list.value.map(item => item.month_date); 141 + dates.value = dates_list.value.map(item => item.month_date)
120 } 142 }
121 }) 143 })
122 144
...@@ -125,22 +147,24 @@ useDidShow(async () => { ...@@ -125,22 +147,24 @@ useDidShow(async () => {
125 * @param {string} date 147 * @param {string} date
126 * @return {object} {text: 日期, date: 日期, reserve_full: 是否可约 1=可约,0=约满,-1=无需预约 overdue=过期日期 } 148 * @return {object} {text: 日期, date: 日期, reserve_full: 是否可约 1=可约,0=约满,-1=无需预约 overdue=过期日期 }
127 */ 149 */
128 -const findDatesInfo = (date) => { 150 +const findDatesInfo = date => {
129 - if (!date) return { text: '', date: '', reserve_full: '', lunar_date: {} }; 151 + if (!date) {
130 - const result = dates_list.value.find((item) => item.month_date === date); 152 + return { text: '', date: '', reserve_full: '', lunar_date: {} }
131 - const currentDate = new Date(date); 153 + }
154 + const result = dates_list.value.find(item => item.month_date === date)
155 + const currentDate = new Date(date)
132 // calendar.solar2lunar 需要年,月,日 (数字) 156 // calendar.solar2lunar 需要年,月,日 (数字)
133 // dayjs(date).format('YYYY-MM-DD') -> 2024-01-01 157 // dayjs(date).format('YYYY-MM-DD') -> 2024-01-01
134 - const d = dayjs(date); 158 + const d = dayjs(date)
135 - const lunarDate = calendar.solar2lunar(d.year(), d.month() + 1, d.date()); 159 + const lunarDate = calendar.solar2lunar(d.year(), d.month() + 1, d.date())
136 return { 160 return {
137 text: currentDate.getDate().toString().padStart(2, '0'), 161 text: currentDate.getDate().toString().padStart(2, '0'),
138 date: result?.month_date, 162 date: result?.month_date,
139 reserve_full: result?.reserve_full, 163 reserve_full: result?.reserve_full,
140 tips: result?.tips || '', 164 tips: result?.tips || '',
141 lunar_date: lunarDate 165 lunar_date: lunarDate
142 - }; 166 + }
143 -}; 167 +}
144 168
145 /** 169 /**
146 * @description: 预约状态 170 * @description: 预约状态
...@@ -150,59 +174,61 @@ const ReserveStatus = { ...@@ -150,59 +174,61 @@ const ReserveStatus = {
150 INFINITY: -1, // 无需预约 174 INFINITY: -1, // 无需预约
151 FULL: 0, // 约满 175 FULL: 0, // 约满
152 AVAILABLE: 1, // 可约 176 AVAILABLE: 1, // 可约
153 - OVERDUE: 'overdue', // 过期日期 177 + OVERDUE: 'overdue' // 过期日期
154 } 178 }
155 179
156 -const daysOfWeek = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]; 180 +const daysOfWeek = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
157 181
158 /** 182 /**
159 * @description: 每周日期列表 183 * @description: 每周日期列表
160 * @return {array} [array] 184 * @return {array} [array]
161 */ 185 */
162 const weeks = computed(() => { 186 const weeks = computed(() => {
163 - if (dates.value.length === 0) return []; 187 + if (dates.value.length === 0) {
164 - const result = []; 188 + return []
165 - let currentWeek = []; 189 + }
166 - let currentDate = new Date(dates.value[0]); 190 + const result = []
191 + let currentWeek = []
192 + let currentDate = new Date(dates.value[0])
167 193
168 // 确定第一个日期是星期几 194 // 确定第一个日期是星期几
169 - const firstDayOfWeek = currentDate.getDay() === 0 ? 7 : currentDate.getDay(); 195 + const firstDayOfWeek = currentDate.getDay() === 0 ? 7 : currentDate.getDay()
170 196
171 // 添加空白的日期,直到第一个日期的星期一 197 // 添加空白的日期,直到第一个日期的星期一
172 for (let i = 1; i < firstDayOfWeek; i++) { 198 for (let i = 1; i < firstDayOfWeek; i++) {
173 - currentWeek.push(''); 199 + currentWeek.push('')
174 } 200 }
175 201
176 // 添加日期 202 // 添加日期
177 for (const date of dates.value) { 203 for (const date of dates.value) {
178 - currentDate = new Date(date); 204 + currentDate = new Date(date)
179 - const dayOfWeek = currentDate.getDay() === 0 ? 7 : currentDate.getDay(); 205 + const dayOfWeek = currentDate.getDay() === 0 ? 7 : currentDate.getDay()
180 206
181 // 如果当前星期一,开始新的一行 207 // 如果当前星期一,开始新的一行
182 if (dayOfWeek === 1 && currentWeek.length > 0) { 208 if (dayOfWeek === 1 && currentWeek.length > 0) {
183 - result.push(currentWeek); 209 + result.push(currentWeek)
184 - currentWeek = []; 210 + currentWeek = []
185 } 211 }
186 212
187 - currentWeek.push(date); // 仅将日期部分作为字符串添加到当前星期数组 213 + currentWeek.push(date) // 仅将日期部分作为字符串添加到当前星期数组
188 } 214 }
189 215
190 // 添加最后一行 216 // 添加最后一行
191 if (currentWeek.length > 0) { 217 if (currentWeek.length > 0) {
192 while (currentWeek.length < 7) { 218 while (currentWeek.length < 7) {
193 - currentWeek.push(''); 219 + currentWeek.push('')
194 } 220 }
195 - result.push(currentWeek); 221 + result.push(currentWeek)
196 } 222 }
197 223
198 - return result; 224 + return result
199 -}); 225 +})
200 226
201 -const checked_day = ref(''); 227 +const checked_day = ref('')
202 -const checked_day_price = ref(0); 228 +const checked_day_price = ref(0)
203 -const checked_day_reserve_full = ref(null); 229 +const checked_day_reserve_full = ref(null)
204 -const checked_time = ref(-1); 230 +const checked_time = ref(-1)
205 -const timePeriod = ref([]); // 当前时间段信息 231 +const timePeriod = ref([]) // 当前时间段信息
206 232
207 /** 233 /**
208 * @description: 无预约提示 234 * @description: 无预约提示
...@@ -210,21 +236,27 @@ const timePeriod = ref([]); // 当前时间段信息 ...@@ -210,21 +236,27 @@ const timePeriod = ref([]); // 当前时间段信息
210 */ 236 */
211 237
212 const infinity_tips_text = computed(() => { 238 const infinity_tips_text = computed(() => {
213 - if (!checked_day.value || checked_day_reserve_full.value !== ReserveStatus.INFINITY) return ''; 239 + if (!checked_day.value || checked_day_reserve_full.value !== ReserveStatus.INFINITY) {
214 - const info = findDatesInfo(checked_day.value); 240 + return ''
241 + }
242 + const info = findDatesInfo(checked_day.value)
215 if (dayjs(checked_day.value).isAfter(dayjs(), 'day')) { 243 if (dayjs(checked_day.value).isAfter(dayjs(), 'day')) {
216 - const tips = (info.tips || '').trim(); 244 + const tips = (info.tips || '').trim()
217 - if (tips) return tips; 245 + if (tips) {
246 + return tips
218 } 247 }
219 - return '暂未开启预约'; 248 + }
220 -}); 249 + return '暂未开启预约'
250 +})
221 251
222 -const chooseTime = (item, index) => { // 选择时间段回调 252 +const chooseTime = (item, index) => {
223 - if (item.rest_qty || item.rest_qty === QtyStatus.INFINITY) { // 余量等于-1为不限制数量 253 + // 选择时间段回调
224 - checked_time.value = index; 254 + if (item.rest_qty || item.rest_qty === QtyStatus.INFINITY) {
225 - checked_day_price.value = item.price; // 当前价格 255 + // 余量等于-1为不限制数量
256 + checked_time.value = index
257 + checked_day_price.value = item.price // 当前价格
226 } 258 }
227 -}; 259 +}
228 260
229 /** 261 /**
230 * @description: 数量状态 262 * @description: 数量状态
...@@ -232,7 +264,7 @@ const chooseTime = (item, index) => { // 选择时间段回调 ...@@ -232,7 +264,7 @@ const chooseTime = (item, index) => { // 选择时间段回调
232 */ 264 */
233 const QtyStatus = { 265 const QtyStatus = {
234 FULL: 0, // 无余量 266 FULL: 0, // 无余量
235 - INFINITY: -1, // 无限制 267 + INFINITY: -1 // 无限制
236 } 268 }
237 269
238 /** 270 /**
...@@ -240,77 +272,90 @@ const QtyStatus = { ...@@ -240,77 +272,90 @@ const QtyStatus = {
240 * @param {string} date 272 * @param {string} date
241 * @return {void} 273 * @return {void}
242 */ 274 */
243 -const chooseDay = async (date) => { // 点击日期回调 275 +const chooseDay = async date => {
244 - if (!date) return; 276 + // 点击日期回调
245 - const info = findDatesInfo(date); 277 + if (!date) {
278 + return
279 + }
280 + const info = findDatesInfo(date)
246 // 281 //
247 - if (info.reserve_full === ReserveStatus.AVAILABLE || info.reserve_full === ReserveStatus.INFINITY) { // 状态 1可约 || -1不限制 282 + if (
248 - checked_day.value = date; // 当前日期 283 + info.reserve_full === ReserveStatus.AVAILABLE ||
249 - checked_day_reserve_full.value = info.reserve_full; // 当前状态 284 + info.reserve_full === ReserveStatus.INFINITY
285 + ) {
286 + // 状态 1可约 || -1不限制
287 + checked_day.value = date // 当前日期
288 + checked_day_reserve_full.value = info.reserve_full // 当前状态
250 // 如果可约,查询时间段信息 289 // 如果可约,查询时间段信息
251 if (info.reserve_full === ReserveStatus.AVAILABLE) { 290 if (info.reserve_full === ReserveStatus.AVAILABLE) {
252 // 选择日期后,查询时间段信息 291 // 选择日期后,查询时间段信息
253 - const { code, data } = await canReserveTimeListAPI({ month_date: checked_day.value }); 292 + const { code, data } = await canReserveTimeListAPI({ month_date: checked_day.value })
254 if (code) { 293 if (code) {
255 // rest_qty >0表示有余量,可约;=0表示没有余量,不可约;<0表示不限,可约; 294 // rest_qty >0表示有余量,可约;=0表示没有余量,不可约;<0表示不限,可约;
256 // period_type 时段类型 REGULAR=日常预约,SPRING_FESTIVAL=春节预约 295 // period_type 时段类型 REGULAR=日常预约,SPRING_FESTIVAL=春节预约
257 - timePeriod.value = data; 296 + timePeriod.value = data
258 - checked_time.value = -1; // 重置已选择的时间段 297 + checked_time.value = -1 // 重置已选择的时间段
259 } 298 }
260 } 299 }
261 } 300 }
262 -}; 301 +}
263 302
264 -const showPicker = ref(false); 303 +const showPicker = ref(false)
265 const chooseDate = () => { 304 const chooseDate = () => {
266 - showPicker.value = true; 305 + showPicker.value = true
267 } 306 }
268 307
269 -const raw_date = new Date(); 308 +const raw_date = new Date()
270 -const currentDate = ref(new Date()); // NutUI DatePicker v-model 绑定的是 Date 对象 309 +const currentDate = ref(new Date()) // NutUI DatePicker v-model 绑定的是 Date 对象
271 -const minDate = new Date(); 310 +const minDate = new Date()
272 -const maxDate = new Date(2050, 11, 1); 311 +const maxDate = new Date(2050, 11, 1)
273 -const currentDateText = ref((raw_date.getMonth() + 1).toString().padStart(2, '0')); 312 +const currentDateText = ref((raw_date.getMonth() + 1).toString().padStart(2, '0'))
274 313
275 -const onConfirm = async ({ selectedValue, selectedOptions }) => { // 选择日期回调 314 +const onConfirm = async ({ selectedValue, selectedOptions }) => {
315 + // 选择日期回调
276 // selectedValue 可能是数组或对象,NutUI 文档 316 // selectedValue 可能是数组或对象,NutUI 文档
277 // selectedOptions 是选项对象数组 317 // selectedOptions 是选项对象数组
278 // year-month 模式下 selectedValue 可能是 [year, month] 318 // year-month 模式下 selectedValue 可能是 [year, month]
279 // 实际上 NutUI DatePicker confirm 事件参数:{ selectedValue, selectedOptions } 319 // 实际上 NutUI DatePicker confirm 事件参数:{ selectedValue, selectedOptions }
280 320
281 - showPicker.value = false; 321 + showPicker.value = false
282 // selectedValue: ['2024', '02'] 322 // selectedValue: ['2024', '02']
283 - const [year, month] = selectedValue; 323 + const [year, month] = selectedValue
284 - currentDateText.value = month; 324 + currentDateText.value = month
285 325
286 // 清空选择 326 // 清空选择
287 - checked_day.value = ''; 327 + checked_day.value = ''
288 - checked_time.value = -1; 328 + checked_time.value = -1
289 - checked_day_reserve_full.value = null; 329 + checked_day_reserve_full.value = null
290 // 选择日期后,查询月份信息 330 // 选择日期后,查询月份信息
291 - const { code, data } = await canReserveDateListAPI({ month: `${year}-${month}` }); 331 + const { code, data } = await canReserveDateListAPI({ month: `${year}-${month}` })
292 if (code) { 332 if (code) {
293 // 日期列表 333 // 日期列表
294 - dates_list.value = data || []; 334 + dates_list.value = data || []
295 // 今日之前都不可约 335 // 今日之前都不可约
296 - dates_list.value.forEach((date) => { 336 + dates_list.value.forEach(date => {
297 if (dayjs(date.month_date).isBefore(dayjs())) { 337 if (dayjs(date.month_date).isBefore(dayjs())) {
298 - date.reserve_full = ReserveStatus.OVERDUE; 338 + date.reserve_full = ReserveStatus.OVERDUE
299 } 339 }
300 - }); 340 + })
301 - dates.value = dates_list.value.map(item => item.month_date); 341 + dates.value = dates_list.value.map(item => item.month_date)
302 } 342 }
303 } 343 }
304 344
305 const onCancel = () => { 345 const onCancel = () => {
306 - showPicker.value = false; 346 + showPicker.value = false
307 } 347 }
308 348
309 const nextBtn = () => { 349 const nextBtn = () => {
310 if (!checked_day.value || checked_time.value === -1) { 350 if (!checked_day.value || checked_time.value === -1) {
311 - Taro.showToast({ title: '请选择日期和时间段', icon: 'none' }); 351 + Taro.showToast({ title: '请选择日期和时间段', icon: 'none' })
312 } else { 352 } else {
313 - go('/submit', { date: checked_day.value, time: `${timePeriod.value[checked_time.value]['begin_time'].slice(0, -3)}-${timePeriod.value[checked_time.value]['end_time'].slice(0, -3)}`, price: checked_day_price.value, period_type: timePeriod.value[checked_time.value].period_type }); 353 + go('/submit', {
354 + date: checked_day.value,
355 + time: `${timePeriod.value[checked_time.value]['begin_time'].slice(0, -3)}-${timePeriod.value[checked_time.value]['end_time'].slice(0, -3)}`,
356 + price: checked_day_price.value,
357 + period_type: timePeriod.value[checked_time.value].period_type
358 + })
314 } 359 }
315 } 360 }
316 </script> 361 </script>
...@@ -319,13 +364,12 @@ const nextBtn = () => { ...@@ -319,13 +364,12 @@ const nextBtn = () => {
319 .booking-page { 364 .booking-page {
320 position: relative; 365 position: relative;
321 min-height: 100vh; 366 min-height: 100vh;
322 - background-color: #F6F6F6; 367 + background-color: #f6f6f6;
323 .calendar { 368 .calendar {
324 padding: 32rpx 16rpx; 369 padding: 32rpx 16rpx;
325 .choose-date { 370 .choose-date {
326 border-radius: 10rpx; 371 border-radius: 10rpx;
327 - background-color: #FFFFFF; 372 + background-color: #ffffff;
328 -
329 373
330 .title { 374 .title {
331 padding: 16rpx 24rpx; 375 padding: 16rpx 24rpx;
...@@ -335,20 +379,20 @@ const nextBtn = () => { ...@@ -335,20 +379,20 @@ const nextBtn = () => {
335 .text { 379 .text {
336 &::before { 380 &::before {
337 content: ''; 381 content: '';
338 - border: 4rpx solid #A67939; 382 + border: 4rpx solid #a67939;
339 margin-right: 16rpx; 383 margin-right: 16rpx;
340 } 384 }
341 } 385 }
342 .day { 386 .day {
343 - background-color: #FFFBF3; 387 + background-color: #fffbf3;
344 border-radius: 14rpx; 388 border-radius: 14rpx;
345 - border: 2rpx solid #A67939; 389 + border: 2rpx solid #a67939;
346 padding: 6rpx 16rpx; 390 padding: 6rpx 16rpx;
347 - color: #A67939; 391 + color: #a67939;
348 } 392 }
349 } 393 }
350 .days-of-week { 394 .days-of-week {
351 - background-color: #F6F6F6; 395 + background-color: #f6f6f6;
352 display: flex; 396 display: flex;
353 padding: 24rpx 1%; 397 padding: 24rpx 1%;
354 font-size: 27rpx; 398 font-size: 27rpx;
...@@ -369,39 +413,39 @@ const nextBtn = () => { ...@@ -369,39 +413,39 @@ const nextBtn = () => {
369 text-align: center; 413 text-align: center;
370 margin: 0 10rpx; 414 margin: 0 10rpx;
371 padding: 16rpx 0; 415 padding: 16rpx 0;
372 - border: 2rpx solid #FFF; 416 + border: 2rpx solid #fff;
373 .day-lunar { 417 .day-lunar {
374 - color: #1E1E1E; 418 + color: #1e1e1e;
375 font-size: 27rpx; 419 font-size: 27rpx;
376 margin-bottom: 10rpx; 420 margin-bottom: 10rpx;
377 } 421 }
378 .day-text { 422 .day-text {
379 - color: #1E1E1E; 423 + color: #1e1e1e;
380 font-weight: bold; 424 font-weight: bold;
381 font-size: 34rpx; 425 font-size: 34rpx;
382 } 426 }
383 .day-price { 427 .day-price {
384 - color: #A67939; 428 + color: #a67939;
385 font-size: 27rpx; 429 font-size: 27rpx;
386 } 430 }
387 &.checked { 431 &.checked {
388 - border: 2rpx solid #A67939; 432 + border: 2rpx solid #a67939;
389 border-radius: 10rpx; 433 border-radius: 10rpx;
390 - background-color: #FFFBF3; 434 + background-color: #fffbf3;
391 } 435 }
392 &.disabled { 436 &.disabled {
393 .day-lunar { 437 .day-lunar {
394 - color: #C7C7C7; 438 + color: #c7c7c7;
395 margin-bottom: 10rpx; 439 margin-bottom: 10rpx;
396 } 440 }
397 .day-text { 441 .day-text {
398 - color: #C7C7C7; 442 + color: #c7c7c7;
399 } 443 }
400 .day-price { 444 .day-price {
401 - color: #C7C7C7; 445 + color: #c7c7c7;
402 } 446 }
403 .day-no-booking { 447 .day-no-booking {
404 - color: #C7C7C7; 448 + color: #c7c7c7;
405 font-size: 24rpx; 449 font-size: 24rpx;
406 } 450 }
407 } 451 }
...@@ -418,7 +462,7 @@ const nextBtn = () => { ...@@ -418,7 +462,7 @@ const nextBtn = () => {
418 .text { 462 .text {
419 &::before { 463 &::before {
420 content: ''; 464 content: '';
421 - border: 4rpx solid #A67939; 465 + border: 4rpx solid #a67939;
422 margin-right: 16rpx; 466 margin-right: 16rpx;
423 } 467 }
424 } 468 }
...@@ -428,37 +472,37 @@ const nextBtn = () => { ...@@ -428,37 +472,37 @@ const nextBtn = () => {
428 display: flex; 472 display: flex;
429 align-items: center; 473 align-items: center;
430 justify-content: space-between; 474 justify-content: space-between;
431 - background-color: #FFF; 475 + background-color: #fff;
432 border-radius: 10rpx; 476 border-radius: 10rpx;
433 padding: 27rpx; 477 padding: 27rpx;
434 margin: 32rpx 0; 478 margin: 32rpx 0;
435 .left { 479 .left {
436 display: flex; 480 display: flex;
437 align-items: center; 481 align-items: center;
438 - color: #1E1E1E; 482 + color: #1e1e1e;
439 .icon { 483 .icon {
440 width: 38rpx; 484 width: 38rpx;
441 height: 38rpx; 485 height: 38rpx;
442 margin-right: 16rpx; 486 margin-right: 16rpx;
443 } 487 }
444 .price { 488 .price {
445 - color:#A67939; 489 + color: #a67939;
446 margin-left: 16rpx; 490 margin-left: 16rpx;
447 } 491 }
448 } 492 }
449 .right { 493 .right {
450 - color: #A67939; 494 + color: #a67939;
451 } 495 }
452 &.disabled { 496 &.disabled {
453 - background-color: #E0E0E0; 497 + background-color: #e0e0e0;
454 .left { 498 .left {
455 - color: #C7C7C7; 499 + color: #c7c7c7;
456 .price { 500 .price {
457 - color:#C7C7C7; 501 + color: #c7c7c7;
458 } 502 }
459 } 503 }
460 .right { 504 .right {
461 - color: #C7C7C7; 505 + color: #c7c7c7;
462 } 506 }
463 } 507 }
464 } 508 }
...@@ -472,12 +516,12 @@ const nextBtn = () => { ...@@ -472,12 +516,12 @@ const nextBtn = () => {
472 width: 750rpx; 516 width: 750rpx;
473 display: flex; 517 display: flex;
474 left: 0; 518 left: 0;
475 - background-color: #FFF; 519 + background-color: #fff;
476 align-items: center; 520 align-items: center;
477 justify-content: center; 521 justify-content: center;
478 - box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.12); 522 + box-shadow: 0 -10rpx 8rpx 0 rgba(0, 0, 0, 0.12);
479 .button { 523 .button {
480 - color: #FFF; 524 + color: #fff;
481 padding: 27rpx 0; 525 padding: 27rpx 0;
482 border-radius: 16rpx; 526 border-radius: 16rpx;
483 font-size: 35rpx; 527 font-size: 35rpx;
......
...@@ -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 }
......
...@@ -6,18 +6,32 @@ ...@@ -6,18 +6,32 @@
6 </view> 6 </view>
7 7
8 <view class="action-area"> 8 <view class="action-area">
9 - <nut-button type="primary" size="large" @click="startScan" :disabled="isScanning" :loading="isScanning"> 9 + <nut-button
10 + type="primary"
11 + size="large"
12 + @click="startScan"
13 + :disabled="isScanning"
14 + :loading="isScanning"
15 + >
10 {{ isScanning ? '正在扫描...' : '开始 NFC 扫描' }} 16 {{ isScanning ? '正在扫描...' : '开始 NFC 扫描' }}
11 </nut-button> 17 </nut-button>
12 18
13 - <nut-button v-if="isScanning" type="danger" size="large" @click="stopScan" style="margin-top: 40rpx;"> 19 + <nut-button
20 + v-if="isScanning"
21 + type="danger"
22 + size="large"
23 + @click="stopScan"
24 + style="margin-top: 40rpx"
25 + >
14 停止扫描 26 停止扫描
15 </nut-button> 27 </nut-button>
16 </view> 28 </view>
17 29
18 <view class="status-area"> 30 <view class="status-area">
19 <text class="status-label">当前状态:</text> 31 <text class="status-label">当前状态:</text>
20 - <text class="status-text" :class="{ 'scanning': isScanning, 'error': !!error }">{{ status }}</text> 32 + <text class="status-text" :class="{ scanning: isScanning, error: !!error }">{{
33 + status
34 + }}</text>
21 </view> 35 </view>
22 36
23 <view class="result-area" v-if="result"> 37 <view class="result-area" v-if="result">
...@@ -41,18 +55,18 @@ ...@@ -41,18 +55,18 @@
41 </template> 55 </template>
42 56
43 <script setup> 57 <script setup>
44 -import { ref, onUnmounted } from 'vue'; 58 +import { ref, onUnmounted } from 'vue'
45 -import Taro from '@tarojs/taro'; 59 +import Taro from '@tarojs/taro'
46 60
47 -const isScanning = ref(false); 61 +const isScanning = ref(false)
48 -const status = ref('等待操作'); 62 +const status = ref('等待操作')
49 -const result = ref(''); 63 +const result = ref('')
50 -const error = ref(''); 64 +const error = ref('')
51 -const debugInfo = ref(''); 65 +const debugInfo = ref('')
52 66
53 -let nfcAdapter = null; 67 +let nfcAdapter = null
54 68
55 -const safe_stringify = (data) => { 69 +const safe_stringify = data => {
56 try { 70 try {
57 return JSON.stringify( 71 return JSON.stringify(
58 data, 72 data,
...@@ -60,63 +74,63 @@ const safe_stringify = (data) => { ...@@ -60,63 +74,63 @@ const safe_stringify = (data) => {
60 if (value instanceof ArrayBuffer) { 74 if (value instanceof ArrayBuffer) {
61 return { 75 return {
62 __type: 'ArrayBuffer', 76 __type: 'ArrayBuffer',
63 - hex: bufferToHex(value), 77 + hex: bufferToHex(value)
64 - }; 78 + }
65 } 79 }
66 if (value && value.buffer instanceof ArrayBuffer) { 80 if (value && value.buffer instanceof ArrayBuffer) {
67 return { 81 return {
68 __type: 'TypedArray', 82 __type: 'TypedArray',
69 - hex: bufferToHex(value.buffer), 83 + hex: bufferToHex(value.buffer)
70 - }; 84 + }
71 } 85 }
72 - return value; 86 + return value
73 }, 87 },
74 2 88 2
75 - ); 89 + )
76 } catch (e) { 90 } catch (e) {
77 - return String(data); 91 + return String(data)
78 } 92 }
79 -}; 93 +}
80 94
81 const startScan = async () => { 95 const startScan = async () => {
82 - error.value = ''; 96 + error.value = ''
83 - result.value = ''; 97 + result.value = ''
84 - debugInfo.value = ''; 98 + debugInfo.value = ''
85 99
86 - let systemInfo = null; 100 + let systemInfo = null
87 try { 101 try {
88 - systemInfo = Taro.getSystemInfoSync(); 102 + systemInfo = Taro.getSystemInfoSync()
89 } catch (e) {} 103 } catch (e) {}
90 - const envType = Taro.getEnv && Taro.getEnv(); 104 + const envType = Taro.getEnv && Taro.getEnv()
91 - const platform = systemInfo && systemInfo.platform ? systemInfo.platform : ''; 105 + const platform = systemInfo && systemInfo.platform ? systemInfo.platform : ''
92 - const system = systemInfo && systemInfo.system ? systemInfo.system : ''; 106 + const system = systemInfo && systemInfo.system ? systemInfo.system : ''
93 - const model = systemInfo && systemInfo.model ? systemInfo.model : ''; 107 + const model = systemInfo && systemInfo.model ? systemInfo.model : ''
94 - const SDKVersion = systemInfo && systemInfo.SDKVersion ? systemInfo.SDKVersion : ''; 108 + const SDKVersion = systemInfo && systemInfo.SDKVersion ? systemInfo.SDKVersion : ''
95 - const version = systemInfo && systemInfo.version ? systemInfo.version : ''; 109 + const version = systemInfo && systemInfo.version ? systemInfo.version : ''
96 - debugInfo.value = `env: ${envType}\nplatform: ${platform}\nsystem: ${system}\nmodel: ${model}\nSDKVersion: ${SDKVersion}\nversion: ${version}`; 110 + debugInfo.value = `env: ${envType}\nplatform: ${platform}\nsystem: ${system}\nmodel: ${model}\nSDKVersion: ${SDKVersion}\nversion: ${version}`
97 111
98 if (platform === 'ios') { 112 if (platform === 'ios') {
99 - error.value = 'iOS 端微信小程序通常不支持 NFC(该能力主要在 Android 可用)'; 113 + error.value = 'iOS 端微信小程序通常不支持 NFC(该能力主要在 Android 可用)'
100 - status.value = '启动失败'; 114 + status.value = '启动失败'
101 - return; 115 + return
102 } 116 }
103 117
104 if (!Taro.getNFCAdapter) { 118 if (!Taro.getNFCAdapter) {
105 - error.value = '当前环境不支持 NFC 接口'; 119 + error.value = '当前环境不支持 NFC 接口'
106 - status.value = '启动失败'; 120 + status.value = '启动失败'
107 - return; 121 + return
108 } 122 }
109 123
110 if (envType && Taro.ENV_TYPE && envType !== Taro.ENV_TYPE.WEAPP) { 124 if (envType && Taro.ENV_TYPE && envType !== Taro.ENV_TYPE.WEAPP) {
111 - error.value = '当前不是微信小程序环境,无法使用 NFC'; 125 + error.value = '当前不是微信小程序环境,无法使用 NFC'
112 - status.value = '启动失败'; 126 + status.value = '启动失败'
113 - return; 127 + return
114 } 128 }
115 129
116 try { 130 try {
117 - nfcAdapter = Taro.getNFCAdapter(); 131 + nfcAdapter = Taro.getNFCAdapter()
118 132
119 - status.value = '正在初始化 NFC...'; 133 + status.value = '正在初始化 NFC...'
120 134
121 await nfcAdapter.startDiscovery({ 135 await nfcAdapter.startDiscovery({
122 techs: [ 136 techs: [
...@@ -127,102 +141,101 @@ const startScan = async () => { ...@@ -127,102 +141,101 @@ const startScan = async () => {
127 'ISO-DEP', 141 'ISO-DEP',
128 'MIFARE-CLASSIC', 142 'MIFARE-CLASSIC',
129 'MIFARE-ULTRALIGHT', 143 'MIFARE-ULTRALIGHT',
130 - 'NDEF', 144 + 'NDEF'
131 ], 145 ],
132 success: () => { 146 success: () => {
133 - status.value = '请将手机背面靠近 NFC 标签'; 147 + status.value = '请将手机背面靠近 NFC 标签'
134 - isScanning.value = true; 148 + isScanning.value = true
135 }, 149 },
136 - fail: (err) => { 150 + fail: err => {
137 - console.error('NFC start error:', err); 151 + console.error('NFC start error:', err)
138 // 错误码参考微信文档 152 // 错误码参考微信文档
139 - debugInfo.value = `${debugInfo.value}\n\nstartDiscovery fail:\n${err && (err.errMsg || JSON.stringify(err))}`; 153 + debugInfo.value = `${debugInfo.value}\n\nstartDiscovery fail:\n${err && (err.errMsg || JSON.stringify(err))}`
140 if (err.errCode === 13000) { 154 if (err.errCode === 13000) {
141 - error.value = '设备不支持 NFC'; 155 + error.value = '设备不支持 NFC'
142 } else if (err.errCode === 13001) { 156 } else if (err.errCode === 13001) {
143 - error.value = '系统 NFC 开关未开启'; 157 + error.value = '系统 NFC 开关未开启'
144 } else if (err.errMsg && err.errMsg.includes('platform is not supported')) { 158 } else if (err.errMsg && err.errMsg.includes('platform is not supported')) {
145 - error.value = '开发者工具不支持 NFC,请使用真机调试'; 159 + error.value = '开发者工具不支持 NFC,请使用真机调试'
146 } else { 160 } else {
147 - error.value = 'NFC 启动失败: ' + (err.errMsg || JSON.stringify(err)); 161 + error.value = `NFC 启动失败: ${err.errMsg || JSON.stringify(err)}`
148 } 162 }
149 - status.value = '启动失败'; 163 + status.value = '启动失败'
150 } 164 }
151 - }); 165 + })
152 166
153 - nfcAdapter.onDiscovered((res) => { 167 + nfcAdapter.onDiscovered(res => {
154 - console.log('NFC Discovered:', res); 168 + console.log('NFC Discovered:', res)
155 - status.value = '发现标签,正在读取...'; 169 + status.value = '发现标签,正在读取...'
156 - Taro.vibrateShort(); 170 + Taro.vibrateShort()
157 171
158 - handleNfcMessage(res); 172 + handleNfcMessage(res)
159 173
160 // 扫描成功后,通常可以选择是否停止。这里我们保持扫描状态,或者提供停止按钮。 174 // 扫描成功后,通常可以选择是否停止。这里我们保持扫描状态,或者提供停止按钮。
161 // 用户需求是“扫描成功后显示信息内容”,为了防止重复读取造成刷屏,可以考虑读取成功后自动停止。 175 // 用户需求是“扫描成功后显示信息内容”,为了防止重复读取造成刷屏,可以考虑读取成功后自动停止。
162 // 但如果是测试页,可能想连续测多个。我选择不自动停止,但更新结果。 176 // 但如果是测试页,可能想连续测多个。我选择不自动停止,但更新结果。
163 - }); 177 + })
164 -
165 } catch (e) { 178 } catch (e) {
166 - console.error('NFC Adapter error:', e); 179 + console.error('NFC Adapter error:', e)
167 - debugInfo.value = `${debugInfo.value}\n\ngetNFCAdapter error:\n${e && (e.errMsg || e.message || JSON.stringify(e))}`; 180 + debugInfo.value = `${debugInfo.value}\n\ngetNFCAdapter error:\n${e && (e.errMsg || e.message || JSON.stringify(e))}`
168 - error.value = 'NFC 初始化失败(可能是设备/系统不支持,或不在可用环境)'; 181 + error.value = 'NFC 初始化失败(可能是设备/系统不支持,或不在可用环境)'
169 - status.value = '错误'; 182 + status.value = '错误'
170 } 183 }
171 -}; 184 +}
172 185
173 const stopScan = () => { 186 const stopScan = () => {
174 if (nfcAdapter) { 187 if (nfcAdapter) {
175 nfcAdapter.stopDiscovery({ 188 nfcAdapter.stopDiscovery({
176 success: () => { 189 success: () => {
177 - status.value = '已停止扫描'; 190 + status.value = '已停止扫描'
178 - isScanning.value = false; 191 + isScanning.value = false
179 }, 192 },
180 - fail: (err) => { 193 + fail: err => {
181 - console.error('Stop NFC fail', err); 194 + console.error('Stop NFC fail', err)
182 }, 195 },
183 complete: () => { 196 complete: () => {
184 // 确保状态更新 197 // 确保状态更新
185 - isScanning.value = false; 198 + isScanning.value = false
186 if (nfcAdapter && nfcAdapter.offDiscovered) { 199 if (nfcAdapter && nfcAdapter.offDiscovered) {
187 - nfcAdapter.offDiscovered(); 200 + nfcAdapter.offDiscovered()
188 } 201 }
189 } 202 }
190 - }); 203 + })
191 } else { 204 } else {
192 - isScanning.value = false; 205 + isScanning.value = false
193 } 206 }
194 -}; 207 +}
195 208
196 // 辅助函数:将 ArrayBuffer 转为 16 进制字符串 209 // 辅助函数:将 ArrayBuffer 转为 16 进制字符串
197 -const bufferToHex = (buffer) => { 210 +const bufferToHex = buffer => {
198 return Array.from(new Uint8Array(buffer)) 211 return Array.from(new Uint8Array(buffer))
199 .map(b => b.toString(16).padStart(2, '0')) 212 .map(b => b.toString(16).padStart(2, '0'))
200 .join(':') 213 .join(':')
201 - .toUpperCase(); 214 + .toUpperCase()
202 -}; 215 +}
203 216
204 -const handleNfcMessage = (res) => { 217 +const handleNfcMessage = res => {
205 - let content = ''; 218 + let content = ''
206 219
207 // 1. 获取 UID 220 // 1. 获取 UID
208 if (res.id) { 221 if (res.id) {
209 - content += `UID: ${bufferToHex(res.id)}\n`; 222 + content += `UID: ${bufferToHex(res.id)}\n`
210 } 223 }
211 224
212 // 2. 获取 Tech Types 225 // 2. 获取 Tech Types
213 if (res.techs && res.techs.length) { 226 if (res.techs && res.techs.length) {
214 - content += `Techs: ${res.techs.join(', ')}\n`; 227 + content += `Techs: ${res.techs.join(', ')}\n`
215 } 228 }
216 229
217 // 3. 解析 NDEF 消息 230 // 3. 解析 NDEF 消息
218 if (res.messages && res.messages.length > 0) { 231 if (res.messages && res.messages.length > 0) {
219 - content += '\n--- NDEF Records ---\n'; 232 + content += '\n--- NDEF Records ---\n'
220 try { 233 try {
221 // res.messages 是一个数组,通常取第一个 NDEF Message 234 // res.messages 是一个数组,通常取第一个 NDEF Message
222 - const records = res.messages[0].records || []; 235 + const records = res.messages[0].records || []
223 236
224 records.forEach((record, index) => { 237 records.forEach((record, index) => {
225 - content += `[Record ${index + 1}]\n`; 238 + content += `[Record ${index + 1}]\n`
226 239
227 // Type Name Format (TNF) - bits 0-2 of first byte (not directly exposed in simple objects usually, 240 // Type Name Format (TNF) - bits 0-2 of first byte (not directly exposed in simple objects usually,
228 // but we might need to parse payload if it's raw. 241 // but we might need to parse payload if it's raw.
...@@ -230,49 +243,48 @@ const handleNfcMessage = (res) => { ...@@ -230,49 +243,48 @@ const handleNfcMessage = (res) => {
230 243
231 if (record.type) { 244 if (record.type) {
232 // record.type is ArrayBuffer 245 // record.type is ArrayBuffer
233 - const typeStr = new TextDecoder().decode(record.type); 246 + const typeStr = new TextDecoder().decode(record.type)
234 - content += `Type: ${typeStr}\n`; 247 + content += `Type: ${typeStr}\n`
235 248
236 // Text Record Parsing (Type = 'T') 249 // Text Record Parsing (Type = 'T')
237 if (typeStr === 'T') { 250 if (typeStr === 'T') {
238 - const payload = new Uint8Array(record.payload); 251 + const payload = new Uint8Array(record.payload)
239 if (payload.length > 0) { 252 if (payload.length > 0) {
240 - const statusByte = payload[0]; 253 + const statusByte = payload[0]
241 - const langCodeLen = statusByte & 0x3F; 254 + const langCodeLen = statusByte & 0x3f
242 // const isUtf16 = (statusByte & 0x80) !== 0; // bit 7 255 // const isUtf16 = (statusByte & 0x80) !== 0; // bit 7
243 256
244 // 提取文本内容 257 // 提取文本内容
245 - const textBytes = payload.slice(1 + langCodeLen); 258 + const textBytes = payload.slice(1 + langCodeLen)
246 - const text = new TextDecoder().decode(textBytes); 259 + const text = new TextDecoder().decode(textBytes)
247 - content += `Content: ${text}\n`; 260 + content += `Content: ${text}\n`
248 } 261 }
249 } else { 262 } else {
250 // 其他类型,尝试直接转码显示,或者显示 HEX 263 // 其他类型,尝试直接转码显示,或者显示 HEX
251 - const text = new TextDecoder().decode(record.payload); 264 + const text = new TextDecoder().decode(record.payload)
252 // 简单的过滤,如果看起来像乱码则显示 Hex 265 // 简单的过滤,如果看起来像乱码则显示 Hex
253 if (/[\x00-\x08\x0E-\x1F]/.test(text)) { 266 if (/[\x00-\x08\x0E-\x1F]/.test(text)) {
254 - content += `Payload (Hex): ${bufferToHex(record.payload)}\n`; 267 + content += `Payload (Hex): ${bufferToHex(record.payload)}\n`
255 } else { 268 } else {
256 - content += `Payload: ${text}\n`; 269 + content += `Payload: ${text}\n`
257 } 270 }
258 } 271 }
259 } 272 }
260 - }); 273 + })
261 -
262 } catch (parseErr) { 274 } catch (parseErr) {
263 - console.error(parseErr); 275 + console.error(parseErr)
264 - content += '解析 NDEF 数据出错\n'; 276 + content += '解析 NDEF 数据出错\n'
265 } 277 }
266 } else { 278 } else {
267 - content += '\n(无 NDEF 消息)\n'; 279 + content += '\n(无 NDEF 消息)\n'
268 } 280 }
269 281
270 - result.value = `--- 原始数据 ---\n${safe_stringify(res)}\n\n--- 解析结果 ---\n${content}`; 282 + result.value = `--- 原始数据 ---\n${safe_stringify(res)}\n\n--- 解析结果 ---\n${content}`
271 -}; 283 +}
272 284
273 onUnmounted(() => { 285 onUnmounted(() => {
274 - stopScan(); 286 + stopScan()
275 -}); 287 +})
276 </script> 288 </script>
277 289
278 <style lang="less"> 290 <style lang="less">
......
...@@ -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;
......
...@@ -14,14 +14,13 @@ import { onMounted } from 'vue' ...@@ -14,14 +14,13 @@ import { onMounted } from 'vue'
14 import Taro from '@tarojs/taro' 14 import Taro from '@tarojs/taro'
15 import { useGo } from '@/hooks/useGo' 15 import { useGo } from '@/hooks/useGo'
16 16
17 -const go = useGo(); 17 +const go = useGo()
18 18
19 onMounted(() => { 19 onMounted(() => {
20 Taro.nextTick(() => { 20 Taro.nextTick(() => {
21 go('/pages/offlineBookingList/index') 21 go('/pages/offlineBookingList/index')
22 }) 22 })
23 -}); 23 +})
24 -
25 </script> 24 </script>
26 25
27 <style lang="less"> 26 <style lang="less">
......
1 export default { 1 export default {
2 navigationBarTitleText: '离线预约详情' 2 navigationBarTitleText: '离线预约详情'
3 } 3 }
4 -
......
...@@ -47,7 +47,10 @@ import { ref, computed } from 'vue' ...@@ -47,7 +47,10 @@ import { ref, computed } from 'vue'
47 import Taro, { useDidShow, useRouter as useTaroRouter } from '@tarojs/taro' 47 import Taro, { useDidShow, useRouter as useTaroRouter } from '@tarojs/taro'
48 import { IconFont } from '@nutui/icons-vue-taro' 48 import { IconFont } from '@nutui/icons-vue-taro'
49 import offlineQrCode from '@/components/offlineQrCode.vue' 49 import offlineQrCode from '@/components/offlineQrCode.vue'
50 -import { get_offline_booking_by_pay_id, build_offline_qr_list } from '@/composables/useOfflineBookingCache' 50 +import {
51 + get_offline_booking_by_pay_id,
52 + build_offline_qr_list
53 +} from '@/composables/useOfflineBookingCache'
51 54
52 const router = useTaroRouter() 55 const router = useTaroRouter()
53 const bill_info = ref(null) 56 const bill_info = ref(null)
...@@ -105,15 +108,15 @@ useDidShow(() => { ...@@ -105,15 +108,15 @@ useDidShow(() => {
105 <style lang="less"> 108 <style lang="less">
106 .offline-booking-detail-page { 109 .offline-booking-detail-page {
107 min-height: 100vh; 110 min-height: 100vh;
108 - background-color: #F6F6F6; 111 + background-color: #f6f6f6;
109 112
110 .header-tip { 113 .header-tip {
111 display: flex; 114 display: flex;
112 align-items: center; 115 align-items: center;
113 padding: 20rpx 32rpx; 116 padding: 20rpx 32rpx;
114 - color: #A67939; 117 + color: #a67939;
115 font-size: 26rpx; 118 font-size: 26rpx;
116 - background: #FFF; 119 + background: #fff;
117 } 120 }
118 121
119 .content { 122 .content {
...@@ -122,11 +125,11 @@ useDidShow(() => { ...@@ -122,11 +125,11 @@ useDidShow(() => {
122 } 125 }
123 126
124 .detail-wrapper { 127 .detail-wrapper {
125 - background-color: #FFF; 128 + background-color: #fff;
126 border-radius: 16rpx; 129 border-radius: 16rpx;
127 padding: 32rpx; 130 padding: 32rpx;
128 margin-top: 32rpx; 131 margin-top: 32rpx;
129 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.1); 132 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.1);
130 133
131 .detail-item { 134 .detail-item {
132 display: flex; 135 display: flex;
...@@ -156,13 +159,13 @@ useDidShow(() => { ...@@ -156,13 +159,13 @@ useDidShow(() => {
156 left: 0; 159 left: 0;
157 width: 750rpx; 160 width: 750rpx;
158 padding: 24rpx 32rpx; 161 padding: 24rpx 32rpx;
159 - background: #FFF; 162 + background: #fff;
160 box-sizing: border-box; 163 box-sizing: border-box;
161 - box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.06); 164 + box-shadow: 0 -10rpx 8rpx 0 rgba(0, 0, 0, 0.06);
162 165
163 .back-btn { 166 .back-btn {
164 - background-color: #A67939; 167 + background-color: #a67939;
165 - color: #FFF; 168 + color: #fff;
166 border-radius: 16rpx; 169 border-radius: 16rpx;
167 font-size: 32rpx; 170 font-size: 32rpx;
168 padding: 12rpx 0; 171 padding: 12rpx 0;
......
1 export default { 1 export default {
2 navigationBarTitleText: '离线预约记录' 2 navigationBarTitleText: '离线预约记录'
3 } 3 }
4 -
......
...@@ -53,15 +53,15 @@ useDidShow(() => { ...@@ -53,15 +53,15 @@ useDidShow(() => {
53 <style lang="less"> 53 <style lang="less">
54 .offline-booking-list-page { 54 .offline-booking-list-page {
55 min-height: 100vh; 55 min-height: 100vh;
56 - background-color: #F6F6F6; 56 + background-color: #f6f6f6;
57 57
58 .header-tip { 58 .header-tip {
59 display: flex; 59 display: flex;
60 align-items: center; 60 align-items: center;
61 padding: 20rpx 32rpx; 61 padding: 20rpx 32rpx;
62 - color: #A67939; 62 + color: #a67939;
63 font-size: 26rpx; 63 font-size: 26rpx;
64 - background: #FFF; 64 + background: #fff;
65 } 65 }
66 66
67 .list-wrapper { 67 .list-wrapper {
...@@ -71,7 +71,7 @@ useDidShow(() => { ...@@ -71,7 +71,7 @@ useDidShow(() => {
71 .empty { 71 .empty {
72 padding: 120rpx 0; 72 padding: 120rpx 0;
73 text-align: center; 73 text-align: center;
74 - color: #A67939; 74 + color: #a67939;
75 font-size: 32rpx; 75 font-size: 32rpx;
76 } 76 }
77 77
...@@ -81,13 +81,13 @@ useDidShow(() => { ...@@ -81,13 +81,13 @@ useDidShow(() => {
81 left: 0; 81 left: 0;
82 width: 750rpx; 82 width: 750rpx;
83 padding: 24rpx 32rpx; 83 padding: 24rpx 32rpx;
84 - background: #FFF; 84 + background: #fff;
85 box-sizing: border-box; 85 box-sizing: border-box;
86 - box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.06); 86 + box-shadow: 0 -10rpx 8rpx 0 rgba(0, 0, 0, 0.06);
87 87
88 .home-btn { 88 .home-btn {
89 - background-color: #A67939; 89 + background-color: #a67939;
90 - color: #FFF; 90 + color: #fff;
91 border-radius: 16rpx; 91 border-radius: 16rpx;
92 font-size: 32rpx; 92 font-size: 32rpx;
93 padding: 12rpx 0; 93 padding: 12rpx 0;
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
25 placeholder="请输入证件号码" 25 placeholder="请输入证件号码"
26 @blur="checkIdCode" 26 @blur="checkIdCode"
27 :maxlength="id_type === 1 ? 18 : 30" 27 :maxlength="id_type === 1 ? 18 : 30"
28 - > 28 + />
29 </view> 29 </view>
30 <view class="tip-block"> 30 <view class="tip-block">
31 <view class="tip-title"> 31 <view class="tip-title">
...@@ -65,72 +65,78 @@ ...@@ -65,72 +65,78 @@
65 import { ref, computed } from 'vue' 65 import { ref, computed } from 'vue'
66 import Taro from '@tarojs/taro' 66 import Taro from '@tarojs/taro'
67 import { IconFont } from '@nutui/icons-vue-taro' 67 import { IconFont } from '@nutui/icons-vue-taro'
68 -import qrCodeSearch from '@/components/qrCodeSearch'; 68 +import qrCodeSearch from '@/components/qrCodeSearch'
69 import { useGo } from '@/hooks/useGo' 69 import { useGo } from '@/hooks/useGo'
70 70
71 -const go = useGo(); 71 +const go = useGo()
72 -const is_search = ref(false); 72 +const is_search = ref(false)
73 -const idCode = ref(''); 73 +const idCode = ref('')
74 -const id_number = ref(''); 74 +const id_number = ref('')
75 -const show_id_type_picker = ref(false); 75 +const show_id_type_picker = ref(false)
76 const id_type_options = [ 76 const id_type_options = [
77 { label: '身份证', value: 1 }, 77 { label: '身份证', value: 1 },
78 { label: '其他', value: 3 } 78 { label: '其他', value: 3 }
79 -]; 79 +]
80 -const id_type = ref(id_type_options[0].value); 80 +const id_type = ref(id_type_options[0].value)
81 -const id_type_picker_value = ref([String(id_type.value)]); 81 +const id_type_picker_value = ref([String(id_type.value)])
82 82
83 const id_type_columns = computed(() => { 83 const id_type_columns = computed(() => {
84 return id_type_options.map(item => ({ 84 return id_type_options.map(item => ({
85 text: item.label, 85 text: item.label,
86 value: String(item.value) 86 value: String(item.value)
87 - })); 87 + }))
88 -}); 88 +})
89 const id_type_label = computed(() => { 89 const id_type_label = computed(() => {
90 - return id_type_options.find(item => item.value === id_type.value)?.label || id_type_options[0].label; 90 + return (
91 -}); 91 + id_type_options.find(item => item.value === id_type.value)?.label || id_type_options[0].label
92 + )
93 +})
92 94
93 const open_id_type_picker = () => { 95 const open_id_type_picker = () => {
94 - id_type_picker_value.value = [String(id_type.value)]; 96 + id_type_picker_value.value = [String(id_type.value)]
95 - show_id_type_picker.value = true; 97 + show_id_type_picker.value = true
96 } 98 }
97 99
98 const on_id_type_confirm = ({ selectedValue }) => { 100 const on_id_type_confirm = ({ selectedValue }) => {
99 - const value = selectedValue?.[0]; 101 + const value = selectedValue?.[0]
100 - id_type.value = Number(value) || 1; 102 + id_type.value = Number(value) || 1
101 - show_id_type_picker.value = false; 103 + show_id_type_picker.value = false
102 } 104 }
103 105
104 // 简单的身份证校验 106 // 简单的身份证校验
105 -const validateCIN = (id) => { 107 +const validateCIN = id => {
106 - return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(id); 108 + return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(id)
107 } 109 }
108 110
109 -const checkIdCode = () => { // 检查身份证号是否为空 111 +const checkIdCode = () => {
110 - if (id_type.value !== 1) return true; 112 + // 检查身份证号是否为空
113 + if (id_type.value !== 1) {
114 + return true
115 + }
111 116
112 - let flag = true; 117 + let flag = true
113 - if (idCode.value.length === 15) { // 15位身份证号码不校验 118 + if (idCode.value.length === 15) {
114 - flag = true; 119 + // 15位身份证号码不校验
120 + flag = true
115 } else { 121 } else {
116 if (!validateCIN(idCode.value)) { 122 if (!validateCIN(idCode.value)) {
117 - Taro.showToast({ title: '请检查身份证号码', icon: 'none' }); 123 + Taro.showToast({ title: '请检查身份证号码', icon: 'none' })
118 - flag = false; 124 + flag = false
119 } 125 }
120 } 126 }
121 - return flag; 127 + return flag
122 } 128 }
123 129
124 const searchBtn = async () => { 130 const searchBtn = async () => {
125 // 查询用户信息 131 // 查询用户信息
126 if (checkIdCode() && idCode.value) { 132 if (checkIdCode() && idCode.value) {
127 - is_search.value = true; 133 + is_search.value = true
128 - id_number.value = idCode.value; 134 + id_number.value = idCode.value
129 idCode.value = '' 135 idCode.value = ''
130 } 136 }
131 } 137 }
132 const goBack = () => { 138 const goBack = () => {
133 - is_search.value = false; 139 + is_search.value = false
134 } 140 }
135 const goToHome = () => { 141 const goToHome = () => {
136 go('/index') 142 go('/index')
...@@ -149,7 +155,7 @@ const goToHome = () => { ...@@ -149,7 +155,7 @@ const goToHome = () => {
149 background-size: cover; 155 background-size: cover;
150 156
151 .input-card { 157 .input-card {
152 - background-color: #FFF; 158 + background-color: #fff;
153 border-radius: 16rpx; 159 border-radius: 16rpx;
154 border: 2rpx solid rgba(166, 121, 57, 0.45); 160 border: 2rpx solid rgba(166, 121, 57, 0.45);
155 margin-bottom: 32rpx; 161 margin-bottom: 32rpx;
...@@ -185,14 +191,14 @@ const goToHome = () => { ...@@ -185,14 +191,14 @@ const goToHome = () => {
185 191
186 .picker-arrow { 192 .picker-arrow {
187 margin-left: 10rpx; 193 margin-left: 10rpx;
188 - color: #BBB; 194 + color: #bbb;
189 font-size: 28rpx; 195 font-size: 28rpx;
190 } 196 }
191 } 197 }
192 198
193 .tip-block { 199 .tip-block {
194 margin-top: 64rpx; 200 margin-top: 64rpx;
195 - color: #A67939; 201 + color: #a67939;
196 text-align: center; 202 text-align: center;
197 font-size: 30rpx; 203 font-size: 30rpx;
198 204
...@@ -222,8 +228,8 @@ const goToHome = () => { ...@@ -222,8 +228,8 @@ const goToHome = () => {
222 } 228 }
223 229
224 .footer-btn { 230 .footer-btn {
225 - background-color: #A67939; 231 + background-color: #a67939;
226 - color: #FFF; 232 + color: #fff;
227 text-align: center; 233 text-align: center;
228 height: 96rpx; 234 height: 96rpx;
229 display: flex; 235 display: flex;
...@@ -256,14 +262,14 @@ const goToHome = () => { ...@@ -256,14 +262,14 @@ const goToHome = () => {
256 } 262 }
257 263
258 .btn-left { 264 .btn-left {
259 - border: 2rpx solid #A67939; 265 + border: 2rpx solid #a67939;
260 - color: #A67939; 266 + color: #a67939;
261 - background-color: #FFF; 267 + background-color: #fff;
262 } 268 }
263 269
264 .btn-right { 270 .btn-right {
265 - background-color: #A67939; 271 + background-color: #a67939;
266 - color: #FFF; 272 + color: #fff;
267 } 273 }
268 } 274 }
269 275
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
10 <view @tap="goToBooking" class="visit-time"> 10 <view @tap="goToBooking" class="visit-time">
11 <view>参访时间</view> 11 <view>参访时间</view>
12 <view class="flex items-center"> 12 <view class="flex items-center">
13 - <text style="font-size: 30rpx;">{{ date }} {{ time }}</text> 13 + <text style="font-size: 30rpx">{{ date }} {{ time }}</text>
14 <IconFont name="rect-right" class="ml-1" /> 14 <IconFont name="rect-right" class="ml-1" />
15 </view> 15 </view>
16 </view> 16 </view>
...@@ -20,37 +20,53 @@ ...@@ -20,37 +20,53 @@
20 </view> 20 </view>
21 </view> 21 </view>
22 <view v-if="visitorList.length" class="visitors-list"> 22 <view v-if="visitorList.length" class="visitors-list">
23 - <view v-for="(item, index) in visitorList" :key="index" @tap="addVisitor(item)" class="visitor-item"> 23 + <view
24 - <view style="margin-right: 32rpx;"> 24 + v-for="(item, index) in visitorList"
25 - <image v-if="!checked_visitors.includes(item.id)" :src="icon_check1" style="width: 38rpx; height: 38rpx;" /> 25 + :key="index"
26 - <image v-else :src="icon_check2" style="width: 38rpx; height: 38rpx;" /> 26 + @tap="addVisitor(item)"
27 + class="visitor-item"
28 + >
29 + <view style="margin-right: 32rpx">
30 + <image
31 + v-if="!checked_visitors.includes(item.id)"
32 + :src="icon_check1"
33 + style="width: 38rpx; height: 38rpx"
34 + />
35 + <image v-else :src="icon_check2" style="width: 38rpx; height: 38rpx" />
27 </view> 36 </view>
28 <view> 37 <view>
29 - <view style="color: #A67939;">{{ item.name }}</view> 38 + <view style="color: #a67939">{{ item.name }}</view>
30 <view>证件号:{{ formatId(item.id_number) }}</view> 39 <view>证件号:{{ formatId(item.id_number) }}</view>
31 - <view v-if="item.is_reserve === RESERVE_STATUS.ENABLE" style="color: #9C9A9A; font-size: 26rpx;">*已预约过{{ date 40 + <view
32 - }}参观,请不要重复预约</view> 41 + v-if="item.is_reserve === RESERVE_STATUS.ENABLE"
42 + style="color: #9c9a9a; font-size: 26rpx"
43 + >*已预约过{{ date }}参观,请不要重复预约</view
44 + >
33 </view> 45 </view>
34 </view> 46 </view>
35 </view> 47 </view>
36 <view v-else class="no-visitors-list"> 48 <view v-else class="no-visitors-list">
37 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png" 49 + <image
38 - style="width: 320rpx; height: 320rpx;" /> 50 + src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png"
51 + style="width: 320rpx; height: 320rpx"
52 + />
39 <view class="no-visitors-list-title">您还没有添加过参观者</view> 53 <view class="no-visitors-list-title">您还没有添加过参观者</view>
40 </view> 54 </view>
41 - <view style="height: 160rpx;"></view> 55 + <view style="height: 160rpx"></view>
42 <view class="submit-wrapper"> 56 <view class="submit-wrapper">
43 <view class="control-wrapper"> 57 <view class="control-wrapper">
44 <view class="left"> 58 <view class="left">
45 - <view style="margin-left: 32rpx; display: flex;align-items: center;"> 59 + <view style="margin-left: 32rpx; display: flex; align-items: center">
46 - 订单金额&nbsp;&nbsp;<view style="color: #FF1919;display: inline-block;">¥<view 60 + 订单金额&nbsp;&nbsp;<view style="color: #ff1919; display: inline-block"
47 - style="font-size: 48rpx;display: inline-block;">&nbsp;{{ total }}</view> 61 + >¥<view style="font-size: 48rpx; display: inline-block">&nbsp;{{ total }}</view>
48 </view> 62 </view>
49 </view> 63 </view>
50 </view> 64 </view>
51 <view @tap="submitBtn" class="right">提交订单</view> 65 <view @tap="submitBtn" class="right">提交订单</view>
52 </view> 66 </view>
53 - <view style="font-size: 27rpx;margin-left: 32rpx;color: #FF1919; margin-bottom: 32rpx;">提交后请在10分钟内完成支付</view> 67 + <view style="font-size: 27rpx; margin-left: 32rpx; color: #ff1919; margin-bottom: 32rpx"
68 + >提交后请在10分钟内完成支付</view
69 + >
54 </view> 70 </view>
55 </view> 71 </view>
56 </template> 72 </template>
...@@ -66,16 +82,16 @@ import { personListAPI, addReserveAPI } from '@/api/index' ...@@ -66,16 +82,16 @@ import { personListAPI, addReserveAPI } from '@/api/index'
66 import { wechat_pay } from '@/utils/wechatPay' 82 import { wechat_pay } from '@/utils/wechatPay'
67 import { mask_id_number } from '@/utils/tools' 83 import { mask_id_number } from '@/utils/tools'
68 84
69 -const router = useTaroRouter(); 85 +const router = useTaroRouter()
70 -const go = useGo(); 86 +const go = useGo()
71 -const replace = useReplace(); 87 +const replace = useReplace()
72 88
73 -const visitorList = ref([]); 89 +const visitorList = ref([])
74 -const date = ref(''); 90 +const date = ref('')
75 -const time = ref(''); 91 +const time = ref('')
76 -const price = ref(0); 92 +const price = ref(0)
77 -const period_type = ref(''); 93 +const period_type = ref('')
78 -const formatId = (id) => mask_id_number(id) 94 +const formatId = id => mask_id_number(id)
79 95
80 /** 96 /**
81 * @description 当天预约标记 97 * @description 当天预约标记
...@@ -86,8 +102,8 @@ const RESERVE_STATUS = { ...@@ -86,8 +102,8 @@ const RESERVE_STATUS = {
86 ENABLE: '1' 102 ENABLE: '1'
87 } 103 }
88 104
89 -const checked_visitors = ref([]); 105 +const checked_visitors = ref([])
90 -const is_submitting = ref(false); // 是否正在提交订单 106 +const is_submitting = ref(false) // 是否正在提交订单
91 107
92 /** 108 /**
93 * @description 选择/取消选择参观者 109 * @description 选择/取消选择参观者
...@@ -95,20 +111,21 @@ const is_submitting = ref(false); // 是否正在提交订单 ...@@ -95,20 +111,21 @@ const is_submitting = ref(false); // 是否正在提交订单
95 * @param {Object} item 参观者数据 111 * @param {Object} item 参观者数据
96 * @returns {void} 无返回值 112 * @returns {void} 无返回值
97 */ 113 */
98 -const addVisitor = (item) => { 114 +const addVisitor = item => {
99 - if (item.is_reserve === RESERVE_STATUS.ENABLE) { // 今天已经预约 115 + if (item.is_reserve === RESERVE_STATUS.ENABLE) {
116 + // 今天已经预约
100 Taro.showToast({ title: '已预约过参观,请不要重复预约', icon: 'none' }) 117 Taro.showToast({ title: '已预约过参观,请不要重复预约', icon: 'none' })
101 - return; 118 + return
102 } 119 }
103 if (checked_visitors.value.includes(item.id)) { 120 if (checked_visitors.value.includes(item.id)) {
104 - checked_visitors.value = checked_visitors.value.filter((v) => v !== item.id); 121 + checked_visitors.value = checked_visitors.value.filter(v => v !== item.id)
105 } else { 122 } else {
106 - checked_visitors.value.push(item.id); 123 + checked_visitors.value.push(item.id)
107 } 124 }
108 } 125 }
109 126
110 const total = computed(() => { 127 const total = computed(() => {
111 - return price.value * checked_visitors.value.length; 128 + return price.value * checked_visitors.value.length
112 }) 129 })
113 130
114 /** 131 /**
...@@ -116,7 +133,7 @@ const total = computed(() => { ...@@ -116,7 +133,7 @@ const total = computed(() => {
116 * @returns {void} 无返回值 133 * @returns {void} 无返回值
117 */ 134 */
118 const goToBooking = () => { 135 const goToBooking = () => {
119 - go('/booking'); 136 + go('/booking')
120 } 137 }
121 138
122 /** 139 /**
...@@ -124,13 +141,13 @@ const goToBooking = () => { ...@@ -124,13 +141,13 @@ const goToBooking = () => {
124 * @returns {void} 无返回值 141 * @returns {void} 无返回值
125 */ 142 */
126 const goToVisitor = () => { 143 const goToVisitor = () => {
127 - go('/addVisitor'); 144 + go('/addVisitor')
128 } 145 }
129 146
130 // 待支付订单ID 147 // 待支付订单ID
131 -const pending_pay_id = ref(null); 148 +const pending_pay_id = ref(null)
132 // 待支付订单是否需要支付 149 // 待支付订单是否需要支付
133 -const pending_need_pay = ref(null); 150 +const pending_need_pay = ref(null)
134 151
135 /** 152 /**
136 * @description 刷新参观者列表(并同步“当天已预约”标记) 153 * @description 刷新参观者列表(并同步“当天已预约”标记)
...@@ -139,43 +156,47 @@ const pending_need_pay = ref(null); ...@@ -139,43 +156,47 @@ const pending_need_pay = ref(null);
139 * @returns {Promise<void>} 无返回值 156 * @returns {Promise<void>} 无返回值
140 */ 157 */
141 158
142 -const refreshVisitorList = async (options) => { 159 +const refreshVisitorList = async options => {
143 - if (!date.value || !time.value) return; 160 + if (!date.value || !time.value) {
161 + return
162 + }
144 const res = await personListAPI({ 163 const res = await personListAPI({
145 reserve_date: date.value, 164 reserve_date: date.value,
146 begin_time: time.value.split('-')[0], 165 begin_time: time.value.split('-')[0],
147 end_time: time.value.split('-')[1], 166 end_time: time.value.split('-')[1],
148 period_type: period_type.value 167 period_type: period_type.value
149 - }); 168 + })
150 if (res && res.code) { 169 if (res && res.code) {
151 - visitorList.value = res.data || []; 170 + visitorList.value = res.data || []
152 if (options?.reset_checked) { 171 if (options?.reset_checked) {
153 - checked_visitors.value = []; 172 + checked_visitors.value = []
154 } 173 }
155 } 174 }
156 } 175 }
157 176
158 -let is_showing_pay_modal = false; 177 +let is_showing_pay_modal = false
159 178
160 /** 179 /**
161 * @description 支付未完成弹窗(防并发) 180 * @description 支付未完成弹窗(防并发)
162 * @param {string} content 弹窗内容 181 * @param {string} content 弹窗内容
163 * @returns {Promise<boolean>} true=继续支付,false=离开 182 * @returns {Promise<boolean>} true=继续支付,false=离开
164 */ 183 */
165 -const showPayErrorModal = async (content) => { 184 +const showPayErrorModal = async content => {
166 - if (is_showing_pay_modal) return; 185 + if (is_showing_pay_modal) {
167 - is_showing_pay_modal = true; 186 + return
187 + }
188 + is_showing_pay_modal = true
168 try { 189 try {
169 const res = await Taro.showModal({ 190 const res = await Taro.showModal({
170 title: '提示', 191 title: '提示',
171 content: content || '支付失败,请稍后再试', 192 content: content || '支付失败,请稍后再试',
172 showCancel: true, 193 showCancel: true,
173 cancelText: '离开', 194 cancelText: '离开',
174 - confirmText: '继续支付', 195 + confirmText: '继续支付'
175 - }); 196 + })
176 - return !!res?.confirm; 197 + return !!res?.confirm
177 } finally { 198 } finally {
178 - is_showing_pay_modal = false; 199 + is_showing_pay_modal = false
179 } 200 }
180 } 201 }
181 202
...@@ -186,20 +207,23 @@ const showPayErrorModal = async (content) => { ...@@ -186,20 +207,23 @@ const showPayErrorModal = async (content) => {
186 * @returns {Promise<void>} 无返回值 207 * @returns {Promise<void>} 无返回值
187 */ 208 */
188 const submitBtn = async () => { 209 const submitBtn = async () => {
189 - if (is_submitting.value) return; 210 + if (is_submitting.value) {
211 + return
212 + }
190 if (!checked_visitors.value.length) { 213 if (!checked_visitors.value.length) {
191 Taro.showToast({ title: '请先添加参观者', icon: 'none' }) 214 Taro.showToast({ title: '请先添加参观者', icon: 'none' })
192 - return; 215 + return
193 } 216 }
194 217
195 - is_submitting.value = true; 218 + is_submitting.value = true
196 try { 219 try {
197 - let pay_id = pending_pay_id.value; 220 + let pay_id = pending_pay_id.value
198 - let need_pay = pending_need_pay.value; 221 + let need_pay = pending_need_pay.value
199 222
200 - if (!pay_id) { // TAG: 提交订单, 如果没有待支付订单ID, 则创建一个新的订单 223 + if (!pay_id) {
201 - Taro.showLoading({ title: '提交中...' }); 224 + // TAG: 提交订单, 如果没有待支付订单ID, 则创建一个新的订单
202 - let reserve_res = null; 225 + Taro.showLoading({ title: '提交中...' })
226 + let reserve_res = null
203 try { 227 try {
204 reserve_res = await addReserveAPI({ 228 reserve_res = await addReserveAPI({
205 reserve_date: date.value, 229 reserve_date: date.value,
...@@ -207,60 +231,61 @@ const submitBtn = async () => { ...@@ -207,60 +231,61 @@ const submitBtn = async () => {
207 end_time: time.value.split('-')[1], 231 end_time: time.value.split('-')[1],
208 person_id_list: JSON.stringify(checked_visitors.value), 232 person_id_list: JSON.stringify(checked_visitors.value),
209 period_type: period_type.value 233 period_type: period_type.value
210 - }); 234 + })
211 } finally { 235 } finally {
212 - Taro.hideLoading(); 236 + Taro.hideLoading()
213 } 237 }
214 238
215 if (!reserve_res || reserve_res.code != 1) { 239 if (!reserve_res || reserve_res.code != 1) {
216 - return; 240 + return
217 } 241 }
218 - pay_id = reserve_res.data.pay_id; 242 + pay_id = reserve_res.data.pay_id
219 - pending_pay_id.value = pay_id; 243 + pending_pay_id.value = pay_id
220 - need_pay = reserve_res.data?.need_pay; 244 + need_pay = reserve_res.data?.need_pay
221 - pending_need_pay.value = need_pay; 245 + pending_need_pay.value = need_pay
222 - await refreshVisitorList({ reset_checked: true }); 246 + await refreshVisitorList({ reset_checked: true })
223 } 247 }
224 248
225 // 以接口返回的 need_pay 为准:1=需要支付,0=不需要支付 249 // 以接口返回的 need_pay 为准:1=需要支付,0=不需要支付
226 if (Number(need_pay) === 1 || need_pay === true) { 250 if (Number(need_pay) === 1 || need_pay === true) {
227 // 初始化循环 251 // 初始化循环
228 - let should_continue = true; 252 + let should_continue = true
229 // 循环支付直到支付成功或用户取消支付 253 // 循环支付直到支付成功或用户取消支付
230 while (should_continue) { 254 while (should_continue) {
231 const pay_res = await wechat_pay({ pay_id }) 255 const pay_res = await wechat_pay({ pay_id })
232 if (pay_res && pay_res.code == 1) { 256 if (pay_res && pay_res.code == 1) {
233 - pending_pay_id.value = null; 257 + pending_pay_id.value = null
234 - pending_need_pay.value = null; 258 + pending_need_pay.value = null
235 - go('/success', { pay_id }); 259 + go('/success', { pay_id })
236 return 260 return
237 } 261 }
238 // 刷新参观者列表, 清除已预约标记 262 // 刷新参观者列表, 清除已预约标记
239 - refreshVisitorList({ reset_checked: true }).catch(() => {}); 263 + refreshVisitorList({ reset_checked: true }).catch(() => {})
240 - should_continue = await showPayErrorModal(pay_res?.msg || '支付未完成,可再次点击提交订单继续支付') 264 + should_continue = await showPayErrorModal(
265 + pay_res?.msg || '支付未完成,可再次点击提交订单继续支付'
266 + )
241 } 267 }
242 268
243 replace('/bookingList') 269 replace('/bookingList')
244 - return
245 } else { 270 } else {
246 - pending_pay_id.value = null; 271 + pending_pay_id.value = null
247 - pending_need_pay.value = null; 272 + pending_need_pay.value = null
248 - go('/success', { pay_id }); 273 + go('/success', { pay_id })
249 } 274 }
250 } finally { 275 } finally {
251 - is_submitting.value = false; 276 + is_submitting.value = false
252 } 277 }
253 } 278 }
254 279
255 useDidShow(async () => { 280 useDidShow(async () => {
256 - const params = router.params; 281 + const params = router.params
257 - date.value = params.date || ''; 282 + date.value = params.date || ''
258 - time.value = params.time || ''; 283 + time.value = params.time || ''
259 - price.value = params.price || 0; 284 + price.value = params.price || 0
260 - period_type.value = params.period_type || ''; 285 + period_type.value = params.period_type || ''
261 - 286 +
262 - await refreshVisitorList(); 287 + await refreshVisitorList()
263 -}); 288 +})
264 </script> 289 </script>
265 290
266 <style lang="less"> 291 <style lang="less">
...@@ -269,7 +294,7 @@ useDidShow(async () => { ...@@ -269,7 +294,7 @@ useDidShow(async () => {
269 position: relative; 294 position: relative;
270 295
271 .visit-time { 296 .visit-time {
272 - background-color: #FFF; 297 + background-color: #fff;
273 display: flex; 298 display: flex;
274 align-items: center; 299 align-items: center;
275 justify-content: space-between; 300 justify-content: space-between;
...@@ -278,8 +303,8 @@ useDidShow(async () => { ...@@ -278,8 +303,8 @@ useDidShow(async () => {
278 } 303 }
279 304
280 .add-visitors { 305 .add-visitors {
281 - border: 2rpx dashed #A67939; 306 + border: 2rpx dashed #a67939;
282 - color: #A67939; 307 + color: #a67939;
283 border-radius: 10rpx; 308 border-radius: 10rpx;
284 text-align: center; 309 text-align: center;
285 padding: 21rpx 0; 310 padding: 21rpx 0;
...@@ -289,7 +314,7 @@ useDidShow(async () => { ...@@ -289,7 +314,7 @@ useDidShow(async () => {
289 314
290 .visitors-list { 315 .visitors-list {
291 .visitor-item { 316 .visitor-item {
292 - background-color: #FFF; 317 + background-color: #fff;
293 border-radius: 16rpx; 318 border-radius: 16rpx;
294 padding: 32rpx; 319 padding: 32rpx;
295 margin-bottom: 32rpx; 320 margin-bottom: 32rpx;
...@@ -311,7 +336,7 @@ useDidShow(async () => { ...@@ -311,7 +336,7 @@ useDidShow(async () => {
311 } 336 }
312 337
313 .no-visitors-list-title { 338 .no-visitors-list-title {
314 - color: #A67939; 339 + color: #a67939;
315 font-size: 34rpx; 340 font-size: 34rpx;
316 } 341 }
317 } 342 }
...@@ -322,7 +347,7 @@ useDidShow(async () => { ...@@ -322,7 +347,7 @@ useDidShow(async () => {
322 left: 0; 347 left: 0;
323 width: 750rpx; 348 width: 750rpx;
324 display: flex; 349 display: flex;
325 - background-color: #FFF; 350 + background-color: #fff;
326 // padding: 32rpx; 351 // padding: 32rpx;
327 justify-content: space-between; 352 justify-content: space-between;
328 flex-direction: column; 353 flex-direction: column;
...@@ -342,8 +367,8 @@ useDidShow(async () => { ...@@ -342,8 +367,8 @@ useDidShow(async () => {
342 } 367 }
343 368
344 .right { 369 .right {
345 - background-color: #A67939; 370 + background-color: #a67939;
346 - color: #FFF; 371 + color: #fff;
347 margin: 32rpx; 372 margin: 32rpx;
348 padding: 26rpx 96rpx; 373 padding: 26rpx 96rpx;
349 border-radius: 5px; 374 border-radius: 5px;
......
...@@ -13,14 +13,23 @@ ...@@ -13,14 +13,23 @@
13 <view class="text">预约成功</view> 13 <view class="text">预约成功</view>
14 </view> 14 </view>
15 <view class="appointment-information"> 15 <view class="appointment-information">
16 - <view class="number-of-visitors">参观人数:<text>{{ billInfo?.total_qty }} 人</text></view> 16 + <view class="number-of-visitors"
17 - <view class="visit-time">参访时间:<text>{{ billInfo?.datetime }}</text></view> 17 + >参观人数:<text>{{ billInfo?.total_qty }} 人</text></view
18 - <view class="payment-amount">支付金额:<text>¥ {{ billInfo?.total_amt }}</text></view> 18 + >
19 + <view class="visit-time"
20 + >参访时间:<text>{{ billInfo?.datetime }}</text></view
21 + >
22 + <view class="payment-amount"
23 + >支付金额:<text>¥ {{ billInfo?.total_amt }}</text></view
24 + >
19 </view> 25 </view>
20 <view class="appointment-notice"> 26 <view class="appointment-notice">
21 - <view style="margin-bottom: 8rpx; display: flex; align-items: center; justify-content: center;"><IconFont name="tips" />&nbsp;温馨提示</view> 27 + <view
22 - <view style="font-size: 27rpx;">1. 一人一码,或拿身份证,扫码或识别身份证成功后进入</view> 28 + style="margin-bottom: 8rpx; display: flex; align-items: center; justify-content: center"
23 - <view style="font-size: 27rpx;">2. 若您无法按时参观,请提前在预约记录中取消您的预约</view> 29 + ><IconFont name="tips" />&nbsp;温馨提示</view
30 + >
31 + <view style="font-size: 27rpx">1. 一人一码,或拿身份证,扫码或识别身份证成功后进入</view>
32 + <view style="font-size: 27rpx">2. 若您无法按时参观,请提前在预约记录中取消您的预约</view>
24 </view> 33 </view>
25 </view> 34 </view>
26 <view class="success-btn"> 35 <view class="success-btn">
...@@ -36,27 +45,27 @@ import Taro, { useDidShow, useRouter as useTaroRouter } from '@tarojs/taro' ...@@ -36,27 +45,27 @@ import Taro, { useDidShow, useRouter as useTaroRouter } from '@tarojs/taro'
36 import { IconFont } from '@nutui/icons-vue-taro' 45 import { IconFont } from '@nutui/icons-vue-taro'
37 import { useGo } from '@/hooks/useGo' 46 import { useGo } from '@/hooks/useGo'
38 import { billInfoAPI } from '@/api/index' 47 import { billInfoAPI } from '@/api/index'
39 -import { formatDatetime } from '@/utils/tools'; 48 +import { formatDatetime } from '@/utils/tools'
40 import { refresh_offline_booking_cache } from '@/composables/useOfflineBookingCache' 49 import { refresh_offline_booking_cache } from '@/composables/useOfflineBookingCache'
41 50
42 -const router = useTaroRouter(); 51 +const router = useTaroRouter()
43 -const go = useGo(); 52 +const go = useGo()
44 53
45 const goToHome = () => { 54 const goToHome = () => {
46 go('/index') 55 go('/index')
47 } 56 }
48 const goToDetail = () => { 57 const goToDetail = () => {
49 - go('/bookingDetail', { pay_id: router.params.pay_id }); 58 + go('/bookingDetail', { pay_id: router.params.pay_id })
50 } 59 }
51 60
52 -const billInfo = ref({}); 61 +const billInfo = ref({})
53 62
54 useDidShow(async () => { 63 useDidShow(async () => {
55 // 获取订单详情 64 // 获取订单详情
56 - const { code, data } = await billInfoAPI({ pay_id: router.params.pay_id }); 65 + const { code, data } = await billInfoAPI({ pay_id: router.params.pay_id })
57 if (code) { 66 if (code) {
58 - data.datetime = data && formatDatetime(data); 67 + data.datetime = data && formatDatetime(data)
59 - billInfo.value = data; 68 + billInfo.value = data
60 } 69 }
61 // 刷新离线预约缓存 70 // 刷新离线预约缓存
62 refresh_offline_booking_cache({ force: true }) 71 refresh_offline_booking_cache({ force: true })
...@@ -66,7 +75,7 @@ useDidShow(async () => { ...@@ -66,7 +75,7 @@ useDidShow(async () => {
66 <style lang="less"> 75 <style lang="less">
67 .success-page { 76 .success-page {
68 position: relative; 77 position: relative;
69 - background-color: #FFF; 78 + background-color: #fff;
70 min-height: 100vh; 79 min-height: 100vh;
71 80
72 .text-prompts { 81 .text-prompts {
...@@ -79,28 +88,28 @@ useDidShow(async () => { ...@@ -79,28 +88,28 @@ useDidShow(async () => {
79 width: 60vw; 88 width: 60vw;
80 } 89 }
81 .text { 90 .text {
82 - color: #A67939; 91 + color: #a67939;
83 font-size: 40rpx; 92 font-size: 40rpx;
84 margin-top: 32rpx; 93 margin-top: 32rpx;
85 } 94 }
86 } 95 }
87 .appointment-information { 96 .appointment-information {
88 padding: 64rpx 32rpx; 97 padding: 64rpx 32rpx;
89 - border-bottom: 2rpx dashed #A67939; 98 + border-bottom: 2rpx dashed #a67939;
90 line-height: 2; 99 line-height: 2;
91 .number-of-visitors { 100 .number-of-visitors {
92 text { 101 text {
93 - color: #A67939; 102 + color: #a67939;
94 } 103 }
95 } 104 }
96 .visit-time { 105 .visit-time {
97 text { 106 text {
98 - color: #A67939; 107 + color: #a67939;
99 } 108 }
100 } 109 }
101 .payment-amount { 110 .payment-amount {
102 text { 111 text {
103 - color: #A67939; 112 + color: #a67939;
104 } 113 }
105 } 114 }
106 } 115 }
...@@ -126,13 +135,13 @@ useDidShow(async () => { ...@@ -126,13 +135,13 @@ useDidShow(async () => {
126 } 135 }
127 136
128 .btn-left { 137 .btn-left {
129 - border: 2rpx solid #A67939; 138 + border: 2rpx solid #a67939;
130 - color: #A67939; 139 + color: #a67939;
131 } 140 }
132 141
133 .btn-right { 142 .btn-right {
134 - background-color: #A67939; 143 + background-color: #a67939;
135 - color: #FFF; 144 + color: #fff;
136 } 145 }
137 } 146 }
138 } 147 }
......
...@@ -28,27 +28,41 @@ ...@@ -28,27 +28,41 @@
28 <view class="text-sm text-gray-500 mb-4">核销记录信息</view> 28 <view class="text-sm text-gray-500 mb-4">核销记录信息</view>
29 29
30 <template v-if="verify_info && Object.keys(verify_info).length > 0"> 30 <template v-if="verify_info && Object.keys(verify_info).length > 0">
31 - <view class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"> 31 + <view
32 + class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"
33 + >
32 <view class="text-gray-500 text-base">姓名</view> 34 <view class="text-gray-500 text-base">姓名</view>
33 - <view class="text-gray-900 text-lg font-medium">{{ verify_info.person_name || '-' }}</view> 35 + <view class="text-gray-900 text-lg font-medium">{{
36 + verify_info.person_name || '-'
37 + }}</view>
34 </view> 38 </view>
35 39
36 - <view class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"> 40 + <view
41 + class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"
42 + >
37 <view class="text-gray-500 text-base">证件号码</view> 43 <view class="text-gray-500 text-base">证件号码</view>
38 - <view class="text-gray-900 text-lg font-medium">{{ formatIdNumber(verify_info.id_number) }}</view> 44 + <view class="text-gray-900 text-lg font-medium">{{
45 + formatIdNumber(verify_info.id_number)
46 + }}</view>
39 </view> 47 </view>
40 48
41 - <view class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"> 49 + <view
50 + class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"
51 + >
42 <view class="text-gray-500 text-base">状态</view> 52 <view class="text-gray-500 text-base">状态</view>
43 <view class="text-amber-600 text-lg font-medium">{{ verify_info.status || '-' }}</view> 53 <view class="text-amber-600 text-lg font-medium">{{ verify_info.status || '-' }}</view>
44 </view> 54 </view>
45 55
46 - <view class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"> 56 + <view
57 + class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"
58 + >
47 <view class="text-gray-500 text-base">预约开始</view> 59 <view class="text-gray-500 text-base">预约开始</view>
48 <view class="text-gray-900 text-lg font-medium">{{ verify_info.begin_time || '-' }}</view> 60 <view class="text-gray-900 text-lg font-medium">{{ verify_info.begin_time || '-' }}</view>
49 </view> 61 </view>
50 62
51 - <view class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"> 63 + <view
64 + class="flex justify-between items-center py-3 border-b border-gray-50 border-solid last:border-0"
65 + >
52 <view class="text-gray-500 text-base">预约结束</view> 66 <view class="text-gray-500 text-base">预约结束</view>
53 <view class="text-gray-900 text-lg font-medium">{{ verify_info.end_time || '-' }}</view> 67 <view class="text-gray-900 text-lg font-medium">{{ verify_info.end_time || '-' }}</view>
54 </view> 68 </view>
...@@ -94,24 +108,38 @@ const msg = ref('请点击下方按钮进行核销') ...@@ -94,24 +108,38 @@ const msg = ref('请点击下方按钮进行核销')
94 const store = mainStore() 108 const store = mainStore()
95 const replace = useReplace() 109 const replace = useReplace()
96 110
97 -const formatIdNumber = (id) => mask_id_number(id, { keep_start: 6, keep_end: 4 }) 111 +const formatIdNumber = id => mask_id_number(id, { keep_start: 6, keep_end: 4 })
98 112
99 const status_title = computed(() => { 113 const status_title = computed(() => {
100 - if (verify_status.value === 'verifying') return '核销中' 114 + if (verify_status.value === 'verifying') {
101 - if (verify_status.value === 'success') return '核销成功' 115 + return '核销中'
102 - if (verify_status.value === 'fail') return '核销失败' 116 + }
117 + if (verify_status.value === 'success') {
118 + return '核销成功'
119 + }
120 + if (verify_status.value === 'fail') {
121 + return '核销失败'
122 + }
103 return '核销' 123 return '核销'
104 }) 124 })
105 125
106 const status_icon_type = computed(() => { 126 const status_icon_type = computed(() => {
107 - if (verify_status.value === 'verifying') return 'waiting' 127 + if (verify_status.value === 'verifying') {
108 - if (verify_status.value === 'success') return 'success' 128 + return 'waiting'
109 - if (verify_status.value === 'fail') return 'cancel' 129 + }
130 + if (verify_status.value === 'success') {
131 + return 'success'
132 + }
133 + if (verify_status.value === 'fail') {
134 + return 'cancel'
135 + }
110 return 'info' 136 return 'info'
111 }) 137 })
112 138
113 const status_icon_color = computed(() => { 139 const status_icon_color = computed(() => {
114 - if (verify_status.value === 'fail') return '#E24A4A' 140 + if (verify_status.value === 'fail') {
141 + return '#E24A4A'
142 + }
115 return '#A67939' 143 return '#A67939'
116 }) 144 })
117 145
...@@ -126,9 +154,13 @@ const status_icon_color = computed(() => { ...@@ -126,9 +154,13 @@ const status_icon_color = computed(() => {
126 * @return {void} 154 * @return {void}
127 */ 155 */
128 156
129 -const verify_ticket = async (code) => { 157 +const verify_ticket = async code => {
130 - if (!code) return 158 + if (!code) {
131 - if (verify_status.value === 'verifying') return 159 + return
160 + }
161 + if (verify_status.value === 'verifying') {
162 + return
163 + }
132 164
133 verify_code.value = code 165 verify_code.value = code
134 verify_status.value = 'verifying' 166 verify_status.value = 'verifying'
...@@ -164,7 +196,9 @@ useDidShow(async () => { ...@@ -164,7 +196,9 @@ useDidShow(async () => {
164 return 196 return
165 } 197 }
166 198
167 - if (permission_res?.data) store.changeUserInfo(permission_res.data) 199 + if (permission_res?.data) {
200 + store.changeUserInfo(permission_res.data)
201 + }
168 if (permission_res?.data?.can_redeem !== true) { 202 if (permission_res?.data?.can_redeem !== true) {
169 replace('volunteerLogin') 203 replace('volunteerLogin')
170 return 204 return
...@@ -178,11 +212,10 @@ useDidShow(async () => { ...@@ -178,11 +212,10 @@ useDidShow(async () => {
178 212
179 const start_scan_and_verify = () => { 213 const start_scan_and_verify = () => {
180 Taro.scanCode({ 214 Taro.scanCode({
181 - success: (res) => { 215 + success: res => {
182 verify_ticket(res?.result || '') 216 verify_ticket(res?.result || '')
183 }, 217 },
184 - fail: () => { 218 + fail: () => {}
185 - }
186 }) 219 })
187 } 220 }
188 </script> 221 </script>
...@@ -199,9 +232,9 @@ const start_scan_and_verify = () => { ...@@ -199,9 +232,9 @@ const start_scan_and_verify = () => {
199 bottom: 0; 232 bottom: 0;
200 width: 750rpx; 233 width: 750rpx;
201 padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom)); 234 padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
202 - background-color: #FFFFFF; 235 + background-color: #ffffff;
203 box-sizing: border-box; 236 box-sizing: border-box;
204 - box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.08); 237 + box-shadow: 0 -10rpx 8rpx 0 rgba(0, 0, 0, 0.08);
205 } 238 }
206 239
207 .verify-btn { 240 .verify-btn {
......
...@@ -4,7 +4,14 @@ ...@@ -4,7 +4,14 @@
4 <view class="title"> 4 <view class="title">
5 <view class="text">参观者信息</view> 5 <view class="text">参观者信息</view>
6 </view> 6 </view>
7 - <view @tap="() => { go('/pages/addVisitor/index') }" class="add-visitors"> 7 + <view
8 + @tap="
9 + () => {
10 + go('/pages/addVisitor/index')
11 + }
12 + "
13 + class="add-visitors"
14 + >
8 <view class="add-btn flex items-center justify-center"> 15 <view class="add-btn flex items-center justify-center">
9 <IconFont name="plus" class="mr-1" /> 添加参观者 16 <IconFont name="plus" class="mr-1" /> 添加参观者
10 </view> 17 </view>
...@@ -12,20 +19,26 @@ ...@@ -12,20 +19,26 @@
12 <view v-if="visitorList.length" class="visitors-list"> 19 <view v-if="visitorList.length" class="visitors-list">
13 <view v-for="(item, index) in visitorList" :key="index" class="visitor-item"> 20 <view v-for="(item, index) in visitorList" :key="index" class="visitor-item">
14 <view> 21 <view>
15 - <view style="color: #A67939;">{{ item.name }}</view> 22 + <view style="color: #a67939">{{ item.name }}</view>
16 <view>证件号:{{ formatId(item.id_number) }}</view> 23 <view>证件号:{{ formatId(item.id_number) }}</view>
17 </view> 24 </view>
18 - <view @tap="removeItem(item)" style="margin-left: 32rpx;"> 25 + <view @tap="removeItem(item)" style="margin-left: 32rpx">
19 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E5%88%A0%E9%99%A4@2x.png" style="width: 38rpx; height: 38rpx;" /> 26 + <image
27 + src="https://cdn.ipadbiz.cn/xys/booking/%E5%88%A0%E9%99%A4@2x.png"
28 + style="width: 38rpx; height: 38rpx"
29 + />
20 </view> 30 </view>
21 </view> 31 </view>
22 </view> 32 </view>
23 <view v-else class="no-visitors-list"> 33 <view v-else class="no-visitors-list">
24 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png" style="width: 320rpx; height: 320rpx;" /> 34 + <image
35 + src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png"
36 + style="width: 320rpx; height: 320rpx"
37 + />
25 <view class="no-visitors-list-title">您还没有添加过参观者</view> 38 <view class="no-visitors-list-title">您还没有添加过参观者</view>
26 </view> 39 </view>
27 </view> 40 </view>
28 - <view style="height: 256rpx;"></view> 41 + <view style="height: 256rpx"></view>
29 <indexNav 42 <indexNav
30 :icons="nav_icons" 43 :icons="nav_icons"
31 active="me" 44 active="me"
...@@ -49,28 +62,37 @@ import icon_4 from '@/assets/images/二维码icon.png' ...@@ -49,28 +62,37 @@ import icon_4 from '@/assets/images/二维码icon.png'
49 import icon_5 from '@/assets/images/我的02@2x.png' 62 import icon_5 from '@/assets/images/我的02@2x.png'
50 import { mask_id_number } from '@/utils/tools' 63 import { mask_id_number } from '@/utils/tools'
51 64
52 -const go = useGo(); 65 +const go = useGo()
53 66
54 -const toCode = () => { // 跳转到预约码 67 +const toCode = () => {
55 - go('/pages/bookingCode/index'); 68 + // 跳转到预约码
69 + go('/pages/bookingCode/index')
56 } 70 }
57 -const toHome = () => { // 跳转到首页 71 +const toHome = () => {
58 - go('/pages/index/index'); 72 + // 跳转到首页
73 + go('/pages/index/index')
59 } 74 }
60 -const toMy = () => { // 跳转到我的 75 +const toMy = () => {
61 - go('/pages/me/index'); 76 + // 跳转到我的
77 + go('/pages/me/index')
62 } 78 }
63 79
64 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 } 80 const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
65 81
66 -const on_nav_select = (key) => { 82 +const on_nav_select = key => {
67 - if (key === 'home') return toHome() 83 + if (key === 'home') {
68 - if (key === 'code') return toCode() 84 + return toHome()
69 - if (key === 'me') return toMy() 85 + }
86 + if (key === 'code') {
87 + return toCode()
88 + }
89 + if (key === 'me') {
90 + return toMy()
91 + }
70 } 92 }
71 93
72 -const visitorList = ref([]); 94 +const visitorList = ref([])
73 -const formatId = (id) => mask_id_number(id) 95 +const formatId = id => mask_id_number(id)
74 96
75 /** 97 /**
76 * @description 加载参观者列表 98 * @description 加载参观者列表
...@@ -78,13 +100,13 @@ const formatId = (id) => mask_id_number(id) ...@@ -78,13 +100,13 @@ const formatId = (id) => mask_id_number(id)
78 */ 100 */
79 const loadList = async () => { 101 const loadList = async () => {
80 try { 102 try {
81 - const { code, data } = await personListAPI({}); 103 + const { code, data } = await personListAPI({})
82 if (code) { 104 if (code) {
83 - visitorList.value = data || []; 105 + visitorList.value = data || []
84 } 106 }
85 } catch (err) { 107 } catch (err) {
86 - console.error(err); 108 + console.error(err)
87 - Taro.showToast({ title: '加载失败', icon: 'none' }); 109 + Taro.showToast({ title: '加载失败', icon: 'none' })
88 } 110 }
89 } 111 }
90 112
...@@ -93,31 +115,31 @@ const loadList = async () => { ...@@ -93,31 +115,31 @@ const loadList = async () => {
93 * @param {Object} item 参观者对象 115 * @param {Object} item 参观者对象
94 * @returns {Promise<void>} 无返回值 116 * @returns {Promise<void>} 无返回值
95 */ 117 */
96 -const removeItem = async (item) => { 118 +const removeItem = async item => {
97 - const { confirm } = await Taro.showModal({ title: '提示', content: '确定删除该参观者吗?' }); 119 + const { confirm } = await Taro.showModal({ title: '提示', content: '确定删除该参观者吗?' })
98 if (confirm) { 120 if (confirm) {
99 try { 121 try {
100 - const res = await delPersonAPI({ person_id: item.id }); 122 + const res = await delPersonAPI({ person_id: item.id })
101 if (res && res.code) { 123 if (res && res.code) {
102 - Taro.showToast({ title: '删除成功' }); 124 + Taro.showToast({ title: '删除成功' })
103 - loadList(); 125 + loadList()
104 } 126 }
105 } catch (error) { 127 } catch (error) {
106 - console.error(error); 128 + console.error(error)
107 - Taro.showToast({ title: '删除出错', icon: 'none' }); 129 + Taro.showToast({ title: '删除出错', icon: 'none' })
108 } 130 }
109 } 131 }
110 } 132 }
111 133
112 useDidShow(() => { 134 useDidShow(() => {
113 - loadList(); 135 + loadList()
114 }) 136 })
115 </script> 137 </script>
116 138
117 <style lang="less"> 139 <style lang="less">
118 .visitor-list-page { 140 .visitor-list-page {
119 min-height: 100vh; 141 min-height: 100vh;
120 - background-color: #F6F6F6; 142 + background-color: #f6f6f6;
121 padding: 32rpx; 143 padding: 32rpx;
122 144
123 .visitor-content { 145 .visitor-content {
...@@ -126,14 +148,14 @@ useDidShow(() => { ...@@ -126,14 +148,14 @@ useDidShow(() => {
126 font-size: 35rpx; 148 font-size: 35rpx;
127 font-weight: bold; 149 font-weight: bold;
128 margin-bottom: 32rpx; 150 margin-bottom: 32rpx;
129 - border-left: 6rpx solid #A67939; 151 + border-left: 6rpx solid #a67939;
130 padding-left: 16rpx; 152 padding-left: 16rpx;
131 } 153 }
132 } 154 }
133 155
134 .add-visitors { 156 .add-visitors {
135 - border: 2rpx dashed #A67939; 157 + border: 2rpx dashed #a67939;
136 - color: #A67939; 158 + color: #a67939;
137 border-radius: 10rpx; 159 border-radius: 10rpx;
138 text-align: center; 160 text-align: center;
139 padding: 21rpx 0; 161 padding: 21rpx 0;
...@@ -148,7 +170,7 @@ useDidShow(() => { ...@@ -148,7 +170,7 @@ useDidShow(() => {
148 170
149 .visitors-list { 171 .visitors-list {
150 .visitor-item { 172 .visitor-item {
151 - background-color: #FFF; 173 + background-color: #fff;
152 border-radius: 16rpx; 174 border-radius: 16rpx;
153 padding: 32rpx; 175 padding: 32rpx;
154 margin-bottom: 32rpx; 176 margin-bottom: 32rpx;
...@@ -165,7 +187,7 @@ useDidShow(() => { ...@@ -165,7 +187,7 @@ useDidShow(() => {
165 flex-direction: column; 187 flex-direction: column;
166 188
167 .no-visitors-list-title { 189 .no-visitors-list-title {
168 - color: #A67939; 190 + color: #a67939;
169 font-size: 34rpx; 191 font-size: 34rpx;
170 margin-top: 32rpx; 192 margin-top: 32rpx;
171 } 193 }
......
...@@ -17,13 +17,23 @@ ...@@ -17,13 +17,23 @@
17 17
18 <view class="input-group"> 18 <view class="input-group">
19 <text class="label">账号</text> 19 <text class="label">账号</text>
20 - <input v-model="username" placeholder="请输入账号" placeholder-class="input-placeholder" cursorSpacing="40rpx" /> 20 + <input
21 + v-model="username"
22 + placeholder="请输入账号"
23 + placeholder-class="input-placeholder"
24 + cursorSpacing="40rpx"
25 + />
21 </view> 26 </view>
22 27
23 <view class="input-group"> 28 <view class="input-group">
24 <text class="label">密码</text> 29 <text class="label">密码</text>
25 - <input v-model="password" password placeholder="请输入密码" placeholder-class="input-placeholder" 30 + <input
26 - cursorSpacing="40rpx" /> 31 + v-model="password"
32 + password
33 + placeholder="请输入密码"
34 + placeholder-class="input-placeholder"
35 + cursorSpacing="40rpx"
36 + />
27 </view> 37 </view>
28 38
29 <button class="login-btn" @tap="handleLogin">立即登录</button> 39 <button class="login-btn" @tap="handleLogin">立即登录</button>
...@@ -51,10 +61,16 @@ const password = ref('') ...@@ -51,10 +61,16 @@ const password = ref('')
51 const check_permission_and_redirect = async () => { 61 const check_permission_and_redirect = async () => {
52 try { 62 try {
53 const permission_res = await checkRedeemPermissionAPI() 63 const permission_res = await checkRedeemPermissionAPI()
54 - if (permission_res?.code !== 1) return 64 + if (permission_res?.code !== 1) {
55 - if (permission_res?.data) store.changeUserInfo(permission_res.data) 65 + return
56 - if (permission_res?.data?.can_redeem === true) replace('verificationResult') 66 + }
57 - } catch (e) { } 67 + if (permission_res?.data) {
68 + store.changeUserInfo(permission_res.data)
69 + }
70 + if (permission_res?.data?.can_redeem === true) {
71 + replace('verificationResult')
72 + }
73 + } catch (e) {}
58 } 74 }
59 75
60 useDidShow(() => { 76 useDidShow(() => {
...@@ -85,7 +101,9 @@ const handleLogin = async () => { ...@@ -85,7 +101,9 @@ const handleLogin = async () => {
85 return 101 return
86 } 102 }
87 103
88 - if (permission_res?.data) store.changeUserInfo(permission_res.data) 104 + if (permission_res?.data) {
105 + store.changeUserInfo(permission_res.data)
106 + }
89 107
90 if (permission_res?.data?.can_redeem === true) { 108 if (permission_res?.data?.can_redeem === true) {
91 Taro.showToast({ title: permission_res?.msg || login_res?.msg || '登录成功', icon: 'success' }) 109 Taro.showToast({ title: permission_res?.msg || login_res?.msg || '登录成功', icon: 'success' })
...@@ -100,7 +118,7 @@ const handleLogin = async () => { ...@@ -100,7 +118,7 @@ const handleLogin = async () => {
100 <style lang="less"> 118 <style lang="less">
101 .login-page { 119 .login-page {
102 min-height: 100vh; 120 min-height: 100vh;
103 - background-color: #F6F6F6; 121 + background-color: #f6f6f6;
104 display: flex; 122 display: flex;
105 flex-direction: column; 123 flex-direction: column;
106 align-items: center; 124 align-items: center;
...@@ -146,7 +164,7 @@ const handleLogin = async () => { ...@@ -146,7 +164,7 @@ const handleLogin = async () => {
146 } 164 }
147 165
148 .input-group { 166 .input-group {
149 - background-color: #F7F8FA; 167 + background-color: #f7f8fa;
150 border-radius: 12rpx; 168 border-radius: 12rpx;
151 padding: 28rpx 30rpx; 169 padding: 28rpx 30rpx;
152 margin-bottom: 32rpx; 170 margin-bottom: 32rpx;
...@@ -171,13 +189,13 @@ const handleLogin = async () => { ...@@ -171,13 +189,13 @@ const handleLogin = async () => {
171 } 189 }
172 190
173 .input-placeholder { 191 .input-placeholder {
174 - color: #C0C4CC; 192 + color: #c0c4cc;
175 } 193 }
176 } 194 }
177 195
178 .login-btn { 196 .login-btn {
179 margin-top: 80rpx; 197 margin-top: 80rpx;
180 - background: #A67939; 198 + background: #a67939;
181 color: #fff; 199 color: #fff;
182 height: 96rpx; 200 height: 96rpx;
183 line-height: 96rpx; 201 line-height: 96rpx;
......
...@@ -4,9 +4,17 @@ ...@@ -4,9 +4,17 @@
4 <view> 4 <view>
5 <IconFont name="clock" size="80rpx" color="#A67939" /> 5 <IconFont name="clock" size="80rpx" color="#A67939" />
6 </view> 6 </view>
7 - <view style="margin: 32rpx 0;">支付中</view> 7 + <view style="margin: 32rpx 0">支付中</view>
8 <view>{{ current.seconds }} s</view> 8 <view>{{ current.seconds }} s</view>
9 - <view style="margin: 48rpx 0; font-size: 27rpx; color: #A67939; text-align: center; line-height: 2;"> 9 + <view
10 + style="
11 + margin: 48rpx 0;
12 + font-size: 27rpx;
13 + color: #a67939;
14 + text-align: center;
15 + line-height: 2;
16 + "
17 + >
10 温馨提示:{{ pay_msg }}<br /> 18 温馨提示:{{ pay_msg }}<br />
11 </view> 19 </view>
12 </view> 20 </view>
...@@ -56,7 +64,9 @@ const startCountdown = () => { ...@@ -56,7 +64,9 @@ const startCountdown = () => {
56 } 64 }
57 65
58 const checkStatus = async () => { 66 const checkStatus = async () => {
59 - if (!pay_id) return 67 + if (!pay_id) {
68 + return
69 + }
60 try { 70 try {
61 const { code, data } = await billPayStatusAPI({ pay_id }) 71 const { code, data } = await billPayStatusAPI({ pay_id })
62 // TAG:轮询支付回调 72 // TAG:轮询支付回调
...@@ -96,8 +106,12 @@ onMounted(() => { ...@@ -96,8 +106,12 @@ onMounted(() => {
96 }) 106 })
97 107
98 onUnmounted(() => { 108 onUnmounted(() => {
99 - if(timer) clearInterval(timer) 109 + if (timer) {
100 - if(countdownTimer) clearInterval(countdownTimer) 110 + clearInterval(timer)
111 + }
112 + if (countdownTimer) {
113 + clearInterval(countdownTimer)
114 + }
101 }) 115 })
102 116
103 const goBackBtn = () => { 117 const goBackBtn = () => {
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
16 16
17 <view class="offline-entry" @tap="toOfflineCode"> 17 <view class="offline-entry" @tap="toOfflineCode">
18 <view class="circle-btn"> 18 <view class="circle-btn">
19 - <image :src="icon_invite" style="width: 60rpx; height: 60rpx; margin-bottom: 16rpx;" /> 19 + <image :src="icon_invite" style="width: 60rpx; height: 60rpx; margin-bottom: 16rpx" />
20 <text>预约记录</text> 20 <text>预约记录</text>
21 </view> 21 </view>
22 </view> 22 </view>
...@@ -38,12 +38,14 @@ import { weak_network_text, get_weak_network_modal_no_cache_options } from '@/ut ...@@ -38,12 +38,14 @@ import { weak_network_text, get_weak_network_modal_no_cache_options } from '@/ut
38 38
39 import icon_invite from '@/assets/images/二维码@2x2.png' 39 import icon_invite from '@/assets/images/二维码@2x2.png'
40 40
41 -const go = useGo(); 41 +const go = useGo()
42 const weak_network_title = weak_network_text.title 42 const weak_network_title = weak_network_text.title
43 const weak_network_desc = weak_network_text.offline_page_desc 43 const weak_network_desc = weak_network_text.offline_page_desc
44 44
45 onMounted(async () => { 45 onMounted(async () => {
46 - if (has_offline_booking_cache()) return 46 + if (has_offline_booking_cache()) {
47 + return
48 + }
47 try { 49 try {
48 await Taro.showModal(get_weak_network_modal_no_cache_options()) 50 await Taro.showModal(get_weak_network_modal_no_cache_options())
49 } catch (e) { 51 } catch (e) {
...@@ -53,13 +55,13 @@ onMounted(async () => { ...@@ -53,13 +55,13 @@ onMounted(async () => {
53 }) 55 })
54 56
55 const toOfflineCode = () => { 57 const toOfflineCode = () => {
56 - go('/pages/offlineBookingList/index'); 58 + go('/pages/offlineBookingList/index')
57 } 59 }
58 60
59 const retry = () => { 61 const retry = () => {
60 // 尝试重新加载当前页或者是返回上一页重试 62 // 尝试重新加载当前页或者是返回上一页重试
61 // 这里简单做成返回首页 63 // 这里简单做成返回首页
62 - Taro.reLaunch({ url: '/pages/index/index' }); 64 + Taro.reLaunch({ url: '/pages/index/index' })
63 } 65 }
64 </script> 66 </script>
65 67
...@@ -103,7 +105,7 @@ const retry = () => { ...@@ -103,7 +105,7 @@ const retry = () => {
103 width: 240rpx; 105 width: 240rpx;
104 height: 240rpx; 106 height: 240rpx;
105 border-radius: 50%; 107 border-radius: 50%;
106 - background: #FFFFFF; 108 + background: #ffffff;
107 display: flex; 109 display: flex;
108 flex-direction: column; 110 flex-direction: column;
109 align-items: center; 111 align-items: center;
...@@ -111,7 +113,7 @@ const retry = () => { ...@@ -111,7 +113,7 @@ const retry = () => {
111 box-shadow: 0 10rpx 30rpx rgba(166, 121, 57, 0.4); 113 box-shadow: 0 10rpx 30rpx rgba(166, 121, 57, 0.4);
112 114
113 text { 115 text {
114 - color: #A67939; 116 + color: #a67939;
115 font-size: 32rpx; 117 font-size: 32rpx;
116 font-weight: bold; 118 font-weight: bold;
117 letter-spacing: 2rpx; 119 letter-spacing: 2rpx;
...@@ -126,7 +128,7 @@ const retry = () => { ...@@ -126,7 +128,7 @@ const retry = () => {
126 .sub-action { 128 .sub-action {
127 padding: 20rpx; 129 padding: 20rpx;
128 text { 130 text {
129 - color: #A67939; 131 + color: #a67939;
130 font-size: 28rpx; 132 font-size: 28rpx;
131 text-decoration: underline; 133 text-decoration: underline;
132 } 134 }
......
...@@ -16,8 +16,8 @@ export const useCounterStore = defineStore('counter', { ...@@ -16,8 +16,8 @@ export const useCounterStore = defineStore('counter', {
16 */ 16 */
17 increment() { 17 increment() {
18 this.count++ 18 this.count++
19 - }, 19 + }
20 - }, 20 + }
21 }) 21 })
22 22
23 // 也可以用函数式(类似组件 setup)定义 Store,适合更复杂场景: 23 // 也可以用函数式(类似组件 setup)定义 Store,适合更复杂场景:
......
...@@ -24,7 +24,7 @@ export const hostStore = defineStore('host', { ...@@ -24,7 +24,7 @@ export const hostStore = defineStore('host', {
24 * @param {string} id 主办方 id 24 * @param {string} id 主办方 id
25 * @returns {void} 无返回值 25 * @returns {void} 无返回值
26 */ 26 */
27 - add (id) { 27 + add(id) {
28 this.id = id 28 this.id = id
29 }, 29 },
30 /** 30 /**
...@@ -32,8 +32,8 @@ export const hostStore = defineStore('host', { ...@@ -32,8 +32,8 @@ export const hostStore = defineStore('host', {
32 * @param {string} id join_id 32 * @param {string} id join_id
33 * @returns {void} 无返回值 33 * @returns {void} 无返回值
34 */ 34 */
35 - addJoin (id) { 35 + addJoin(id) {
36 this.join_id = id 36 this.join_id = id
37 - }, 37 + }
38 - }, 38 + }
39 }) 39 })
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 * @FilePath: /xyxBooking-weapp/src/stores/main.js 5 * @FilePath: /xyxBooking-weapp/src/stores/main.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
8 -import { defineStore } from 'pinia'; 8 +import { defineStore } from 'pinia'
9 9
10 /** 10 /**
11 * @description 全局主状态 11 * @description 全局主状态
...@@ -18,17 +18,17 @@ export const mainStore = defineStore('main', { ...@@ -18,17 +18,17 @@ export const mainStore = defineStore('main', {
18 count: 0, 18 count: 0,
19 auth: false, 19 auth: false,
20 // keepPages: ['default'], // 小程序不支持这种 keep-alive 机制 20 // keepPages: ['default'], // 小程序不支持这种 keep-alive 机制
21 - appUserInfo: null, // 用户信息 21 + appUserInfo: null // 用户信息
22 - }; 22 + }
23 }, 23 },
24 getters: { 24 getters: {
25 /** 25 /**
26 * @description 是否具备义工核销权限 26 * @description 是否具备义工核销权限
27 * @returns {boolean} true=义工,false=非义工 27 * @returns {boolean} true=义工,false=非义工
28 */ 28 */
29 - isVolunteer: (state) => { 29 + isVolunteer: state => {
30 - return !!(state.appUserInfo && (state.appUserInfo.can_redeem === true)); 30 + return !!(state.appUserInfo && state.appUserInfo.can_redeem === true)
31 - }, 31 + }
32 }, 32 },
33 actions: { 33 actions: {
34 /** 34 /**
...@@ -36,8 +36,8 @@ export const mainStore = defineStore('main', { ...@@ -36,8 +36,8 @@ export const mainStore = defineStore('main', {
36 * @param {boolean} state 是否已授权 36 * @param {boolean} state 是否已授权
37 * @returns {void} 无返回值 37 * @returns {void} 无返回值
38 */ 38 */
39 - changeState (state) { 39 + changeState(state) {
40 - this.auth = state; 40 + this.auth = state
41 }, 41 },
42 // setVolunteerStatus(status) { 42 // setVolunteerStatus(status) {
43 // this.isVolunteer = status; 43 // this.isVolunteer = status;
...@@ -55,8 +55,8 @@ export const mainStore = defineStore('main', { ...@@ -55,8 +55,8 @@ export const mainStore = defineStore('main', {
55 * @param {Object|null} info 用户信息对象 55 * @param {Object|null} info 用户信息对象
56 * @returns {void} 无返回值 56 * @returns {void} 无返回值
57 */ 57 */
58 - changeUserInfo (info) { 58 + changeUserInfo(info) {
59 - this.appUserInfo = info; 59 + this.appUserInfo = info
60 } 60 }
61 - }, 61 + }
62 -}); 62 +})
......
...@@ -15,7 +15,7 @@ import { defineStore } from 'pinia' ...@@ -15,7 +15,7 @@ import { defineStore } from 'pinia'
15 export const routerStore = defineStore('router', { 15 export const routerStore = defineStore('router', {
16 state: () => { 16 state: () => {
17 return { 17 return {
18 - url: '', 18 + url: ''
19 } 19 }
20 }, 20 },
21 actions: { 21 actions: {
...@@ -24,15 +24,15 @@ export const routerStore = defineStore('router', { ...@@ -24,15 +24,15 @@ export const routerStore = defineStore('router', {
24 * @param {string} path 页面路径(可带 query) 24 * @param {string} path 页面路径(可带 query)
25 * @returns {void} 无返回值 25 * @returns {void} 无返回值
26 */ 26 */
27 - add (path) { 27 + add(path) {
28 this.url = path 28 this.url = path
29 }, 29 },
30 /** 30 /**
31 * @description 清空回跳路径 31 * @description 清空回跳路径
32 * @returns {void} 无返回值 32 * @returns {void} 无返回值
33 */ 33 */
34 - remove () { 34 + remove() {
35 this.url = '' 35 this.url = ''
36 - }, 36 + }
37 - }, 37 + }
38 }) 38 })
......
...@@ -28,7 +28,9 @@ let navigating_to_auth = false ...@@ -28,7 +28,9 @@ let navigating_to_auth = false
28 */ 28 */
29 export const getCurrentPageFullPath = () => { 29 export const getCurrentPageFullPath = () => {
30 const pages = Taro.getCurrentPages() 30 const pages = Taro.getCurrentPages()
31 - if (!pages || pages.length === 0) return '' 31 + if (!pages || pages.length === 0) {
32 + return ''
33 + }
32 34
33 const current_page = pages[pages.length - 1] 35 const current_page = pages[pages.length - 1]
34 const route = current_page.route 36 const route = current_page.route
...@@ -36,7 +38,7 @@ export const getCurrentPageFullPath = () => { ...@@ -36,7 +38,7 @@ export const getCurrentPageFullPath = () => {
36 38
37 // 改进:key 也需要编码,避免特殊字符导致 URL 解析错误 39 // 改进:key 也需要编码,避免特殊字符导致 URL 解析错误
38 const query_params = Object.keys(options) 40 const query_params = Object.keys(options)
39 - .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(options[key])}`) 41 + .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(options[key])}`)
40 .join('&') 42 .join('&')
41 43
42 return query_params ? `${route}?${query_params}` : route 44 return query_params ? `${route}?${query_params}` : route
...@@ -47,7 +49,7 @@ export const getCurrentPageFullPath = () => { ...@@ -47,7 +49,7 @@ export const getCurrentPageFullPath = () => {
47 * @param {string} custom_path 自定义路径,不传则取当前页完整路径 49 * @param {string} custom_path 自定义路径,不传则取当前页完整路径
48 * @returns {void} 无返回值 50 * @returns {void} 无返回值
49 */ 51 */
50 -export const saveCurrentPagePath = (custom_path) => { 52 +export const saveCurrentPagePath = custom_path => {
51 const router = routerStore() 53 const router = routerStore()
52 const path = custom_path || getCurrentPageFullPath() 54 const path = custom_path || getCurrentPageFullPath()
53 router.add(path) 55 router.add(path)
...@@ -75,12 +77,16 @@ let auth_promise = null ...@@ -75,12 +77,16 @@ let auth_promise = null
75 * @param {object} response Taro.request 响应对象 77 * @param {object} response Taro.request 响应对象
76 * @returns {string|null} cookie 字符串或 null 78 * @returns {string|null} cookie 字符串或 null
77 */ 79 */
78 -const extractCookie = (response) => { 80 +const extractCookie = response => {
79 // 小程序端优先从 response.cookies 取 81 // 小程序端优先从 response.cookies 取
80 - if (response.cookies?.[0]) return response.cookies[0] 82 + if (response.cookies?.[0]) {
83 + return response.cookies[0]
84 + }
81 // H5 端从 header 取(兼容不同大小写) 85 // H5 端从 header 取(兼容不同大小写)
82 const cookie = response.header?.['Set-Cookie'] || response.header?.['set-cookie'] 86 const cookie = response.header?.['Set-Cookie'] || response.header?.['set-cookie']
83 - if (Array.isArray(cookie)) return cookie[0] 87 + if (Array.isArray(cookie)) {
88 + return cookie[0]
89 + }
84 return cookie || null 90 return cookie || null
85 } 91 }
86 92
...@@ -92,18 +98,20 @@ const extractCookie = (response) => { ...@@ -92,18 +98,20 @@ const extractCookie = (response) => {
92 * @param {boolean} options.show_loading 是否展示 loading,默认 true 98 * @param {boolean} options.show_loading 是否展示 loading,默认 true
93 * @returns {Promise<{code:number,msg?:string,data?:any,cookie?:string}>} 授权结果(会把 cookie 写入 storage 的 sessionid) 99 * @returns {Promise<{code:number,msg?:string,data?:any,cookie?:string}>} 授权结果(会把 cookie 写入 storage 的 sessionid)
94 */ 100 */
95 -export const refreshSession = async (options) => { 101 +export const refreshSession = async options => {
96 const show_loading = options?.show_loading !== false 102 const show_loading = options?.show_loading !== false
97 103
98 // 已有授权进行中时,直接复用同一个 Promise 104 // 已有授权进行中时,直接复用同一个 Promise
99 - if (auth_promise) return auth_promise 105 + if (auth_promise) {
106 + return auth_promise
107 + }
100 108
101 auth_promise = (async () => { 109 auth_promise = (async () => {
102 try { 110 try {
103 if (show_loading) { 111 if (show_loading) {
104 Taro.showLoading({ 112 Taro.showLoading({
105 title: '加载中...', 113 title: '加载中...',
106 - mask: true, 114 + mask: true
107 }) 115 })
108 } 116 }
109 117
...@@ -111,7 +119,7 @@ export const refreshSession = async (options) => { ...@@ -111,7 +119,7 @@ export const refreshSession = async (options) => {
111 const login_result = await new Promise((resolve, reject) => { 119 const login_result = await new Promise((resolve, reject) => {
112 Taro.login({ 120 Taro.login({
113 success: resolve, 121 success: resolve,
114 - fail: reject, 122 + fail: reject
115 }) 123 })
116 }) 124 })
117 125
...@@ -120,14 +128,14 @@ export const refreshSession = async (options) => { ...@@ -120,14 +128,14 @@ export const refreshSession = async (options) => {
120 } 128 }
121 129
122 const request_data = { 130 const request_data = {
123 - code: login_result.code, 131 + code: login_result.code
124 } 132 }
125 133
126 // 换取后端会话(服务端通过 Set-Cookie 返回会话信息) 134 // 换取后端会话(服务端通过 Set-Cookie 返回会话信息)
127 const response = await Taro.request({ 135 const response = await Taro.request({
128 url: buildApiUrl('openid_wxapp'), 136 url: buildApiUrl('openid_wxapp'),
129 method: 'POST', 137 method: 'POST',
130 - data: request_data, 138 + data: request_data
131 }) 139 })
132 140
133 if (!response?.data || response.data.code !== 1) { 141 if (!response?.data || response.data.code !== 1) {
...@@ -150,7 +158,7 @@ export const refreshSession = async (options) => { ...@@ -150,7 +158,7 @@ export const refreshSession = async (options) => {
150 158
151 return { 159 return {
152 ...response.data, 160 ...response.data,
153 - cookie, 161 + cookie
154 } 162 }
155 } finally { 163 } finally {
156 if (show_loading) { 164 if (show_loading) {
...@@ -171,7 +179,7 @@ export const refreshSession = async (options) => { ...@@ -171,7 +179,7 @@ export const refreshSession = async (options) => {
171 * 179 *
172 * 改进:使用下划线前缀表示私有函数,仅供 silentAuth 内部使用 180 * 改进:使用下划线前缀表示私有函数,仅供 silentAuth 内部使用
173 */ 181 */
174 -const _do_silent_auth = async (show_loading) => { 182 +const _do_silent_auth = async show_loading => {
175 // 已有 sessionid 时直接视为已授权 183 // 已有 sessionid 时直接视为已授权
176 if (hasAuth()) { 184 if (hasAuth()) {
177 return { code: 1, msg: '已授权' } 185 return { code: 1, msg: '已授权' }
...@@ -206,13 +214,14 @@ export const silentAuth = async (on_success, on_error, options) => { ...@@ -206,13 +214,14 @@ export const silentAuth = async (on_success, on_error, options) => {
206 * 后续再调用 silentAuth() 会复用这个失败的 Promise,导致永远失败、且永远不会重新发起授权。 214 * 后续再调用 silentAuth() 会复用这个失败的 Promise,导致永远失败、且永远不会重新发起授权。
207 * 用 finally :保证成功/失败都会清空,下一次调用才有机会重新走授权流程。 215 * 用 finally :保证成功/失败都会清空,下一次调用才有机会重新走授权流程。
208 */ 216 */
209 - auth_promise = _do_silent_auth(show_loading) 217 + auth_promise = _do_silent_auth(show_loading).finally(() => {
210 - .finally(() => {
211 auth_promise = null 218 auth_promise = null
212 }) 219 })
213 } 220 }
214 const result = await auth_promise 221 const result = await auth_promise
215 - if (on_success) on_success(result) 222 + if (on_success) {
223 + on_success(result)
224 + }
216 225
217 /** 226 /**
218 * 当前返回值 没有实际消费点 :全项目只在 3 处调用,全部都 不使用返回值 。 227 * 当前返回值 没有实际消费点 :全项目只在 3 处调用,全部都 不使用返回值 。
...@@ -230,7 +239,9 @@ export const silentAuth = async (on_success, on_error, options) => { ...@@ -230,7 +239,9 @@ export const silentAuth = async (on_success, on_error, options) => {
230 message: error?.message || '授权失败,请稍后重试', 239 message: error?.message || '授权失败,请稍后重试',
231 original: error 240 original: error
232 } 241 }
233 - if (on_error) on_error(error_obj) 242 + if (on_error) {
243 + on_error(error_obj)
244 + }
234 throw error 245 throw error
235 } 246 }
236 } 247 }
...@@ -253,7 +264,7 @@ const NAVIGATING_RESET_DELAY_MS = 300 ...@@ -253,7 +264,7 @@ const NAVIGATING_RESET_DELAY_MS = 300
253 * @param {string} return_path 指定回跳路径(可选) 264 * @param {string} return_path 指定回跳路径(可选)
254 * @returns {Promise<void>} 无返回值 265 * @returns {Promise<void>} 无返回值
255 */ 266 */
256 -export const navigateToAuth = async (return_path) => { 267 +export const navigateToAuth = async return_path => {
257 const pages = Taro.getCurrentPages() 268 const pages = Taro.getCurrentPages()
258 const current_page = pages[pages.length - 1] 269 const current_page = pages[pages.length - 1]
259 const current_route = current_page?.route 270 const current_route = current_page?.route
...@@ -262,8 +273,12 @@ export const navigateToAuth = async (return_path) => { ...@@ -262,8 +273,12 @@ export const navigateToAuth = async (return_path) => {
262 } 273 }
263 274
264 const now = Date.now() 275 const now = Date.now()
265 - if (navigating_to_auth) return 276 + if (navigating_to_auth) {
266 - if (now - last_navigate_auth_at < NAVIGATE_AUTH_COOLDOWN_MS) return 277 + return
278 + }
279 + if (now - last_navigate_auth_at < NAVIGATE_AUTH_COOLDOWN_MS) {
280 + return
281 + }
267 282
268 last_navigate_auth_at = now 283 last_navigate_auth_at = now
269 navigating_to_auth = true 284 navigating_to_auth = true
...@@ -339,7 +354,7 @@ export const returnToOriginalPage = async (default_path = '/pages/index/index') ...@@ -339,7 +354,7 @@ export const returnToOriginalPage = async (default_path = '/pages/index/index')
339 * @param {object} options 页面 options 354 * @param {object} options 页面 options
340 * @returns {boolean} true=来自分享场景,false=非分享场景 355 * @returns {boolean} true=来自分享场景,false=非分享场景
341 */ 356 */
342 -export const isFromShare = (options) => { 357 +export const isFromShare = options => {
343 return options && (options.from_share === '1' || options.scene) 358 return options && (options.from_share === '1' || options.scene)
344 } 359 }
345 360
...@@ -353,7 +368,9 @@ export const isFromShare = (options) => { ...@@ -353,7 +368,9 @@ export const isFromShare = (options) => {
353 */ 368 */
354 export const handleSharePageAuth = async (options, callback) => { 369 export const handleSharePageAuth = async (options, callback) => {
355 if (hasAuth()) { 370 if (hasAuth()) {
356 - if (typeof callback === 'function') callback() 371 + if (typeof callback === 'function') {
372 + callback()
373 + }
357 return true 374 return true
358 } 375 }
359 376
...@@ -364,7 +381,9 @@ export const handleSharePageAuth = async (options, callback) => { ...@@ -364,7 +381,9 @@ export const handleSharePageAuth = async (options, callback) => {
364 try { 381 try {
365 await silentAuth( 382 await silentAuth(
366 () => { 383 () => {
367 - if (typeof callback === 'function') callback() 384 + if (typeof callback === 'function') {
385 + callback()
386 + }
368 }, 387 },
369 () => { 388 () => {
370 navigateToAuth() 389 navigateToAuth()
...@@ -382,7 +401,7 @@ export const handleSharePageAuth = async (options, callback) => { ...@@ -382,7 +401,7 @@ export const handleSharePageAuth = async (options, callback) => {
382 * @param {string} path 原路径 401 * @param {string} path 原路径
383 * @returns {string} 追加后的路径 402 * @returns {string} 追加后的路径
384 */ 403 */
385 -export const addShareFlag = (path) => { 404 +export const addShareFlag = path => {
386 const separator = path.includes('?') ? '&' : '?' 405 const separator = path.includes('?') ? '&' : '?'
387 return `${path}${separator}from_share=1` 406 return `${path}${separator}from_share=1`
388 } 407 }
......
...@@ -14,13 +14,14 @@ ...@@ -14,13 +14,14 @@
14 * - 线上/测试环境按需切换 14 * - 线上/测试环境按需切换
15 * @type {string} 15 * @type {string}
16 */ 16 */
17 -const BASE_URL = process.env.NODE_ENV === 'production' 17 +const BASE_URL =
18 - // ? 'https://oa.onwall.cn' 18 + process.env.NODE_ENV === 'production'
19 - ? 'https://oa-dev.onwall.cn' 19 + ? // ? 'https://oa.onwall.cn'
20 - // ?'https://oa.jcedu.org' 20 + 'https://oa-dev.onwall.cn'
21 - : 'https://oa-dev.onwall.cn' 21 + : // ?'https://oa.jcedu.org'
22 - // : 'https://oa.jcedu.org' 22 + 'https://oa-dev.onwall.cn'
23 -; 23 +// : 'https://oa.jcedu.org'
24 +
24 /** 25 /**
25 * 接口默认公共参数(避免在多个文件里硬编码) 26 * 接口默认公共参数(避免在多个文件里硬编码)
26 * - f:业务模块标识 27 * - f:业务模块标识
...@@ -28,7 +29,7 @@ const BASE_URL = process.env.NODE_ENV === 'production' ...@@ -28,7 +29,7 @@ const BASE_URL = process.env.NODE_ENV === 'production'
28 */ 29 */
29 export const REQUEST_DEFAULT_PARAMS = { 30 export const REQUEST_DEFAULT_PARAMS = {
30 f: 'reserve', 31 f: 'reserve',
31 - client_name: '智慧西园寺', 32 + client_name: '智慧西园寺'
32 } 33 }
33 34
34 export default BASE_URL 35 export default BASE_URL
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 * @FilePath: /xyxBooking-weapp/src/utils/mixin.js 5 * @FilePath: /xyxBooking-weapp/src/utils/mixin.js
6 * @Description: 全局 mixin(兼容保留) 6 * @Description: 全局 mixin(兼容保留)
7 */ 7 */
8 -import { getSessionId, setSessionId, clearSessionId } from './request'; 8 +import { getSessionId, setSessionId, clearSessionId } from './request'
9 9
10 /** 10 /**
11 * @description 全局 mixin(兼容保留) 11 * @description 全局 mixin(兼容保留)
...@@ -16,12 +16,12 @@ import { getSessionId, setSessionId, clearSessionId } from './request'; ...@@ -16,12 +16,12 @@ import { getSessionId, setSessionId, clearSessionId } from './request';
16 export default { 16 export default {
17 // 初始化入口(如需全局混入逻辑可写在这里) 17 // 初始化入口(如需全局混入逻辑可写在这里)
18 init: { 18 init: {
19 - created () { 19 + created() {
20 // 说明:sessionid 现在由 request.js 的拦截器自动管理 20 // 说明:sessionid 现在由 request.js 的拦截器自动管理
21 // 如需在组件创建时做通用初始化,可在此补充 21 // 如需在组件创建时做通用初始化,可在此补充
22 } 22 }
23 } 23 }
24 -}; 24 +}
25 25
26 /** 26 /**
27 * @description 导出 sessionid 管理工具(供极端场景手动处理) 27 * @description 导出 sessionid 管理工具(供极端场景手动处理)
......
...@@ -12,7 +12,7 @@ import Taro from '@tarojs/taro' ...@@ -12,7 +12,7 @@ import Taro from '@tarojs/taro'
12 * @param {string} network_type - 网络类型 12 * @param {string} network_type - 网络类型
13 * @returns {boolean} 是否可用 13 * @returns {boolean} 是否可用
14 */ 14 */
15 -export const is_usable_network = (network_type) => { 15 +export const is_usable_network = network_type => {
16 return ['wifi', '4g', '5g', '3g'].includes(network_type) 16 return ['wifi', '4g', '5g', '3g'].includes(network_type)
17 } 17 }
18 18
...@@ -25,7 +25,7 @@ export const get_network_type = async () => { ...@@ -25,7 +25,7 @@ export const get_network_type = async () => {
25 const result = await new Promise((resolve, reject) => { 25 const result = await new Promise((resolve, reject) => {
26 Taro.getNetworkType({ 26 Taro.getNetworkType({
27 success: resolve, 27 success: resolve,
28 - fail: reject, 28 + fail: reject
29 }) 29 })
30 }) 30 })
31 return result?.networkType || 'unknown' 31 return result?.networkType || 'unknown'
......
...@@ -20,39 +20,39 @@ if (typeof TextEncoder === 'undefined') { ...@@ -20,39 +20,39 @@ if (typeof TextEncoder === 'undefined') {
20 * @returns {Uint8Array} UTF-8 字节数组 20 * @returns {Uint8Array} UTF-8 字节数组
21 */ 21 */
22 encode(str) { 22 encode(str) {
23 - const len = str.length; 23 + const len = str.length
24 - const res = []; 24 + const res = []
25 for (let i = 0; i < len; i++) { 25 for (let i = 0; i < len; i++) {
26 - let point = str.charCodeAt(i); 26 + let point = str.charCodeAt(i)
27 if (point <= 0x007f) { 27 if (point <= 0x007f) {
28 - res.push(point); 28 + res.push(point)
29 } else if (point <= 0x07ff) { 29 } else if (point <= 0x07ff) {
30 - res.push(0xc0 | (point >>> 6)); 30 + res.push(0xc0 | (point >>> 6))
31 - res.push(0x80 | (0x3f & point)); 31 + res.push(0x80 | (0x3f & point))
32 } else if (point <= 0xffff) { 32 } else if (point <= 0xffff) {
33 - res.push(0xe0 | (point >>> 12)); 33 + res.push(0xe0 | (point >>> 12))
34 - res.push(0x80 | (0x3f & (point >>> 6))); 34 + res.push(0x80 | (0x3f & (point >>> 6)))
35 - res.push(0x80 | (0x3f & point)); 35 + res.push(0x80 | (0x3f & point))
36 } else { 36 } else {
37 - point = 0x10000 + ((point - 0xd800) << 10) + (str.charCodeAt(++i) - 0xdc00); 37 + point = 0x10000 + ((point - 0xd800) << 10) + (str.charCodeAt(++i) - 0xdc00)
38 - res.push(0xf0 | (point >>> 18)); 38 + res.push(0xf0 | (point >>> 18))
39 - res.push(0x80 | (0x3f & (point >>> 12))); 39 + res.push(0x80 | (0x3f & (point >>> 12)))
40 - res.push(0x80 | (0x3f & (point >>> 6))); 40 + res.push(0x80 | (0x3f & (point >>> 6)))
41 - res.push(0x80 | (0x3f & point)); 41 + res.push(0x80 | (0x3f & point))
42 } 42 }
43 } 43 }
44 - return new Uint8Array(res); 44 + return new Uint8Array(res)
45 } 45 }
46 } 46 }
47 47
48 if (typeof globalThis !== 'undefined') { 48 if (typeof globalThis !== 'undefined') {
49 - globalThis.TextEncoder = TextEncoder; 49 + globalThis.TextEncoder = TextEncoder
50 } 50 }
51 if (typeof global !== 'undefined') { 51 if (typeof global !== 'undefined') {
52 - global.TextEncoder = TextEncoder; 52 + global.TextEncoder = TextEncoder
53 } 53 }
54 if (typeof window !== 'undefined') { 54 if (typeof window !== 'undefined') {
55 - window.TextEncoder = TextEncoder; 55 + window.TextEncoder = TextEncoder
56 } 56 }
57 } 57 }
58 58
...@@ -65,30 +65,30 @@ if (typeof TextDecoder === 'undefined') { ...@@ -65,30 +65,30 @@ if (typeof TextDecoder === 'undefined') {
65 * @returns {string} 解码后的字符串 65 * @returns {string} 解码后的字符串
66 */ 66 */
67 decode(view, options) { 67 decode(view, options) {
68 - void options; 68 + void options
69 if (!view) { 69 if (!view) {
70 - return ''; 70 + return ''
71 } 71 }
72 - let string = ''; 72 + let string = ''
73 - const arr = new Uint8Array(view); 73 + const arr = new Uint8Array(view)
74 for (let i = 0; i < arr.length; i++) { 74 for (let i = 0; i < arr.length; i++) {
75 - string += String.fromCharCode(arr[i]); 75 + string += String.fromCharCode(arr[i])
76 } 76 }
77 try { 77 try {
78 // 简单的 UTF-8 解码尝试 78 // 简单的 UTF-8 解码尝试
79 - return decodeURIComponent(escape(string)); 79 + return decodeURIComponent(escape(string))
80 } catch (e) { 80 } catch (e) {
81 - return string; 81 + return string
82 } 82 }
83 } 83 }
84 } 84 }
85 if (typeof globalThis !== 'undefined') { 85 if (typeof globalThis !== 'undefined') {
86 - globalThis.TextDecoder = TextDecoder; 86 + globalThis.TextDecoder = TextDecoder
87 } 87 }
88 if (typeof global !== 'undefined') { 88 if (typeof global !== 'undefined') {
89 - global.TextDecoder = TextDecoder; 89 + global.TextDecoder = TextDecoder
90 } 90 }
91 if (typeof window !== 'undefined') { 91 if (typeof window !== 'undefined') {
92 - window.TextDecoder = TextDecoder; 92 + window.TextDecoder = TextDecoder
93 } 93 }
94 } 94 }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
6 * @Description: 简单axios封装,后续按实际处理 6 * @Description: 简单axios封装,后续按实际处理
7 */ 7 */
8 // import axios from 'axios' 8 // import axios from 'axios'
9 -import axios from 'axios-miniprogram'; 9 +import axios from 'axios-miniprogram'
10 import Taro from '@tarojs/taro' 10 import Taro from '@tarojs/taro'
11 // import qs from 'qs' 11 // import qs from 'qs'
12 // import { strExist } from './tools' 12 // import { strExist } from './tools'
...@@ -18,7 +18,7 @@ import { parseQueryString } from './tools' ...@@ -18,7 +18,7 @@ import { parseQueryString } from './tools'
18 // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress'; 18 // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress';
19 // import store from '@/store' 19 // import store from '@/store'
20 // import { getToken } from '@/utils/auth' 20 // import { getToken } from '@/utils/auth'
21 -import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config'; 21 +import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config'
22 22
23 /** 23 /**
24 * @description 获取 sessionid 的工具函数 24 * @description 获取 sessionid 的工具函数
...@@ -28,12 +28,12 @@ import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config'; ...@@ -28,12 +28,12 @@ import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config';
28 */ 28 */
29 export const getSessionId = () => { 29 export const getSessionId = () => {
30 try { 30 try {
31 - return Taro.getStorageSync("sessionid") || null; 31 + return Taro.getStorageSync('sessionid') || null
32 } catch (error) { 32 } catch (error) {
33 - console.error('获取sessionid失败:', error); 33 + console.error('获取sessionid失败:', error)
34 - return null; 34 + return null
35 } 35 }
36 -}; 36 +}
37 37
38 /** 38 /**
39 * @description 设置 sessionid(一般不需要手动调用) 39 * @description 设置 sessionid(一般不需要手动调用)
...@@ -42,9 +42,11 @@ export const getSessionId = () => { ...@@ -42,9 +42,11 @@ export const getSessionId = () => {
42 * @param {string} sessionid cookie 字符串 42 * @param {string} sessionid cookie 字符串
43 * @returns {void} 无返回值 43 * @returns {void} 无返回值
44 */ 44 */
45 -export const setSessionId = (sessionid) => { 45 +export const setSessionId = sessionid => {
46 try { 46 try {
47 - if (!sessionid) return 47 + if (!sessionid) {
48 + return
49 + }
48 Taro.setStorageSync('sessionid', sessionid) 50 Taro.setStorageSync('sessionid', sessionid)
49 } catch (error) { 51 } catch (error) {
50 console.error('设置sessionid失败:', error) 52 console.error('设置sessionid失败:', error)
...@@ -76,7 +78,7 @@ export const clearSessionId = () => { ...@@ -76,7 +78,7 @@ export const clearSessionId = () => {
76 const service = axios.create({ 78 const service = axios.create({
77 baseURL: BASE_URL, // url = base url + request url 79 baseURL: BASE_URL, // url = base url + request url
78 // withCredentials: true, // send cookies when cross-domain requests 80 // withCredentials: true, // send cookies when cross-domain requests
79 - timeout: 5000, // request timeout 81 + timeout: 5000 // request timeout
80 }) 82 })
81 83
82 // service.defaults.params = { 84 // service.defaults.params = {
...@@ -91,9 +93,11 @@ let has_shown_timeout_modal = false ...@@ -91,9 +93,11 @@ let has_shown_timeout_modal = false
91 * @returns {boolean} true=超时,false=非超时 93 * @returns {boolean} true=超时,false=非超时
92 */ 94 */
93 95
94 -const is_timeout_error = (error) => { 96 +const is_timeout_error = error => {
95 const msg = String(error?.message || error?.errMsg || '') 97 const msg = String(error?.message || error?.errMsg || '')
96 - if (error?.code === 'ECONNABORTED') return true 98 + if (error?.code === 'ECONNABORTED') {
99 + return true
100 + }
97 return msg.toLowerCase().includes('timeout') 101 return msg.toLowerCase().includes('timeout')
98 } 102 }
99 103
...@@ -102,7 +106,7 @@ const is_timeout_error = (error) => { ...@@ -102,7 +106,7 @@ const is_timeout_error = (error) => {
102 * @param {Error} error 请求错误对象 106 * @param {Error} error 请求错误对象
103 * @returns {boolean} true=网络错误,false=非网络错误 107 * @returns {boolean} true=网络错误,false=非网络错误
104 */ 108 */
105 -const is_network_error = (error) => { 109 +const is_network_error = error => {
106 const msg = String(error?.message || error?.errMsg || '') 110 const msg = String(error?.message || error?.errMsg || '')
107 const raw = (() => { 111 const raw = (() => {
108 try { 112 try {
...@@ -111,14 +115,28 @@ const is_network_error = (error) => { ...@@ -111,14 +115,28 @@ const is_network_error = (error) => {
111 return '' 115 return ''
112 } 116 }
113 })() 117 })()
114 - const lower = (msg + ' ' + raw).toLowerCase() 118 + const lower = `${msg} ${raw}`.toLowerCase()
115 - if (lower.includes('request:fail')) return true 119 + if (lower.includes('request:fail')) {
116 - if (lower.includes('request fail')) return true 120 + return true
117 - if (lower.includes('network error')) return true 121 + }
118 - if (lower.includes('failed to fetch')) return true 122 + if (lower.includes('request fail')) {
119 - if (lower.includes('the internet connection appears to be offline')) return true 123 + return true
120 - if (lower.includes('err_blocked_by_client')) return true 124 + }
121 - if (lower.includes('blocked_by_client')) return true 125 + if (lower.includes('network error')) {
126 + return true
127 + }
128 + if (lower.includes('failed to fetch')) {
129 + return true
130 + }
131 + if (lower.includes('the internet connection appears to be offline')) {
132 + return true
133 + }
134 + if (lower.includes('err_blocked_by_client')) {
135 + return true
136 + }
137 + if (lower.includes('blocked_by_client')) {
138 + return true
139 + }
122 return false 140 return false
123 } 141 }
124 142
...@@ -129,8 +147,10 @@ const is_network_error = (error) => { ...@@ -129,8 +147,10 @@ const is_network_error = (error) => {
129 * @param {Error} error 请求错误对象 147 * @param {Error} error 请求错误对象
130 * @returns {Promise<boolean>} true=需要降级,false=不需要 148 * @returns {Promise<boolean>} true=需要降级,false=不需要
131 */ 149 */
132 -const should_handle_bad_network = async (error) => { 150 +const should_handle_bad_network = async error => {
133 - if (is_timeout_error(error)) return true 151 + if (is_timeout_error(error)) {
152 + return true
153 + }
134 return is_network_error(error) 154 return is_network_error(error)
135 } 155 }
136 156
...@@ -141,13 +161,17 @@ const should_handle_bad_network = async (error) => { ...@@ -141,13 +161,17 @@ const should_handle_bad_network = async (error) => {
141 * @returns {Promise<void>} 无返回值 161 * @returns {Promise<void>} 无返回值
142 */ 162 */
143 const handle_request_timeout = async () => { 163 const handle_request_timeout = async () => {
144 - if (has_shown_timeout_modal) return 164 + if (has_shown_timeout_modal) {
165 + return
166 + }
145 has_shown_timeout_modal = true 167 has_shown_timeout_modal = true
146 168
147 const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : [] 169 const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : []
148 const current_page = pages && pages.length ? pages[pages.length - 1] : null 170 const current_page = pages && pages.length ? pages[pages.length - 1] : null
149 const current_route = current_page?.route || '' 171 const current_route = current_page?.route || ''
150 - if (String(current_route).includes('pages/offlineBookingList/index')) return 172 + if (String(current_route).includes('pages/offlineBookingList/index')) {
173 + return
174 + }
151 175
152 // 若有离线预约记录缓存,则跳转至离线预约列表页 176 // 若有离线预约记录缓存,则跳转至离线预约列表页
153 if (has_offline_booking_cache()) { 177 if (has_offline_booking_cache()) {
...@@ -193,15 +217,15 @@ service.interceptors.request.use( ...@@ -193,15 +217,15 @@ service.interceptors.request.use(
193 * - 确保每个请求都带上最新的 sessionid 217 * - 确保每个请求都带上最新的 sessionid
194 * - 注意:axios-miniprogram 的 headers 可能不存在,需要先兜底 218 * - 注意:axios-miniprogram 的 headers 可能不存在,需要先兜底
195 */ 219 */
196 - const sessionid = getSessionId(); 220 + const sessionid = getSessionId()
197 if (sessionid) { 221 if (sessionid) {
198 config.headers = config.headers || {} 222 config.headers = config.headers || {}
199 - config.headers.cookie = sessionid; 223 + config.headers.cookie = sessionid
200 } 224 }
201 225
202 // 增加时间戳 226 // 增加时间戳
203 if (config.method === 'get') { 227 if (config.method === 'get') {
204 - config.params = { ...config.params, timestamp: (new Date()).valueOf() } 228 + config.params = { ...config.params, timestamp: new Date().valueOf() }
205 } 229 }
206 230
207 // if ((config.method || '').toLowerCase() === 'post') { 231 // if ((config.method || '').toLowerCase() === 'post') {
...@@ -253,8 +277,8 @@ service.interceptors.response.use( ...@@ -253,8 +277,8 @@ service.interceptors.response.use(
253 * 记录来源页:用于授权成功后回跳 277 * 记录来源页:用于授权成功后回跳
254 * - 避免死循环:如果已经在 auth 页则不重复记录/跳转 278 * - 避免死循环:如果已经在 auth 页则不重复记录/跳转
255 */ 279 */
256 - const pages = Taro.getCurrentPages(); 280 + const pages = Taro.getCurrentPages()
257 - const currentPage = pages[pages.length - 1]; 281 + const currentPage = pages[pages.length - 1]
258 if (currentPage && currentPage.route !== 'pages/auth/index') { 282 if (currentPage && currentPage.route !== 'pages/auth/index') {
259 saveCurrentPagePath() 283 saveCurrentPagePath()
260 } 284 }
...@@ -266,8 +290,8 @@ service.interceptors.response.use( ...@@ -266,8 +290,8 @@ service.interceptors.response.use(
266 return await service(retry_config) 290 return await service(retry_config)
267 } catch (error) { 291 } catch (error) {
268 // 静默续期失败:降级跳转到授权页(由授权页完成授权并回跳) 292 // 静默续期失败:降级跳转到授权页(由授权页完成授权并回跳)
269 - const pages_retry = Taro.getCurrentPages(); 293 + const pages_retry = Taro.getCurrentPages()
270 - const current_page_retry = pages_retry[pages_retry.length - 1]; 294 + const current_page_retry = pages_retry[pages_retry.length - 1]
271 if (current_page_retry && current_page_retry.route !== 'pages/auth/index') { 295 if (current_page_retry && current_page_retry.route !== 'pages/auth/index') {
272 navigateToAuth() 296 navigateToAuth()
273 } 297 }
...@@ -276,7 +300,7 @@ service.interceptors.response.use( ...@@ -276,7 +300,7 @@ service.interceptors.response.use(
276 } 300 }
277 301
278 if (['预约ID不存在'].includes(res.msg)) { 302 if (['预约ID不存在'].includes(res.msg)) {
279 - res.show = false; 303 + res.show = false
280 } 304 }
281 305
282 return response 306 return response
......
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
6 * @description 主办方默认用户类型 6 * @description 主办方默认用户类型
7 * @type {Array<string>} 7 * @type {Array<string>}
8 */ 8 */
9 -const DEFAULT_HOST_TYPE = ['首次参与', '老用户']; 9 +const DEFAULT_HOST_TYPE = ['首次参与', '老用户']
10 10
11 /** 11 /**
12 * @description 主办方默认用户状态 12 * @description 主办方默认用户状态
13 * @type {Array<string>} 13 * @type {Array<string>}
14 */ 14 */
15 -const DEFAULT_HOST_STATUS = ['跟踪', '引导']; 15 +const DEFAULT_HOST_STATUS = ['跟踪', '引导']
16 16
17 export { DEFAULT_HOST_TYPE, DEFAULT_HOST_STATUS } 17 export { DEFAULT_HOST_TYPE, DEFAULT_HOST_STATUS }
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
5 * @FilePath: /git/xyxBooking-weapp/src/utils/tools.js 5 * @FilePath: /git/xyxBooking-weapp/src/utils/tools.js
6 * @Description: 工具函数库 6 * @Description: 工具函数库
7 */ 7 */
8 -import dayjs from 'dayjs'; 8 +import dayjs from 'dayjs'
9 -import Taro from '@tarojs/taro'; 9 +import Taro from '@tarojs/taro'
10 import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config' 10 import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config'
11 11
12 /** 12 /**
...@@ -14,25 +14,25 @@ import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config' ...@@ -14,25 +14,25 @@ import BASE_URL, { REQUEST_DEFAULT_PARAMS } from './config'
14 * @param {string|number|Date} date 时间入参 14 * @param {string|number|Date} date 时间入参
15 * @returns {string} 格式化后的时间字符串(YYYY-MM-DD HH:mm) 15 * @returns {string} 格式化后的时间字符串(YYYY-MM-DD HH:mm)
16 */ 16 */
17 -const formatDate = (date) => { 17 +const formatDate = date => {
18 - return dayjs(date).format('YYYY-MM-DD HH:mm'); 18 + return dayjs(date).format('YYYY-MM-DD HH:mm')
19 -}; 19 +}
20 20
21 /** 21 /**
22 * @description 判断设备信息 22 * @description 判断设备信息
23 * @returns {Object} 设备信息对象,包含是否为 Android、iOS、是否为平板等属性 23 * @returns {Object} 设备信息对象,包含是否为 Android、iOS、是否为平板等属性
24 */ 24 */
25 const wxInfo = () => { 25 const wxInfo = () => {
26 - const info = Taro.getSystemInfoSync(); 26 + const info = Taro.getSystemInfoSync()
27 - const isAndroid = info.platform === 'android'; 27 + const isAndroid = info.platform === 'android'
28 - const isiOS = info.platform === 'ios'; 28 + const isiOS = info.platform === 'ios'
29 // 说明:当前项目只用到 Android/iOS 区分;平板能力按需补充 29 // 说明:当前项目只用到 Android/iOS 区分;平板能力按需补充
30 return { 30 return {
31 isAndroid, 31 isAndroid,
32 isiOS, 32 isiOS,
33 isTable: false // 小程序通常不是 tablet 模式,或者可以根据 screenWidth 判断 33 isTable: false // 小程序通常不是 tablet 模式,或者可以根据 screenWidth 判断
34 - }; 34 + }
35 -}; 35 +}
36 36
37 /** 37 /**
38 * @description 解析 URL 参数 38 * @description 解析 URL 参数
...@@ -40,14 +40,16 @@ const wxInfo = () => { ...@@ -40,14 +40,16 @@ const wxInfo = () => {
40 * @returns {Object} URL 参数对象(键值对) 40 * @returns {Object} URL 参数对象(键值对)
41 */ 41 */
42 const parseQueryString = url => { 42 const parseQueryString = url => {
43 - if (!url) return {}; 43 + if (!url) {
44 - var json = {}; 44 + return {}
45 - var arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : []; 45 + }
46 + const json = {}
47 + const arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : []
46 arr.forEach(item => { 48 arr.forEach(item => {
47 - var tmp = item.split('='); 49 + const tmp = item.split('=')
48 - json[tmp[0]] = tmp[1]; 50 + json[tmp[0]] = tmp[1]
49 - }); 51 + })
50 - return json; 52 + return json
51 } 53 }
52 54
53 /** 55 /**
...@@ -57,9 +59,13 @@ const parseQueryString = url => { ...@@ -57,9 +59,13 @@ const parseQueryString = url => {
57 * @returns {boolean} true=包含任意一个子串,false=都不包含 59 * @returns {boolean} true=包含任意一个子串,false=都不包含
58 */ 60 */
59 const strExist = (array, str) => { 61 const strExist = (array, str) => {
60 - if (!str) return false; 62 + if (!str) {
63 + return false
64 + }
61 const exist = array.filter(arr => { 65 const exist = array.filter(arr => {
62 - if (str.indexOf(arr) >= 0) return str; 66 + if (str.indexOf(arr) >= 0) {
67 + return str
68 + }
63 }) 69 })
64 return exist.length > 0 70 return exist.length > 0
65 } 71 }
...@@ -90,32 +96,35 @@ const strExist = (array, str) => { ...@@ -90,32 +96,35 @@ const strExist = (array, str) => {
90 * 2. 若 begin_time/end_time 缺失,拼接后可能出现 "undefined-undefined" 等异常,需保证入参完整性; 96 * 2. 若 begin_time/end_time 缺失,拼接后可能出现 "undefined-undefined" 等异常,需保证入参完整性;
91 * 3. 该函数默认截取时间字符串前19位(slice(0, -6)),需根据实际时间格式调整截取长度 97 * 3. 该函数默认截取时间字符串前19位(slice(0, -6)),需根据实际时间格式调整截取长度
92 */ 98 */
93 -const formatDatetime = (data) => { 99 +const formatDatetime = data => {
94 - if (!data || !data.begin_time || !data.end_time) return ''; 100 + if (!data || !data.begin_time || !data.end_time) {
101 + return ''
102 + }
95 103
96 - const normalize = (timeStr) => { 104 + const normalize = timeStr => {
97 - if (!timeStr) return ''; 105 + if (!timeStr) {
98 - let clean = timeStr.split('+')[0]; 106 + return ''
99 - clean = clean.split('Z')[0]; 107 + }
100 - clean = clean.trim().replace(/\s+/, 'T'); 108 + let clean = timeStr.split('+')[0]
101 - return clean; 109 + clean = clean.split('Z')[0]
102 - }; 110 + clean = clean.trim().replace(/\s+/, 'T')
111 + return clean
112 + }
103 113
104 - const start = dayjs(normalize(data.begin_time)); 114 + const start = dayjs(normalize(data.begin_time))
105 - const end = dayjs(normalize(data.end_time)); 115 + const end = dayjs(normalize(data.end_time))
106 116
107 - if (!start.isValid() || !end.isValid()) return ''; 117 + if (!start.isValid() || !end.isValid()) {
118 + return ''
119 + }
108 120
109 const isNextDayMidnight = 121 const isNextDayMidnight =
110 - end.diff(start, 'day') === 1 && 122 + end.diff(start, 'day') === 1 && end.hour() === 0 && end.minute() === 0 && end.second() === 0
111 - end.hour() === 0 &&
112 - end.minute() === 0 &&
113 - end.second() === 0;
114 123
115 - const endTimeText = isNextDayMidnight ? '24:00' : end.format('HH:mm'); 124 + const endTimeText = isNextDayMidnight ? '24:00' : end.format('HH:mm')
116 125
117 - return `${start.format('YYYY-MM-DD')} ${start.format('HH:mm')}-${endTimeText}`; 126 + return `${start.format('YYYY-MM-DD')} ${start.format('HH:mm')}-${endTimeText}`
118 -}; 127 +}
119 128
120 /** 129 /**
121 * @description 证件号脱敏 130 * @description 证件号脱敏
...@@ -128,7 +137,9 @@ const formatDatetime = (data) => { ...@@ -128,7 +137,9 @@ const formatDatetime = (data) => {
128 */ 137 */
129 const mask_id_number = (id_number, options = {}) => { 138 const mask_id_number = (id_number, options = {}) => {
130 const raw = String(id_number || '') 139 const raw = String(id_number || '')
131 - if (!raw) return '' 140 + if (!raw) {
141 + return ''
142 + }
132 143
133 const has_keep_start = Number.isFinite(options.keep_start) 144 const has_keep_start = Number.isFinite(options.keep_start)
134 const has_keep_end = Number.isFinite(options.keep_end) 145 const has_keep_end = Number.isFinite(options.keep_end)
...@@ -137,19 +148,25 @@ const mask_id_number = (id_number, options = {}) => { ...@@ -137,19 +148,25 @@ const mask_id_number = (id_number, options = {}) => {
137 const mask_count = Number.isFinite(options.mask_count) ? options.mask_count : 8 148 const mask_count = Number.isFinite(options.mask_count) ? options.mask_count : 8
138 149
139 if (has_keep_start && has_keep_end) { 150 if (has_keep_start && has_keep_end) {
140 - if (raw.length <= keep_start + keep_end) return raw 151 + if (raw.length <= keep_start + keep_end) {
152 + return raw
153 + }
141 const prefix = raw.slice(0, keep_start) 154 const prefix = raw.slice(0, keep_start)
142 const suffix = raw.slice(raw.length - keep_end) 155 const suffix = raw.slice(raw.length - keep_end)
143 const middle_len = Math.max(1, raw.length - keep_start - keep_end) 156 const middle_len = Math.max(1, raw.length - keep_start - keep_end)
144 return `${prefix}${'*'.repeat(middle_len)}${suffix}` 157 return `${prefix}${'*'.repeat(middle_len)}${suffix}`
145 } 158 }
146 159
147 - if (raw.length < 15) return raw 160 + if (raw.length < 15) {
161 + return raw
162 + }
148 163
149 const safe_mask_count = Math.min(Math.max(1, mask_count), raw.length) 164 const safe_mask_count = Math.min(Math.max(1, mask_count), raw.length)
150 const start = Math.floor((raw.length - safe_mask_count) / 2) 165 const start = Math.floor((raw.length - safe_mask_count) / 2)
151 const end = start + safe_mask_count 166 const end = start + safe_mask_count
152 - if (start < 0 || end > raw.length) return raw 167 + if (start < 0 || end > raw.length) {
168 + return raw
169 + }
153 170
154 return raw.substring(0, start) + '*'.repeat(safe_mask_count) + raw.substring(end) 171 return raw.substring(0, start) + '*'.repeat(safe_mask_count) + raw.substring(end)
155 } 172 }
...@@ -159,12 +176,20 @@ const mask_id_number = (id_number, options = {}) => { ...@@ -159,12 +176,20 @@ const mask_id_number = (id_number, options = {}) => {
159 * @param {string|number} status 状态值 176 * @param {string|number} status 状态值
160 * @returns {string} 状态文案 177 * @returns {string} 状态文案
161 */ 178 */
162 -const get_qrcode_status_text = (status) => { 179 +const get_qrcode_status_text = status => {
163 const key = String(status || '') 180 const key = String(status || '')
164 - if (key === '1') return '未激活' 181 + if (key === '1') {
165 - if (key === '3') return '待使用' 182 + return '未激活'
166 - if (key === '5') return '被取消' 183 + }
167 - if (key === '7') return '已使用' 184 + if (key === '3') {
185 + return '待使用'
186 + }
187 + if (key === '5') {
188 + return '被取消'
189 + }
190 + if (key === '7') {
191 + return '已使用'
192 + }
168 return '未知状态' 193 return '未知状态'
169 } 194 }
170 195
...@@ -173,12 +198,20 @@ const get_qrcode_status_text = (status) => { ...@@ -173,12 +198,20 @@ const get_qrcode_status_text = (status) => {
173 * @param {string|number} status 状态值 198 * @param {string|number} status 状态值
174 * @returns {string} 状态文案 199 * @returns {string} 状态文案
175 */ 200 */
176 -const get_bill_status_text = (status) => { 201 +const get_bill_status_text = status => {
177 const key = String(status || '') 202 const key = String(status || '')
178 - if (key === '3') return '预约成功' 203 + if (key === '3') {
179 - if (key === '5') return '已取消' 204 + return '预约成功'
180 - if (key === '9') return '已使用' 205 + }
181 - if (key === '11') return '退款中' 206 + if (key === '5') {
207 + return '已取消'
208 + }
209 + if (key === '9') {
210 + return '已使用'
211 + }
212 + if (key === '11') {
213 + return '退款中'
214 + }
182 return '未知状态' 215 return '未知状态'
183 } 216 }
184 217
...@@ -193,9 +226,19 @@ const buildApiUrl = (action, params = {}) => { ...@@ -193,9 +226,19 @@ const buildApiUrl = (action, params = {}) => {
193 a: action, 226 a: action,
194 f: REQUEST_DEFAULT_PARAMS.f, 227 f: REQUEST_DEFAULT_PARAMS.f,
195 client_name: REQUEST_DEFAULT_PARAMS.client_name, 228 client_name: REQUEST_DEFAULT_PARAMS.client_name,
196 - ...params, 229 + ...params
197 }) 230 })
198 return `${BASE_URL}/srv/?${queryParams.toString()}` 231 return `${BASE_URL}/srv/?${queryParams.toString()}`
199 } 232 }
200 233
201 -export { formatDate, wxInfo, parseQueryString, strExist, formatDatetime, mask_id_number, get_qrcode_status_text, get_bill_status_text, buildApiUrl }; 234 +export {
235 + formatDate,
236 + wxInfo,
237 + parseQueryString,
238 + strExist,
239 + formatDatetime,
240 + mask_id_number,
241 + get_qrcode_status_text,
242 + get_bill_status_text,
243 + buildApiUrl
244 +}
......
...@@ -14,13 +14,14 @@ export const weak_network_text = { ...@@ -14,13 +14,14 @@ export const weak_network_text = {
14 toast_title: '网络连接不畅', 14 toast_title: '网络连接不畅',
15 banner_desc: '网络开小差啦!请检查网络设置,或更换位置后重新进入小程序~', 15 banner_desc: '网络开小差啦!请检查网络设置,或更换位置后重新进入小程序~',
16 offline_page_desc: '当前网络信号较弱,已自动为您切换至离线模式', 16 offline_page_desc: '当前网络信号较弱,已自动为您切换至离线模式',
17 - modal_no_cache_content: '当前网络信号较弱,暂无法使用小程序,请检查网络设置,或更换位置后重新进入小程序~', 17 + modal_no_cache_content:
18 + '当前网络信号较弱,暂无法使用小程序,请检查网络设置,或更换位置后重新进入小程序~',
18 modal_use_cache_content: '当前网络信号较弱,可使用已缓存的预约记录进入离线模式', 19 modal_use_cache_content: '当前网络信号较弱,可使用已缓存的预约记录进入离线模式',
19 modal_go_offline_records_content: '当前网络信号较弱,是否进入离线预约记录?', 20 modal_go_offline_records_content: '当前网络信号较弱,是否进入离线预约记录?',
20 offline_mode_no_booking_toast: '当前为离线模式,无法预约', 21 offline_mode_no_booking_toast: '当前为离线模式,无法预约',
21 confirm_ok: '知道了', 22 confirm_ok: '知道了',
22 confirm_booking_records: '预约记录', 23 confirm_booking_records: '预约记录',
23 - confirm_offline_records: '离线记录', 24 + confirm_offline_records: '离线记录'
24 } 25 }
25 26
26 /** 27 /**
...@@ -32,7 +33,7 @@ export const get_weak_network_modal_no_cache_options = () => { ...@@ -32,7 +33,7 @@ export const get_weak_network_modal_no_cache_options = () => {
32 title: weak_network_text.title, 33 title: weak_network_text.title,
33 content: weak_network_text.modal_no_cache_content, 34 content: weak_network_text.modal_no_cache_content,
34 confirmText: weak_network_text.confirm_ok, 35 confirmText: weak_network_text.confirm_ok,
35 - showCancel: false, 36 + showCancel: false
36 } 37 }
37 } 38 }
38 39
...@@ -45,7 +46,7 @@ export const get_weak_network_modal_use_cache_options = () => { ...@@ -45,7 +46,7 @@ export const get_weak_network_modal_use_cache_options = () => {
45 title: weak_network_text.title, 46 title: weak_network_text.title,
46 content: weak_network_text.modal_use_cache_content, 47 content: weak_network_text.modal_use_cache_content,
47 confirmText: weak_network_text.confirm_booking_records, 48 confirmText: weak_network_text.confirm_booking_records,
48 - cancelText: weak_network_text.confirm_ok, 49 + cancelText: weak_network_text.confirm_ok
49 } 50 }
50 } 51 }
51 52
...@@ -58,6 +59,6 @@ export const get_weak_network_modal_go_offline_records_options = () => { ...@@ -58,6 +59,6 @@ export const get_weak_network_modal_go_offline_records_options = () => {
58 title: weak_network_text.title, 59 title: weak_network_text.title,
59 content: weak_network_text.modal_go_offline_records_content, 60 content: weak_network_text.modal_go_offline_records_content,
60 confirmText: weak_network_text.confirm_offline_records, 61 confirmText: weak_network_text.confirm_offline_records,
61 - cancelText: weak_network_text.confirm_ok, 62 + cancelText: weak_network_text.confirm_ok
62 } 63 }
63 } 64 }
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
4 */ 4 */
5 const getCurrentPageUrl = () => { 5 const getCurrentPageUrl = () => {
6 // 获取加载的页面栈 6 // 获取加载的页面栈
7 - let pages = getCurrentPages() 7 + const pages = getCurrentPages()
8 // 获取当前页面对象 8 // 获取当前页面对象
9 - let currentPage = pages[pages.length - 1] 9 + const currentPage = pages[pages.length - 1]
10 // 当前页面 route(不含 query) 10 // 当前页面 route(不含 query)
11 - let url = currentPage.route 11 + const url = currentPage.route
12 return url 12 return url
13 } 13 }
14 /** 14 /**
...@@ -17,15 +17,12 @@ const getCurrentPageUrl = () => { ...@@ -17,15 +17,12 @@ const getCurrentPageUrl = () => {
17 */ 17 */
18 const getCurrentPageParam = () => { 18 const getCurrentPageParam = () => {
19 // 获取加载的页面栈 19 // 获取加载的页面栈
20 - let pages = getCurrentPages() 20 + const pages = getCurrentPages()
21 // 获取当前页面对象 21 // 获取当前页面对象
22 - let currentPage = pages[pages.length - 1] 22 + const currentPage = pages[pages.length - 1]
23 // 当前页面 query 参数对象 23 // 当前页面 query 参数对象
24 - let options = currentPage.options 24 + const options = currentPage.options
25 return options 25 return options
26 } 26 }
27 27
28 -export { 28 +export { getCurrentPageUrl, getCurrentPageParam }
29 - getCurrentPageUrl,
30 - getCurrentPageParam
31 -}
......
...@@ -34,15 +34,15 @@ export const wechat_pay = async ({ pay_id }) => { ...@@ -34,15 +34,15 @@ export const wechat_pay = async ({ pay_id }) => {
34 34
35 const pay_params = pay_params_res?.data || {} 35 const pay_params = pay_params_res?.data || {}
36 36
37 - const pay_result = await new Promise((resolve) => { 37 + const pay_result = await new Promise(resolve => {
38 Taro.requestPayment({ 38 Taro.requestPayment({
39 timeStamp: pay_params.timeStamp, 39 timeStamp: pay_params.timeStamp,
40 nonceStr: pay_params.nonceStr, 40 nonceStr: pay_params.nonceStr,
41 package: pay_params.package, 41 package: pay_params.package,
42 signType: pay_params.signType, 42 signType: pay_params.signType,
43 paySign: pay_params.paySign, 43 paySign: pay_params.paySign,
44 - success: (res) => resolve({ ok: true, res }), 44 + success: res => resolve({ ok: true, res }),
45 - fail: (err) => resolve({ ok: false, err }), 45 + fail: err => resolve({ ok: false, err })
46 }) 46 })
47 }) 47 })
48 48
......