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 2239 additions and 967 deletions
1 { 1 {
2 "permissions": { 2 "permissions": {
3 "allow": [ 3 "allow": [
4 - "Skill(glm-plan-usage:usage-query-skill)" 4 + "Skill(glm-plan-usage:usage-query-skill)",
5 + "Bash(pnpm add:*)",
6 + "Bash(chmod:*)",
7 + "Bash(bash:*)",
8 + "Bash(pnpm lint:no-fix:*)",
9 + "Bash(pnpm lint:*)",
10 + "Bash(pnpm list:*)",
11 + "Bash(pnpm format:*)",
12 + "Bash(git add:*)"
5 ] 13 ]
6 } 14 }
7 } 15 }
......
1 -# http://editorconfig.org 1 +# EditorConfig 配置
2 +# https://editorconfig.org
3 +
2 root = true 4 root = true
3 5
6 +# 所有文件
4 [*] 7 [*]
8 +charset = utf-8
5 indent_style = space 9 indent_style = space
6 indent_size = 2 10 indent_size = 2
7 -charset = utf-8 11 +end_of_line = lf
8 -trim_trailing_whitespace = true
9 insert_final_newline = true 12 insert_final_newline = true
13 +trim_trailing_whitespace = true
14 +
15 +# Vue 文件
16 +[*.{vue,js,jsx,ts,tsx}]
17 +indent_style = space
18 +indent_size = 2
19 +
20 +# Less/SCSS 文件
21 +[*.{less,scss,css}]
22 +indent_style = space
23 +indent_size = 2
10 24
25 +# JSON 文件
26 +[*.json]
27 +indent_style = space
28 +indent_size = 2
29 +
30 +# Markdown 文件
11 [*.md] 31 [*.md]
12 trim_trailing_whitespace = false 32 trim_trailing_whitespace = false
33 +indent_style = space
34 +indent_size = 2
35 +
36 +# 配置文件
37 +[*.{yml,yaml}]
38 +indent_style = space
39 +indent_size = 2
40 +
41 +# Shell 脚本
42 +[*.sh]
43 +end_of_line = lf
44 +
45 +# Windows 特定
46 +[*.{bat,cmd}]
47 +end_of_line = crlf
......
1 +module.exports = {
2 + root: true,
3 + env: {
4 + browser: true,
5 + node: true,
6 + es2021: true
7 + },
8 + extends: [
9 + 'eslint:recommended'
10 + // 暂时不使用 '@vue/eslint-config-prettier',手动配置规则避免冲突
11 + ],
12 + plugins: ['vue'],
13 + parser: 'vue-eslint-parser', // 使用 Vue parser
14 + parserOptions: {
15 + parser: 'espree', // JavaScript parser
16 + ecmaVersion: 2021,
17 + sourceType: 'module',
18 + ecmaFeatures: {
19 + jsx: true
20 + }
21 + },
22 + rules: {
23 + // Vue 规则(手动配置)
24 + 'vue/multi-word-component-names': 'off', // 允许单词组件名
25 + 'vue/no-v-html': 'warn', // 警告使用 v-html(XSS 风险)
26 + 'vue/require-default-prop': 'off', // 不强制 prop 默认值
27 + 'vue/require-prop-types': 'off', // 不强制 prop 类型(使用 JSDoc)
28 + 'vue/no-unused-vars': 'warn', // 警告未使用的变量
29 + 'vue/no-unused-components': 'warn', // 警告未使用的组件
30 +
31 + // 通用规则
32 + 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
33 + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
34 + 'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], // 警告未使用的变量
35 + 'prefer-const': 'error', // 优先使用 const
36 + 'no-var': 'error', // 禁止使用 var
37 + 'eqeqeq': ['error', 'always'], // 强制使用 === 和 !==
38 + 'curly': ['error', 'all'], // 强制使用大括号
39 + 'brace-style': ['error', '1tbs'], // 大括号风格
40 + 'quotes': ['error', 'single', { avoidEscape: true }], // 单引号
41 + 'semi': ['error', 'never'], // 不使用分号
42 + 'comma-dangle': ['error', 'never'], // 不允许尾随逗号
43 + 'arrow-parens': ['error', 'as-needed'], // 箭头函数参数括号
44 + 'object-curly-spacing': ['error', 'always'], // 对象大括号空格
45 + 'array-bracket-spacing': ['error', 'never'], // 数组方括号无空格
46 +
47 + // 代码质量
48 + 'no-duplicate-imports': 'error', // 禁止重复导入
49 + 'no-useless-return': 'error', // 禁止无用的 return
50 + 'no-else-return': 'error', // 禁止 else return(提前 return)
51 + 'prefer-template': 'error', // 优先使用模板字符串
52 + 'template-curly-spacing': 'error', // 模板字符串大括号内无空格
53 + 'object-shorthand': ['error', 'always'], // 对象属性简写
54 +
55 + // 放宽一些规则,避免过多警告
56 + 'no-prototype-builtins': 'off', // 允许使用原型方法
57 + 'no-nested-ternary': 'off', // 允许嵌套三元表达式
58 + 'no-param-reassign': 'off', // 允许修改参数
59 + 'consistent-return': 'off' // 不要求一致的 return
60 + },
61 + globals: {
62 + // Taro 全局变量
63 + wx: 'readonly',
64 + getCurrentPages: 'readonly',
65 + getApp: 'readonly',
66 +
67 + // NutUI 全局变量
68 + NutUI: 'readonly'
69 + },
70 + overrides: [
71 + // 测试文件规则
72 + {
73 + files: ['**/__tests__/**/*', '**/*.test.js', '**/*.spec.js'],
74 + env: {
75 + jest: true,
76 + node: true
77 + },
78 + rules: {
79 + 'no-console': 'off'
80 + }
81 + }
82 + ]
83 +}
1 +#!/bin/sh
2 +. "$(dirname "$0")/_/husky.sh"
3 +
4 +# 验证 commit 信息格式(可选)
5 +# commit_regex='^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\(.+\))?: .{1,50}'
6 +#
7 +#if ! grep -qE "$commit_regex" "$1"; then
8 +# echo "❌ Commit 信息格式不正确"
9 +# echo "✅ 正确格式: type(scope): subject"
10 +# echo "📝 类型: feat, fix, docs, style, refactor, test, chore, etc."
11 +# exit 1
12 +#fi
13 +
14 +echo "✅ Commit 信息验证通过"
1 +#!/bin/sh
2 +. "$(dirname "$0")/_/husky.sh"
3 +
4 +echo "🔍 运行代码检查..."
5 +pnpm lint-staged
1 +module.exports = {
2 + // Vue 文件
3 + '*.{vue,js,jsx,ts,tsx}': [
4 + 'eslint --fix',
5 + 'prettier --write'
6 + ],
7 +
8 + // 样式文件
9 + '*.{less,scss,css}': [
10 + 'prettier --write'
11 + ],
12 +
13 + // JSON/配置文件
14 + '*.{json,md,yml,yaml}': [
15 + 'prettier --write'
16 + ]
17 +}
1 +# 忽略构建输出
2 +dist/
3 +build/
4 +
5 +# 忽略依赖
6 +node_modules/
7 +
8 +# 忽略配置文件
9 +.prettierignore
10 +.eslintrc.js
11 +
12 +# 忽略锁文件
13 +package-lock.json
14 +pnpm-lock.yaml
15 +yarn.lock
16 +
17 +# 忽略日志
18 +*.log
19 +logs/
20 +
21 +# 忽略临时文件
22 +*.tmp
23 +.cache/
24 +
25 +# 忽略覆盖率报告
26 +coverage/
27 +
28 +# 忽略 Taro 配置
29 +config/prod.config.js
30 +config/dev.config.js
31 +config/index.js
32 +
33 +# 忽略静态资源
34 +src/assets/fonts/
35 +src/assets/images/
36 +
37 +# 忽略特定文件
38 +miniprogram_npm/
1 +{
2 + "semi": false,
3 + "singleQuote": true,
4 + "quoteProps": "as-needed",
5 + "trailingComma": "none",
6 + "bracketSpacing": true,
7 + "bracketSameLine": false,
8 + "arrowParens": "avoid",
9 + "printWidth": 100,
10 + "tabWidth": 2,
11 + "useTabs": false,
12 + "endOfLine": "lf",
13 + "vueIndentScriptAndStyle": false,
14 + "singleAttributePerLine": false,
15 + "overrides": [
16 + {
17 + "files": "*.vue",
18 + "options": {
19 + "parser": "vue"
20 + }
21 + },
22 + {
23 + "files": "*.less",
24 + "options": {
25 + "parser": "less"
26 + }
27 + }
28 + ]
29 +}
...@@ -23,12 +23,70 @@ ...@@ -23,12 +23,70 @@
23 ## 开发命令 23 ## 开发命令
24 24
25 ```bash 25 ```bash
26 +# 安装依赖
26 pnpm install 27 pnpm install
27 -pnpm dev:weapp 28 +
28 -pnpm build:weapp 29 +# 开发模式
29 -pnpm lint 30 +pnpm dev:weapp # 微信小程序
31 +pnpm dev:h5 # H5 端
32 +
33 +# 构建
34 +pnpm build:weapp # 微信小程序生产包
35 +pnpm build:h5 # H5 端生产包
36 +
37 +# 代码质量
38 +pnpm lint # ESLint 检查并修复
39 +pnpm format # Prettier 格式化
40 +pnpm lint:no-fix # 仅检查不修复
41 +```
42 +
43 +## 代码质量保障
44 +
45 +项目已配置完整的代码质量保障体系:
46 +
47 +### ✅ 已配置工具
48 +
49 +- **ESLint**:代码风格检查和潜在错误检测
50 +- **Prettier**:代码格式化统一
51 +- **EditorConfig**:编辑器配置统一
52 +- **Husky**:Git Hooks 自动化
53 +- **lint-staged**:提交前仅检查本次修改文件
54 +
55 +### 📋 初始配置步骤
56 +
57 +```bash
58 +# 1. 安装代码质量相关依赖
59 +pnpm add -D eslint prettier eslint-plugin-vue husky lint-staged
60 +
61 +# 2. 初始化 Husky(自动设置 Git Hooks)
62 +bash scripts/setup-husky.sh
63 +
64 +# 3. 提交代码时会自动运行检查
65 +git add .
66 +git commit -m "feat: 添加新功能"
30 ``` 67 ```
31 68
69 +### 📚 详细配置文档
70 +
71 +查看 `docs/development-guide.md` 获取完整的配置使用说明。
72 +
73 +### 🎯 Claude Code 开发配置
74 +
75 +项目配置了完善的 Claude Code 全局规则,支持:
76 +- Vue 3 最佳实践
77 +- Taro 开发规范
78 +- 小程序特性适配
79 +- 多端兼容处理
80 +- 代码审查清单
81 +
82 +全局规则位于 `~/.claude/rules/`
83 +- `taro-patterns.md` - Taro 开发规范
84 +- `miniprogram-checklist.md` - 小程序检查清单
85 +- `taro-cross-platform.md` - 多端兼容指南
86 +- `vue-patterns.md` - Vue 3 最佳实践
87 +- `frontend-testing.md` - 前端测试指南
88 +- `code-review.md` - 代码审查清单
89 +
32 ## 项目结构 90 ## 项目结构
33 91
34 ```text 92 ```text
......
1 +# 配置快速参考
2 +
3 +## 🚀 快速开始
4 +
5 +### 1. 安装依赖
6 +
7 +```bash
8 +# 安装项目依赖
9 +pnpm install
10 +
11 +# 安装代码质量工具(首次)
12 +pnpm add -D eslint prettier eslint-plugin-vue husky lint-staged @vue/eslint-config-prettier
13 +
14 +# 初始化 Git Hooks
15 +bash scripts/setup-husky.sh
16 +```
17 +
18 +### 2. 日常开发
19 +
20 +```bash
21 +# 启动开发服务器
22 +pnpm dev:weapp
23 +
24 +# 代码检查与格式化
25 +pnpm lint # ESLint 检查并修复
26 +pnpm format # Prettier 格式化
27 +
28 +# 提交代码(自动检查)
29 +git add .
30 +git commit -m "feat: 添加新功能"
31 +```
32 +
33 +## 📁 配置文件说明
34 +
35 +### 项目配置
36 +
37 +| 文件 | 用途 |
38 +|------|------|
39 +| `.eslintrc.js` | ESLint 规则配置 |
40 +| `.prettierrc` | Prettier 格式化配置 |
41 +| `.editorconfig` | 编辑器统一配置 |
42 +| `.lintstagedrc.js` | Git 暂存文件检查配置 |
43 +| `.husky/pre-commit` | Git 提交前钩子 |
44 +
45 +### 全局配置(`~/.claude/rules/`)
46 +
47 +| 文件 | 用途 |
48 +|------|------|
49 +| `taro-patterns.md` | Taro 开发规范 |
50 +| `miniprogram-checklist.md` | 小程序检查清单 |
51 +| `taro-cross-platform.md` | 多端兼容指南 |
52 +| `vue-patterns.md` | Vue 3 最佳实践 |
53 +| `frontend-testing.md` | 前端测试指南 |
54 +| `code-review.md` | 代码审查清单 |
55 +| `tailwindcss-guide.md` | TailwindCSS 使用规范 |
56 +| `frontend-performance.md` | 前端性能优化 |
57 +
58 +## 🎯 常用命令
59 +
60 +### 开发命令
61 +
62 +```bash
63 +pnpm dev:weapp # 微信小程序开发模式
64 +pnpm dev:h5 # H5 端开发模式
65 +pnpm build:weapp # 微信小程序构建
66 +pnpm build:h5 # H5 端构建
67 +```
68 +
69 +### 代码质量命令
70 +
71 +```bash
72 +pnpm lint # ESLint 检查并修复
73 +pnpm lint:no-fix # ESLint 仅检查
74 +pnpm format # Prettier 格式化
75 +pnpm format:check # Prettier 检查
76 +```
77 +
78 +### Git 命令
79 +
80 +```bash
81 +git add . # 添加所有文件
82 +git commit -m "feat: xxx" # 提交(自动运行检查)
83 +git commit --no-verify -m "xxx" # 跳过检查(不推荐)
84 +```
85 +
86 +## 📝 Commit 规范
87 +
88 +推荐使用 Conventional Commits 格式:
89 +
90 +```
91 +feat: 新功能
92 +fix: 修复 bug
93 +docs: 文档更新
94 +style: 代码格式
95 +refactor: 重构
96 +test: 测试相关
97 +chore: 构建过程或辅助工具
98 +```
99 +
100 +### 示例
101 +
102 +```bash
103 +git commit -m "feat(booking): 添加预约日期选择功能"
104 +git commit -m "fix(auth): 修复登录时 token 未持久化的问题"
105 +git commit -m "docs: 更新开发文档"
106 +```
107 +
108 +## ⚙️ VS Code 配置
109 +
110 +### 推荐插件
111 +
112 +```bash
113 +# 安装推荐插件
114 +code --install-extension dbaeumer.vscode-eslint
115 +code --install-extension esbenp.prettier-vscode
116 +code --install-extension EditorConfig.EditorConfig
117 +code --install-extension Vue.volar
118 +code --install-extension taro.vscode-tarojs
119 +```
120 +
121 +### 工作区配置
122 +
123 +创建 `.vscode/settings.json`
124 +
125 +```json
126 +{
127 + "editor.formatOnSave": false,
128 + "editor.codeActionsOnSave": {
129 + "source.fixAll.eslint": true
130 + },
131 + "[javascript]": {
132 + "editor.defaultFormatter": "esbenp.prettier-vscode"
133 + },
134 + "[vue]": {
135 + "editor.defaultFormatter": "esbenp.prettier-vscode"
136 + },
137 + "files.eol": "\n",
138 + "files.trimTrailingWhitespace": true
139 +}
140 +```
141 +
142 +## 🔍 常见问题
143 +
144 +### Q: Husky 钩子不生效?
145 +
146 +```bash
147 +# 重新初始化 Husky
148 +npx husky install
149 +npx husky add .husky/pre-commit "pnpm lint-staged"
150 +chmod +x .husky/pre-commit
151 +```
152 +
153 +### Q: ESLint 和 Prettier 冲突?
154 +
155 +```bash
156 +# 安装 @vue/eslint-config-prettier
157 +pnpm add -D @vue/eslint-config-prettier
158 +
159 +# 在 .eslintrc.js 的 extends 最后添加
160 +'@vue/eslint-config-prettier'
161 +```
162 +
163 +### Q: 想跳过检查临时提交?
164 +
165 +```bash
166 +# ⚠️ 不推荐,仅用于紧急情况
167 +git commit --no-verify -m "feat: 临时提交"
168 +```
169 +
170 +## 📋 代码审查清单
171 +
172 +提交代码前检查:
173 +
174 +- [ ] 代码已通过 `pnpm lint`
175 +- [ ] 代码已通过 `pnpm format`
176 +- [ ]`console.log``debugger`
177 +- [ ] 无注释掉的代码
178 +- [ ] 代码有必要的注释
179 +- [ ] 功能测试通过
180 +- [ ] 文档已更新(如需要)
181 +
182 +## 🎨 代码风格
183 +
184 +### Vue 组件
185 +
186 +```vue
187 +<script setup>
188 +// 1. 导入
189 +import { ref, computed } from 'vue'
190 +
191 +// 2. Props/Emits
192 +const props = defineProps({})
193 +const emit = defineEmits({})
194 +
195 +// 3. 响应式状态
196 +const count = ref(0)
197 +
198 +// 4. Computed
199 +const double = computed(() => count.value * 2)
200 +
201 +// 5. 方法
202 +const increment = () => { count.value++ }
203 +
204 +// 6. 生命周期
205 +onMounted(() => { init() })
206 +
207 +// 7. Watch
208 +watch(count, (val) => { track(val) })
209 +</script>
210 +```
211 +
212 +### 命名规范
213 +
214 +```javascript
215 +// 组件:PascalCase
216 +UserCard.vue
217 +BookingList.vue
218 +
219 +// 函数/变量:camelCase
220 +getUserInfo
221 +handleSubmit
222 +
223 +// 常量:UPPER_SNAKE_CASE
224 +API_BASE_URL
225 +MAX_RETRY_COUNT
226 +
227 +// 文件夹:kebab-case
228 +use-offline-booking.js
229 +auth-redirect.js
230 +```
231 +
232 +## 🔐 安全检查
233 +
234 +提交前确认:
235 +
236 +- [ ] 无硬编码密钥/Token
237 +- [ ] 用户输入已验证
238 +- [ ] API 错误信息不泄露敏感数据
239 +- [ ] XSS 防护(避免 `v-html` 或净化)
240 +- [ ] 敏感数据不存储在 localStorage
241 +
242 +## 🚀 性能检查
243 +
244 +部署前确认:
245 +
246 +- [ ] 主包体积 < 2MB
247 +- [ ] 单个分包 < 2MB
248 +- [ ] 首屏渲染 < 2s
249 +- [ ] 图片已优化(CDN 参数)
250 +- [ ] 长列表使用虚拟滚动
251 +- [ ] 路由懒加载已配置
252 +
253 +## 📚 参考资源
254 +
255 +- [完整开发指南](./development-guide.md)
256 +- [项目 CLAUDE.md](../CLAUDE.md)
257 +- [Taro 官方文档](https://docs.taro.zone/)
258 +- [Vue 3 官方文档](https://cn.vuejs.org/)
259 +- [NutUI 官方文档](https://nutui.jd.com/4/taro/)
260 +
261 +## 🎯 下一步
262 +
263 +1. ✅ 安装依赖并初始化 Husky
264 +2. ✅ 配置 VS Code
265 +3. ✅ 运行 `pnpm dev:weapp` 启动开发
266 +4. ✅ 开始编码,享受自动代码检查
267 +5. ✅ 查看全局配置了解最佳实践
268 +
269 +祝开发愉快!🎉
1 +# Taro 小程序开发配置指南
2 +
3 +## 配置概览
4 +
5 +项目已配置完整的代码质量保障体系:
6 +
7 +### ✅ 已创建的配置文件
8 +
9 +#### 1. ESLint 配置(`.eslintrc.js`)
10 +- Vue 3 推荐规则
11 +- Taro 小程序适配规则
12 +- 代码风格检查
13 +- 潜在错误检测
14 +
15 +#### 2. Prettier 配置(`.prettierrc`)
16 +- 代码格式化规则
17 +- 统一代码风格
18 +- 与 ESLint 无冲突集成
19 +
20 +#### 3. EditorConfig 配置(`.editorconfig`)
21 +- 编辑器统一配置
22 +- 缩进、换行符等
23 +
24 +#### 4. lint-staged 配置(`.lintstagedrc.js`)
25 +- Git 暂存文件检查
26 +- 仅检查本次修改的文件
27 +
28 +#### 5. Husky 配置(`scripts/setup-husky.sh`)
29 +- Git Hooks 自动化
30 +- 提交前自动检查
31 +
32 +## 快速开始
33 +
34 +### 步骤 1:安装依赖
35 +
36 +```bash
37 +# 安装 ESLint 相关依赖
38 +pnpm add -D eslint prettier eslint-plugin-vue @vue/eslint-config-prettier
39 +
40 +# 安装 Husky 和 lint-staged
41 +pnpm add -D husky lint-staged
42 +```
43 +
44 +### 步骤 2:初始化 Husky
45 +
46 +```bash
47 +# 方式 1:使用自动安装脚本
48 +bash scripts/setup-husky.sh
49 +
50 +# 方式 2:手动安装
51 +npx husky install
52 +npx husky add .husky/pre-commit "pnpm lint-staged"
53 +npx husky add .husky/commit-msg "npx commitlint --edit \$1"
54 +```
55 +
56 +### 步骤 3:更新 package.json
57 +
58 +`package.json``scripts` 中添加:
59 +
60 +```json
61 +{
62 + "scripts": {
63 + "dev:weapp": "npm run build:weapp -- --watch",
64 + "build:weapp": "taro build --type weapp",
65 + "lint": "eslint \"src/**/*.{js,jsx,vue,ts,tsx}\" --fix",
66 + "lint:no-fix": "eslint \"src/**/*.{js,jsx,vue,ts,tsx}\"",
67 + "format": "prettier --write \"src/**/*.{js,jsx,vue,ts,tsx,less,css,json,md}\"",
68 + "format:check": "prettier --check \"src/**/*.{js,jsx,vue,ts,tsx,less,css,json,md}\"",
69 + "prepare": "husky install"
70 + }
71 +}
72 +```
73 +
74 +## 使用说明
75 +
76 +### 日常开发
77 +
78 +#### 1. 开发前检查
79 +
80 +```bash
81 +# 启动开发服务器
82 +pnpm dev:weapp
83 +
84 +# 代码会自动检查,但有错误时不会阻止编译
85 +```
86 +
87 +#### 2. 提交代码
88 +
89 +```bash
90 +# 添加文件到暂存区
91 +git add .
92 +
93 +# 提交代码(会自动运行 lint-staged)
94 +git commit -m "feat: 添加新功能"
95 +
96 +# 如果检查失败,修复后再次提交
97 +git add .
98 +git commit -m "feat: 添加新功能"
99 +```
100 +
101 +#### 3. 手动检查代码
102 +
103 +```bash
104 +# 检查并自动修复
105 +pnpm lint
106 +
107 +# 仅检查不修复
108 +pnpm lint:no-fix
109 +
110 +# 格式化代码
111 +pnpm format
112 +
113 +# 检查代码格式
114 +pnpm format:check
115 +```
116 +
117 +### 跳过检查(不推荐)
118 +
119 +```bash
120 +# 跳过 lint-staged 检查
121 +git commit --no-verify -m "feat: 临时提交"
122 +
123 +# ⚠️ 注意:仅用于紧急情况,平时不要使用
124 +```
125 +
126 +## 编辑器集成
127 +
128 +### VS Code
129 +
130 +#### 1. 安装插件
131 +
132 +推荐安装以下 VS Code 插件:
133 +
134 +```json
135 +{
136 + "recommendations": [
137 + "dbaeumer.vscode-eslint", // ESLint
138 + "esbenp.prettier-vscode", // Prettier
139 + "EditorConfig.EditorConfig", // EditorConfig
140 + "Vue.volar", // Vue 语言支持
141 + "taro.vscode-tarojs" // Taro 开发工具
142 + ]
143 +}
144 +```
145 +
146 +#### 2. 配置 VS Code
147 +
148 +创建 `.vscode/settings.json`
149 +
150 +```json
151 +{
152 + // ESLint
153 + "editor.formatOnSave": false,
154 + "editor.codeActionsOnSave": {
155 + "source.fixAll.eslint": true
156 + },
157 +
158 + // Prettier
159 + "[javascript]": {
160 + "editor.defaultFormatter": "esbenp.prettier-vscode"
161 + },
162 + "[vue]": {
163 + "editor.defaultFormatter": "esbenp.prettier-vscode"
164 + },
165 + "[json]": {
166 + "editor.defaultFormatter": "esbenp.prettier-vscode"
167 + },
168 +
169 + // Vue
170 + "volar.autoCompleteRefs": true,
171 + "volar.codeLens.pugTools": false,
172 + "volar.completion.autoImportComponent": true,
173 +
174 + // 文件
175 + "files.eol": "\n",
176 + "files.trimTrailingWhitespace": true,
177 + "files.insertFinalNewline": true
178 +}
179 +```
180 +
181 +#### 3. 配置 VS Code 任务
182 +
183 +创建 `.vscode/tasks.json`
184 +
185 +```json
186 +{
187 + "version": "2.0.0",
188 + "tasks": [
189 + {
190 + "label": "Lint: 检查并修复",
191 + "type": "npm",
192 + "script": "lint",
193 + "problemMatcher": []
194 + },
195 + {
196 + "label": "Format: 格式化代码",
197 + "type": "npm",
198 + "script": "format",
199 + "problemMatcher": []
200 + },
201 + {
202 + "label": "Dev: 启动微信小程序",
203 + "type": "npm",
204 + "script": "dev:weapp",
205 + "problemMatcher": []
206 + }
207 + ]
208 +}
209 +```
210 +
211 +### WebStorm / IntelliJ IDEA
212 +
213 +1. **启用 ESLint**
214 + - Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint
215 + - 选择 "Automatic ESLint configuration"
216 + - 勾选 "Run eslint --fix on save"
217 +
218 +2. **启用 Prettier**
219 + - Settings → Languages & Frameworks → JavaScript → Prettier
220 + - 选择 "Run on save for files"
221 + - 勾选 "On code reformat"
222 +
223 +3. **启用 EditorConfig**
224 + - Settings → Editor → Code Style → EditorConfig
225 + - 勾选 "Enable EditorConfig support"
226 +
227 +## 配置详解
228 +
229 +### ESLint 规则说明
230 +
231 +#### Vue 相关规则
232 +
233 +```javascript
234 +'vue/multi-word-component-names': 'off', // 允许单词组件名(如 Home.vue)
235 +'vue/no-v-html': 'warn', // 警告使用 v-html(XSS 风险)
236 +'vue/require-default-prop': 'off', // 不强制 prop 默认值
237 +'vue/no-unused-vars': 'warn', // 警告未使用的变量
238 +```
239 +
240 +#### 通用规则
241 +
242 +```javascript
243 +'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 生产环境警告 console
244 +'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', // 生产环境禁止 debugger
245 +'prefer-const': 'error', // 优先使用 const
246 +'no-var': 'error', // 禁止使用 var
247 +'eqeqeq': ['error', 'always'], // 强制使用 ===
248 +'semi': ['error', 'never'], // 不使用分号
249 +'quotes': ['error', 'single'], // 使用单引号
250 +```
251 +
252 +### Prettier 规则说明
253 +
254 +```json
255 +{
256 + "semi": false, // 不使用分号
257 + "singleQuote": true, // 使用单引号
258 + "trailingComma": "none", // 不使用尾随逗号
259 + "printWidth": 100, // 每行最大 100 字符
260 + "tabWidth": 2, // 缩进 2 空格
261 + "endOfLine": "lf" // 使用 LF 换行符
262 +}
263 +```
264 +
265 +## 常见问题
266 +
267 +### Q1: Husky 钩子不生效
268 +
269 +**问题**:提交代码时没有自动运行检查
270 +
271 +**解决方案**
272 +
273 +```bash
274 +# 1. 检查 Husky 是否安装
275 +ls -la .husky/
276 +
277 +# 2. 重新安装 Husky
278 +pnpm add -D husky
279 +npx husky install
280 +
281 +# 3. 添加 pre-commit 钩子
282 +npx husky add .husky/pre-commit "pnpm lint-staged"
283 +
284 +# 4. 检查钩子文件
285 +cat .husky/pre-commit
286 +```
287 +
288 +### Q2: ESLint 和 Prettier 冲突
289 +
290 +**问题**:ESLint 和 Prettier 对同一处代码有不同规则
291 +
292 +**解决方案**
293 +
294 +```bash
295 +# 安装 @vue/eslint-config-prettier
296 +pnpm add -D @vue/eslint-config-prettier
297 +
298 +# 在 .eslintrc.js 中添加
299 +{
300 + "extends": [
301 + 'plugin:vue/vue3-recommended',
302 + '@vue/eslint-config-prettier' // 放在最后
303 + ]
304 +}
305 +```
306 +
307 +### Q3: lint-staged 检查所有文件
308 +
309 +**问题**:每次提交都检查所有文件,很慢
310 +
311 +**解决方案**
312 +
313 +```bash
314 +# 确保 lint-staged 配置正确
315 +cat .lintstagedrc.js
316 +
317 +# 应该配置为:
318 +{
319 + "*.{js,jsx,vue}": ["eslint --fix", "prettier --write"]
320 +}
321 +```
322 +
323 +### Q4: 提交被阻止,但不想修复
324 +
325 +**问题**:代码有问题但想临时提交
326 +
327 +**解决方案**
328 +
329 +```bash
330 +# ⚠️ 不推荐,仅用于紧急情况
331 +git commit --no-verify -m "feat: 临时提交"
332 +```
333 +
334 +### Q5: Taro API 报 ESLint 错误
335 +
336 +**问题**:使用了 `wx` 全局变量报错
337 +
338 +**解决方案**
339 +
340 +```javascript
341 +// .eslintrc.js 中已配置
342 +globals: {
343 + wx: 'readonly',
344 + getCurrentPages: 'readonly',
345 + getApp: 'readonly'
346 +}
347 +```
348 +
349 +## 最佳实践
350 +
351 +### 1. 提交前自检
352 +
353 +```bash
354 +# 1. 拉取最新代码
355 +git pull origin develop
356 +
357 +# 2. 运行检查
358 +pnpm lint
359 +pnpm format:check
360 +
361 +# 3. 运行测试(如果有)
362 +pnpm test
363 +
364 +# 4. 提交代码
365 +git add .
366 +git commit -m "feat: 添加新功能"
367 +```
368 +
369 +### 2. Commit 信息规范
370 +
371 +推荐使用 Conventional Commits 格式:
372 +
373 +```
374 +feat: 新功能
375 +fix: 修复 bug
376 +docs: 文档更新
377 +style: 代码格式(不影响代码运行的变动)
378 +refactor: 重构(既不是新增功能,也不是修改 bug 的代码变动)
379 +test: 测试相关
380 +chore: 构建过程或辅助工具的变动
381 +```
382 +
383 +示例:
384 +
385 +```bash
386 +git commit -m "feat(booking): 添加预约日期选择功能"
387 +git commit -m "fix(auth): 修复登录时 token 未持久化的问题"
388 +git commit -m "docs: 更新开发文档"
389 +```
390 +
391 +### 3. 代码审查清单
392 +
393 +在提交 PR 前检查:
394 +
395 +- [ ] 代码已通过 ESLint 检查
396 +- [ ] 代码已通过 Prettier 格式化
397 +- [ ]`console.log``debugger`
398 +- [ ] 无注释掉的代码
399 +- [ ] 代码有必要的注释
400 +- [ ] 测试已通过(如果有)
401 +- [ ] 文档已更新(如需要)
402 +
403 +## 团队协作
404 +
405 +### 统一开发环境
406 +
407 +确保团队成员使用相同的配置:
408 +
409 +```bash
410 +# 1. 克隆项目
411 +git clone <repo-url>
412 +
413 +# 2. 安装依赖
414 +pnpm install
415 +
416 +# 3. 初始化 Husky
417 +pnpm prepare
418 +
419 +# 4. 安装 VS Code 插件
420 +code --install-extension dbaeumer.vscode-eslint
421 +code --install-extension esbenp.prettier-vscode
422 +code --install-extension Vue.volar
423 +```
424 +
425 +### 代码审查流程
426 +
427 +1. **开发者**:提交代码前运行 `pnpm lint`
428 +2. **Husky**:自动运行 `lint-staged`
429 +3. **CI/CD**:运行完整的 `pnpm lint``pnpm test`
430 +4. **审查者**:检查代码质量和规范
431 +5. **合并**:通过所有检查后合并
432 +
433 +## 持续改进
434 +
435 +### 定期更新依赖
436 +
437 +```bash
438 +# 检查过时的依赖
439 +pnpm outdated
440 +
441 +# 更新依赖
442 +pnpm update
443 +
444 +# 更新主要版本
445 +pnpm upgrade --latest
446 +```
447 +
448 +### 自定义规则
449 +
450 +根据团队需求调整规则:
451 +
452 +```javascript
453 +// .eslintrc.js
454 +rules: {
455 + // 添加团队特定规则
456 + 'custom-rule-name': 'error'
457 +}
458 +```
459 +
460 +## 参考资源
461 +
462 +- [ESlint 官方文档](https://eslint.org/)
463 +- [Prettier 官方文档](https://prettier.io/)
464 +- [EditorConfig 官方文档](https://editorconfig.org/)
465 +- [Husky 官方文档](https://typicode.github.io/husky/)
466 +- [lint-staged 官方文档](https://github.com/okonet/lint-staged)
467 +- [Vue ESLint 官方插件](https://eslint.vuejs.org/)
468 +- [Conventional Commits](https://www.conventionalcommits.org/)
...@@ -27,7 +27,11 @@ ...@@ -27,7 +27,11 @@
27 "dev:qq": "NODE_ENV=development taro build --type qq --watch", 27 "dev:qq": "NODE_ENV=development taro build --type qq --watch",
28 "dev:quickapp": "NODE_ENV=development taro build --type quickapp --watch", 28 "dev:quickapp": "NODE_ENV=development taro build --type quickapp --watch",
29 "postinstall": "weapp-tw patch", 29 "postinstall": "weapp-tw patch",
30 - "lint": "eslint --ext .js,.vue src" 30 + "lint": "eslint \"src/**/*.{js,jsx,vue}\" --fix",
31 + "lint:no-fix": "eslint \"src/**/*.{js,jsx,vue}\"",
32 + "format": "prettier --write \"src/**/*.{js,jsx,vue,less,css,json,md}\"",
33 + "format:check": "prettier --check \"src/**/*.{js,jsx,vue,less,css,json,md}\"",
34 + "prepare": "husky install"
31 }, 35 },
32 "browserslist": [ 36 "browserslist": [
33 "last 3 versions", 37 "last 3 versions",
...@@ -72,17 +76,23 @@ ...@@ -72,17 +76,23 @@
72 "@types/webpack-env": "^1.13.6", 76 "@types/webpack-env": "^1.13.6",
73 "@vue/babel-plugin-jsx": "^1.0.6", 77 "@vue/babel-plugin-jsx": "^1.0.6",
74 "@vue/compiler-sfc": "^3.0.0", 78 "@vue/compiler-sfc": "^3.0.0",
79 + "@vue/eslint-config-prettier": "^10.2.0",
75 "autoprefixer": "^10.4.21", 80 "autoprefixer": "^10.4.21",
76 "babel-preset-taro": "4.1.9", 81 "babel-preset-taro": "4.1.9",
77 "css-loader": "3.4.2", 82 "css-loader": "3.4.2",
78 "eslint": "^8.12.0", 83 "eslint": "^8.12.0",
79 "eslint-config-taro": "4.1.9", 84 "eslint-config-taro": "4.1.9",
85 + "eslint-plugin-vue": "^10.7.0",
86 + "husky": "^9.1.7",
80 "less": "^4.2.0", 87 "less": "^4.2.0",
88 + "lint-staged": "^16.2.7",
81 "postcss": "^8.5.6", 89 "postcss": "^8.5.6",
90 + "prettier": "^3.8.1",
82 "sass": "^1.78.0", 91 "sass": "^1.78.0",
83 "style-loader": "1.3.0", 92 "style-loader": "1.3.0",
84 "tailwindcss": "^3.4.0", 93 "tailwindcss": "^3.4.0",
85 "unplugin-vue-components": "^0.26.0", 94 "unplugin-vue-components": "^0.26.0",
95 + "vue-eslint-parser": "^10.2.0",
86 "vue-loader": "^17.0.0", 96 "vue-loader": "^17.0.0",
87 "weapp-tailwindcss": "^4.1.10", 97 "weapp-tailwindcss": "^4.1.10",
88 "webpack": "5.91.0" 98 "webpack": "5.91.0"
......
This diff is collapsed. Click to expand it.
1 +#!/bin/bash
2 +
3 +# Husky 初始化脚本
4 +# 使用方法: bash scripts/setup-husky.sh
5 +
6 +set -e
7 +
8 +echo "🔧 开始设置 Husky Git Hooks..."
9 +
10 +# 检查是否在项目根目录
11 +if [ ! -f "package.json" ]; then
12 + echo "❌ 错误:请在项目根目录运行此脚本"
13 + exit 1
14 +fi
15 +
16 +# 安装依赖(如果未安装)
17 +echo "📦 安装依赖..."
18 +pnpm add -D husky lint-staged prettier || {
19 + echo "❌ 依赖安装失败"
20 + exit 1
21 +}
22 +
23 +# 初始化 Husky
24 +echo "🪝 初始化 Husky..."
25 +npx husky install || {
26 + echo "❌ Husky 初始化失败"
27 + exit 1
28 +}
29 +
30 +# 创建 pre-commit 钩子
31 +echo "📝 创建 pre-commit 钩子..."
32 +cat > .husky/pre-commit << 'EOF'
33 +#!/bin/sh
34 +. "$(dirname "$0")/_/husky.sh"
35 +
36 +echo "🔍 运行代码检查..."
37 +pnpm lint-staged
38 +EOF
39 +
40 +# 添加执行权限
41 +chmod +x .husky/pre-commit
42 +
43 +# 创建 commit-msg 钩子(可选,用于验证 commit 信息)
44 +cat > .husky/commit-msg << 'EOF'
45 +#!/bin/sh
46 +. "$(dirname "$0")/_/husky.sh"
47 +
48 +# 验证 commit 信息格式(可选)
49 +# commit_regex='^(feat|fix|docs|style|refactor|test|chore|build|ci|perf|revert)(\(.+\))?: .{1,50}'
50 +#
51 +#if ! grep -qE "$commit_regex" "$1"; then
52 +# echo "❌ Commit 信息格式不正确"
53 +# echo "✅ 正确格式: type(scope): subject"
54 +# echo "📝 类型: feat, fix, docs, style, refactor, test, chore, etc."
55 +# exit 1
56 +#fi
57 +
58 +echo "✅ Commit 信息验证通过"
59 +EOF
60 +
61 +chmod +x .husky/commit-msg
62 +
63 +# 更新 package.json scripts
64 +echo "📦 更新 package.json scripts..."
65 +if command -v jq > /dev/null 2>&1; then
66 + # 如果系统有 jq,使用它更新 package.json
67 + jq '.scripts.prepare = "husky install"' package.json > package.json.tmp && mv package.json.tmp package.json
68 +else
69 + echo "⚠️ 请手动在 package.json 的 scripts 中添加: \"prepare\": \"husky install\""
70 +fi
71 +
72 +echo "✅ Git Hooks 设置完成!"
73 +echo ""
74 +echo "📝 使用说明:"
75 +echo " - 每次 commit 前会自动运行 ESLint 和 Prettier"
76 +echo " - 如果检查失败,commit 将被中止"
77 +echo " - 使用 'git commit --no-verify' 跳过检查(不推荐)"
78 +echo ""
79 +echo "🎯 现在可以开始开发了!"
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
5 * @FilePath: /tswj/src/api/common.js 5 * @FilePath: /tswj/src/api/common.js
6 * @Description: 通用接口 6 * @Description: 通用接口
7 */ 7 */
8 -import { fn, fetch, uploadFn } from '@/api/fn'; 8 +import { fn, fetch, uploadFn } from '@/api/fn'
9 9
10 const Api = { 10 const Api = {
11 SMS: '/srv/?a=sms', 11 SMS: '/srv/?a=sms',
12 TOKEN: '/srv/?a=upload', 12 TOKEN: '/srv/?a=upload',
13 - SAVE_FILE: '/srv/?a=upload&t=save_file', 13 + SAVE_FILE: '/srv/?a=upload&t=save_file'
14 } 14 }
15 15
16 /** 16 /**
...@@ -19,7 +19,7 @@ const Api = { ...@@ -19,7 +19,7 @@ const Api = {
19 * @param {string} params.phone 手机号 19 * @param {string} params.phone 手机号
20 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 20 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
21 */ 21 */
22 -export const smsAPI = (params) => fn(fetch.post(Api.SMS, params)); 22 +export const smsAPI = params => fn(fetch.post(Api.SMS, params))
23 23
24 /** 24 /**
25 * @description: 获取七牛token 25 * @description: 获取七牛token
...@@ -28,7 +28,7 @@ export const smsAPI = (params) => fn(fetch.post(Api.SMS, params)); ...@@ -28,7 +28,7 @@ export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));
28 * @param {string} params.file 图片 base64 28 * @param {string} params.file 图片 base64
29 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回(data 为上传 token 等信息) 29 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回(data 为上传 token 等信息)
30 */ 30 */
31 -export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params)); 31 +export const qiniuTokenAPI = params => fn(fetch.stringifyPost(Api.TOKEN, params))
32 32
33 /** 33 /**
34 * @description: 上传七牛 34 * @description: 上传七牛
...@@ -37,7 +37,7 @@ export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, param ...@@ -37,7 +37,7 @@ export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, param
37 * @param {Object} config axios 配置 37 * @param {Object} config axios 配置
38 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false 38 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false
39 */ 39 */
40 -export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config)); 40 +export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config))
41 41
42 /** 42 /**
43 * @description: 保存图片 43 * @description: 保存图片
...@@ -49,4 +49,4 @@ export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url ...@@ -49,4 +49,4 @@ export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url
49 * @param {string} params.filekey 文件 key 49 * @param {string} params.filekey 文件 key
50 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回 50 * @returns {Promise<{code:number,data:any,msg:string}>} 标准返回
51 */ 51 */
52 -export const saveFileAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_FILE, params)); 52 +export const saveFileAPI = params => fn(fetch.stringifyPost(Api.SAVE_FILE, params))
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 * @FilePath: /xyxBooking-weapp/src/api/fn.js 5 * @FilePath: /xyxBooking-weapp/src/api/fn.js
6 * @Description: 统一后端返回格式(强制 { code, data, msg }) 6 * @Description: 统一后端返回格式(强制 { code, data, msg })
7 */ 7 */
8 -import axios from '@/utils/request'; 8 +import axios from '@/utils/request'
9 import Taro from '@tarojs/taro' 9 import Taro from '@tarojs/taro'
10 import qs from 'qs' 10 import qs from 'qs'
11 11
...@@ -16,7 +16,7 @@ import qs from 'qs' ...@@ -16,7 +16,7 @@ import qs from 'qs'
16 * @param {Promise<any>} api axios 请求 Promise 16 * @param {Promise<any>} api axios 请求 Promise
17 * @returns {Promise<{code:number,data:any,msg:string,show?:boolean}>} 标准化后的返回对象 17 * @returns {Promise<{code:number,data:any,msg:string,show?:boolean}>} 标准化后的返回对象
18 */ 18 */
19 -export const fn = (api) => { 19 +export const fn = api => {
20 return api 20 return api
21 .then(res => { 21 .then(res => {
22 // 约定:后端 code === 1 为成功 22 // 约定:后端 code === 1 为成功
...@@ -26,19 +26,29 @@ export const fn = (api) => { ...@@ -26,19 +26,29 @@ export const fn = (api) => {
26 } 26 }
27 // 失败兜底:优先返回后端响应,同时做 toast 提示 27 // 失败兜底:优先返回后端响应,同时做 toast 提示
28 console.warn('接口请求失败:', res) 28 console.warn('接口请求失败:', res)
29 - if (res_data && res_data.show === false) return res_data 29 + if (res_data && res_data.show === false) {
30 + return res_data
31 + }
30 Taro.showToast({ 32 Taro.showToast({
31 - title: (res_data && res_data.msg) ? res_data.msg : '请求失败', 33 + title: res_data && res_data.msg ? res_data.msg : '请求失败',
32 icon: 'none', 34 icon: 'none',
33 duration: 2000 35 duration: 2000
34 }) 36 })
35 return res_data || { code: 0, data: null, msg: '请求失败' } 37 return res_data || { code: 0, data: null, msg: '请求失败' }
36 }) 38 })
37 .catch(err => { 39 .catch(err => {
38 - console.error('接口请求异常:', err); 40 + console.error('接口请求异常:', err)
39 - return { code: 0, data: null, msg: (err && (err.msg || err.message || err.errMsg)) ? (err.msg || err.message || err.errMsg) : '网络异常' } 41 + return {
42 + code: 0,
43 + data: null,
44 + msg:
45 + err && (err.msg || err.message || err.errMsg)
46 + ? err.msg || err.message || err.errMsg
47 + : '网络异常'
48 + }
40 }) 49 })
41 - .finally(() => { // 最终执行 50 + .finally(() => {
51 + // 最终执行
42 }) 52 })
43 } 53 }
44 54
...@@ -47,25 +57,26 @@ export const fn = (api) => { ...@@ -47,25 +57,26 @@ export const fn = (api) => {
47 * @param {Promise<any>} api axios 请求 Promise 57 * @param {Promise<any>} api axios 请求 Promise
48 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false 58 * @returns {Promise<any|false>} 成功返回七牛响应数据,失败返回 false
49 */ 59 */
50 -export const uploadFn = (api) => { 60 +export const uploadFn = api => {
51 return api 61 return api
52 .then(res => { 62 .then(res => {
53 if (res.statusText === 'OK') { 63 if (res.statusText === 'OK') {
54 - return res.data || true; 64 + return res.data || true
55 - } else { 65 + }
56 - console.warn('七牛上传失败:', res); 66 + console.warn('七牛上传失败:', res)
57 - if (!res.data.show) return false; 67 + if (!res.data.show) {
58 - Taro.showToast({ 68 + return false
59 - title: res.data.msg,
60 - icon: 'none',
61 - duration: 2000
62 - });
63 - return false;
64 } 69 }
70 + Taro.showToast({
71 + title: res.data.msg,
72 + icon: 'none',
73 + duration: 2000
74 + })
75 + return false
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,14 +32,15 @@ if (process.env.NODE_ENV === 'development') { ...@@ -32,14 +32,15 @@ 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 - ? [ 36 + process.env.NODE_ENV === 'development'
37 - { 37 + ? [
38 - root: 'pages/demo', 38 + {
39 - pages: ['index'], 39 + root: 'pages/demo',
40 - }, 40 + pages: ['index']
41 - ] 41 + }
42 - : [] 42 + ]
43 + : []
43 44
44 export default { 45 export default {
45 pages, 46 pages,
...@@ -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 }
......
This diff is collapsed. Click to expand it.
...@@ -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)
107 } 99 }
108 } 100 }
109 - }, 101 + }
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
215 } 208 }
216 - }, 209 + }
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,101 +55,104 @@ const props = defineProps({ ...@@ -54,101 +55,104 @@ 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 = () => {
106 - for (const item of userList.value) { 107 + for (const item of userList.value) {
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 - }
119 - }
120 - const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}"><path d="${d}" fill="#000"/></svg>`;
121 -
122 - // 转 Base64
123 - const buffer = new ArrayBuffer(svg.length);
124 - const view = new Uint8Array(buffer);
125 - for (let i = 0; i < svg.length; i++) {
126 - view[i] = svg.charCodeAt(i);
127 - }
128 - const b64 = Taro.arrayBufferToBase64(buffer);
129 -
130 - qrCodeImages.value[item.qr_code] = `data:image/svg+xml;base64,${b64}`;
131 - } catch (err) {
132 - console.error('QR Gen Error', err);
133 } 118 }
119 + }
120 + }
121 + const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}"><path d="${d}" fill="#000"/></svg>`
122 +
123 + // 转 Base64
124 + const buffer = new ArrayBuffer(svg.length)
125 + const view = new Uint8Array(buffer)
126 + for (let i = 0; i < svg.length; i++) {
127 + view[i] = svg.charCodeAt(i)
134 } 128 }
129 + const b64 = Taro.arrayBufferToBase64(buffer)
130 +
131 + qrCodeImages.value[item.qr_code] = `data:image/svg+xml;base64,${b64}`
132 + } catch (err) {
133 + console.error('QR Gen Error', err)
134 + }
135 } 135 }
136 + }
136 } 137 }
137 138
138 onMounted(() => { 139 onMounted(() => {
139 - if (props.list && props.list.length > 0) { 140 + if (props.list && props.list.length > 0) {
140 - userList.value = props.list; 141 + userList.value = props.list
141 - generateQrCodes(); 142 + generateQrCodes()
142 - } 143 + }
143 -}); 144 +})
144 145
145 -watch(() => props.list, (newVal) => { 146 +watch(
147 + () => props.list,
148 + newVal => {
146 if (newVal && newVal.length > 0) { 149 if (newVal && newVal.length > 0) {
147 - userList.value = newVal; 150 + userList.value = newVal
148 - generateQrCodes(); 151 + generateQrCodes()
149 } 152 }
150 -}, { deep: true }); 153 + },
151 - 154 + { deep: true }
155 +)
152 </script> 156 </script>
153 157
154 <style lang="less"> 158 <style lang="less">
...@@ -159,12 +163,12 @@ watch(() => props.list, (newVal) => { ...@@ -159,12 +163,12 @@ watch(() => props.list, (newVal) => {
159 flex-direction: column; 163 flex-direction: column;
160 justify-content: center; 164 justify-content: center;
161 align-items: center; 165 align-items: center;
162 - background-color: #FFF; 166 + background-color: #fff;
163 border-radius: 16rpx; 167 border-radius: 16rpx;
164 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.27); 168 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.27);
165 169
166 .user-info { 170 .user-info {
167 - color: #A6A6A6; 171 + color: #a6a6a6;
168 font-size: 37rpx; 172 font-size: 37rpx;
169 margin-top: 16rpx; 173 margin-top: 16rpx;
170 margin-bottom: 16rpx; 174 margin-bottom: 16rpx;
...@@ -180,21 +184,25 @@ watch(() => props.list, (newVal) => { ...@@ -180,21 +184,25 @@ watch(() => props.list, (newVal) => {
180 align-items: center; 184 align-items: center;
181 .left { 185 .left {
182 image { 186 image {
183 - width: 56rpx; height: 56rpx; margin-right: 16rpx; 187 + width: 56rpx;
188 + height: 56rpx;
189 + margin-right: 16rpx;
184 } 190 }
185 } 191 }
186 .center { 192 .center {
187 - border: 2rpx solid #D1D1D1; 193 + border: 2rpx solid #d1d1d1;
188 border-radius: 40rpx; 194 border-radius: 40rpx;
189 padding: 46rpx; 195 padding: 46rpx;
190 position: relative; 196 position: relative;
191 image { 197 image {
192 - width: 400rpx; height: 400rpx; 198 + width: 400rpx;
199 + height: 400rpx;
193 } 200 }
194 } 201 }
195 .right { 202 .right {
196 image { 203 image {
197 - width: 56rpx; height: 56rpx; 204 + width: 56rpx;
205 + height: 56rpx;
198 margin-left: 16rpx; 206 margin-left: 16rpx;
199 } 207 }
200 } 208 }
...@@ -208,13 +216,13 @@ watch(() => props.list, (newVal) => { ...@@ -208,13 +216,13 @@ watch(() => props.list, (newVal) => {
208 .user-item { 216 .user-item {
209 position: relative; 217 position: relative;
210 padding: 8rpx 16rpx; 218 padding: 8rpx 16rpx;
211 - border: 2rpx solid #A67939; 219 + border: 2rpx solid #a67939;
212 margin: 8rpx; 220 margin: 8rpx;
213 border-radius: 10rpx; 221 border-radius: 10rpx;
214 - color: #A67939; 222 + color: #a67939;
215 &.checked { 223 &.checked {
216 - color: #FFF; 224 + color: #fff;
217 - background-color: #A67939; 225 + background-color: #a67939;
218 } 226 }
219 &.border { 227 &.border {
220 margin-right: 16rpx; 228 margin-right: 16rpx;
...@@ -224,7 +232,7 @@ watch(() => props.list, (newVal) => { ...@@ -224,7 +232,7 @@ watch(() => props.list, (newVal) => {
224 top: calc(50% - 16rpx); 232 top: calc(50% - 16rpx);
225 content: ''; 233 content: '';
226 height: 32rpx; 234 height: 32rpx;
227 - border-right: 2rpx solid #A67939; 235 + border-right: 2rpx solid #a67939;
228 } 236 }
229 } 237 }
230 } 238 }
...@@ -238,7 +246,7 @@ watch(() => props.list, (newVal) => { ...@@ -238,7 +246,7 @@ watch(() => props.list, (newVal) => {
238 margin-bottom: 32rpx; 246 margin-bottom: 32rpx;
239 247
240 .no-qrcode-title { 248 .no-qrcode-title {
241 - color: #A67939; 249 + color: #a67939;
242 font-size: 34rpx; 250 font-size: 34rpx;
243 } 251 }
244 } 252 }
......
This diff is collapsed. Click to expand it.
...@@ -16,7 +16,10 @@ ...@@ -16,7 +16,10 @@
16 </view> 16 </view>
17 <view class="center"> 17 <view class="center">
18 <image :src="userinfo.qr_code_url" mode="aspectFit" /> 18 <image :src="userinfo.qr_code_url" mode="aspectFit" />
19 - <view v-if="useStatus === STATUS_CODE.CANCELED || useStatus === STATUS_CODE.USED" class="qrcode-used"> 19 + <view
20 + v-if="useStatus === STATUS_CODE.CANCELED || useStatus === STATUS_CODE.USED"
21 + class="qrcode-used"
22 + >
20 <view class="overlay"></view> 23 <view class="overlay"></view>
21 <text class="status-text">二维码{{ qr_code_status[useStatus] }}</text> 24 <text class="status-text">二维码{{ qr_code_status[useStatus] }}</text>
22 </view> 25 </view>
...@@ -25,11 +28,14 @@ ...@@ -25,11 +28,14 @@
25 <!-- <image src="https://cdn.ipadbiz.cn/xys/booking/%E5%8F%B3@2x.png"> --> 28 <!-- <image src="https://cdn.ipadbiz.cn/xys/booking/%E5%8F%B3@2x.png"> -->
26 </view> 29 </view>
27 </view> 30 </view>
28 - <view style="color: red; margin-top: 32rpx;">{{ userinfo.datetime }}</view> 31 + <view style="color: red; margin-top: 32rpx">{{ userinfo.datetime }}</view>
29 </view> 32 </view>
30 </view> 33 </view>
31 <view v-else class="no-qrcode"> 34 <view v-else class="no-qrcode">
32 - <image src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png" style="width: 320rpx; height: 320rpx;" /> 35 + <image
36 + src="https://cdn.ipadbiz.cn/xys/booking/%E6%9A%82%E6%97%A0@2x.png"
37 + style="width: 320rpx; height: 320rpx"
38 + />
33 <view class="no-qrcode-title">您还没有预约过今天参观</view> 39 <view class="no-qrcode-title">您还没有预约过今天参观</view>
34 </view> 40 </view>
35 </view> 41 </view>
...@@ -37,9 +43,9 @@ ...@@ -37,9 +43,9 @@
37 43
38 <script setup> 44 <script setup>
39 import { ref, onMounted, watch, onUnmounted } from 'vue' 45 import { ref, onMounted, watch, onUnmounted } from 'vue'
40 -import { formatDatetime } from '@/utils/tools'; 46 +import { formatDatetime } from '@/utils/tools'
41 import { qrcodeStatusAPI, queryQrCodeAPI } from '@/api/index' 47 import { qrcodeStatusAPI, queryQrCodeAPI } from '@/api/index'
42 -import BASE_URL from '@/utils/config'; 48 +import BASE_URL from '@/utils/config'
43 49
44 const props = defineProps({ 50 const props = defineProps({
45 id: { 51 id: {
...@@ -50,42 +56,44 @@ const props = defineProps({ ...@@ -50,42 +56,44 @@ const props = defineProps({
50 type: Number, 56 type: Number,
51 default: 1 57 default: 1
52 } 58 }
53 -}); 59 +})
54 60
55 -const userinfo = ref({}); 61 +const userinfo = ref({})
56 62
57 -const replaceMiddleCharacters = (input_string) => { 63 +const replaceMiddleCharacters = input_string => {
58 if (!input_string || input_string.length < 15) { 64 if (!input_string || input_string.length < 15) {
59 - return input_string; 65 + return input_string
60 } 66 }
61 - const start = Math.floor((input_string.length - 8) / 2); 67 + const start = Math.floor((input_string.length - 8) / 2)
62 - const end = start + 8; 68 + const end = start + 8
63 - const replacement = '*'.repeat(8); 69 + const replacement = '*'.repeat(8)
64 - return input_string.substring(0, start) + replacement + input_string.substring(end); 70 + return input_string.substring(0, start) + replacement + input_string.substring(end)
65 } 71 }
66 72
67 -const formatId = (id) => replaceMiddleCharacters(id); 73 +const formatId = id => replaceMiddleCharacters(id)
68 74
69 -const useStatus = ref('0'); 75 +const useStatus = ref('0')
70 const is_loading = ref(false) 76 const is_loading = ref(false)
71 let is_destroyed = false 77 let is_destroyed = false
72 78
73 const qr_code_status = { 79 const qr_code_status = {
74 - '1': '未激活', 80 + 1: '未激活',
75 - '3': '待使用', 81 + 3: '待使用',
76 - '5': '被取消', 82 + 5: '被取消',
77 - '7': '已使用', 83 + 7: '已使用'
78 -}; 84 +}
79 85
80 const STATUS_CODE = { 86 const STATUS_CODE = {
81 APPLY: '1', 87 APPLY: '1',
82 SUCCESS: '3', 88 SUCCESS: '3',
83 CANCELED: '5', 89 CANCELED: '5',
84 - USED: '7', 90 + USED: '7'
85 -}; 91 +}
86 92
87 -const build_qr_code_url = (qr_code) => { 93 +const build_qr_code_url = qr_code => {
88 - if (!qr_code) return '' 94 + if (!qr_code) {
95 + return ''
96 + }
89 return `${BASE_URL}/admin?m=srv&a=get_qrcode&key=${encodeURIComponent(String(qr_code))}` 97 return `${BASE_URL}/admin?m=srv&a=get_qrcode&key=${encodeURIComponent(String(qr_code))}`
90 } 98 }
91 99
...@@ -95,8 +103,10 @@ const build_qr_code_url = (qr_code) => { ...@@ -95,8 +103,10 @@ const build_qr_code_url = (qr_code) => {
95 * @return {*} 格式化后的数据 103 * @return {*} 格式化后的数据
96 */ 104 */
97 105
98 -const normalize_item = (raw) => { 106 +const normalize_item = raw => {
99 - if (!raw || typeof raw !== 'object') return null 107 + if (!raw || typeof raw !== 'object') {
108 + return null
109 + }
100 const qr_code = raw.qr_code ? String(raw.qr_code) : '' 110 const qr_code = raw.qr_code ? String(raw.qr_code) : ''
101 const id_number = raw.id_number ? String(raw.id_number) : '' 111 const id_number = raw.id_number ? String(raw.id_number) : ''
102 return { 112 return {
...@@ -104,7 +114,7 @@ const normalize_item = (raw) => { ...@@ -104,7 +114,7 @@ const normalize_item = (raw) => {
104 qr_code, 114 qr_code,
105 qr_code_url: build_qr_code_url(qr_code), 115 qr_code_url: build_qr_code_url(qr_code),
106 datetime: formatDatetime({ begin_time: raw.begin_time, end_time: raw.end_time }), 116 datetime: formatDatetime({ begin_time: raw.begin_time, end_time: raw.end_time }),
107 - id: formatId(id_number), 117 + id: formatId(id_number)
108 } 118 }
109 } 119 }
110 120
...@@ -123,13 +133,21 @@ const reset_state = () => { ...@@ -123,13 +133,21 @@ const reset_state = () => {
123 * @return {*} 状态码 133 * @return {*} 状态码
124 */ 134 */
125 135
126 -const load_qr_code_status = async (qr_code) => { 136 +const load_qr_code_status = async qr_code => {
127 - if (!qr_code) return 137 + if (!qr_code) {
138 + return
139 + }
128 const res = await qrcodeStatusAPI({ qr_code }) 140 const res = await qrcodeStatusAPI({ qr_code })
129 - if (is_destroyed) return 141 + if (is_destroyed) {
130 - if (!res || res.code !== 1) return 142 + return
143 + }
144 + if (!res || res.code !== 1) {
145 + return
146 + }
131 const status = res?.data?.status 147 const status = res?.data?.status
132 - if (status === undefined || status === null) return 148 + if (status === undefined || status === null) {
149 + return
150 + }
133 useStatus.value = String(status) 151 useStatus.value = String(status)
134 } 152 }
135 153
...@@ -139,7 +157,7 @@ const load_qr_code_status = async (qr_code) => { ...@@ -139,7 +157,7 @@ const load_qr_code_status = async (qr_code) => {
139 * @return {*} 预约码卡信息 157 * @return {*} 预约码卡信息
140 */ 158 */
141 159
142 -const load_qr_code_info = async (id_number) => { 160 +const load_qr_code_info = async id_number => {
143 const id = String(id_number || '').trim() 161 const id = String(id_number || '').trim()
144 if (!id) { 162 if (!id) {
145 reset_state() 163 reset_state()
...@@ -148,9 +166,13 @@ const load_qr_code_info = async (id_number) => { ...@@ -148,9 +166,13 @@ const load_qr_code_info = async (id_number) => {
148 166
149 is_loading.value = true 167 is_loading.value = true
150 const params = { id_number: id } 168 const params = { id_number: id }
151 - if (props.id_type) params.id_type = props.id_type 169 + if (props.id_type) {
170 + params.id_type = props.id_type
171 + }
152 const res = await queryQrCodeAPI(params) 172 const res = await queryQrCodeAPI(params)
153 - if (is_destroyed) return 173 + if (is_destroyed) {
174 + return
175 + }
154 is_loading.value = false 176 is_loading.value = false
155 177
156 if (!res || res.code !== 1 || !res.data) { 178 if (!res || res.code !== 1 || !res.data) {
...@@ -180,7 +202,9 @@ onMounted(() => { ...@@ -180,7 +202,9 @@ onMounted(() => {
180 watch( 202 watch(
181 () => [props.id, props.id_type], 203 () => [props.id, props.id_type],
182 ([val]) => { 204 ([val]) => {
183 - if (is_loading.value) return 205 + if (is_loading.value) {
206 + return
207 + }
184 load_qr_code_info(val) 208 load_qr_code_info(val)
185 } 209 }
186 ) 210 )
...@@ -194,12 +218,12 @@ watch( ...@@ -194,12 +218,12 @@ watch(
194 flex-direction: column; 218 flex-direction: column;
195 justify-content: center; 219 justify-content: center;
196 align-items: center; 220 align-items: center;
197 - background-color: #FFF; 221 + background-color: #fff;
198 border-radius: 16rpx; 222 border-radius: 16rpx;
199 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.27); 223 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.27);
200 224
201 .user-info { 225 .user-info {
202 - color: #A6A6A6; 226 + color: #a6a6a6;
203 font-size: 37rpx; 227 font-size: 37rpx;
204 margin-top: 16rpx; 228 margin-top: 16rpx;
205 margin-bottom: 16rpx; 229 margin-bottom: 16rpx;
...@@ -208,41 +232,42 @@ watch( ...@@ -208,41 +232,42 @@ 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;
220 - top: 0; 245 + top: 0;
221 - left: 0; 246 + left: 0;
222 - right: 0; 247 + right: 0;
223 - bottom: 0; 248 + bottom: 0;
224 - border-radius: 40rpx; 249 + border-radius: 40rpx;
225 - overflow: hidden; 250 + overflow: hidden;
226 251
227 - .overlay { 252 + .overlay {
228 - width: 100%; 253 + width: 100%;
229 - height: 100%; 254 + height: 100%;
230 - background-image: url('https://cdn.ipadbiz.cn/xys/booking/southeast.jpeg'); 255 + background-image: url('https://cdn.ipadbiz.cn/xys/booking/southeast.jpeg');
231 - background-size: contain; 256 + background-size: contain;
232 - opacity: 0.9; 257 + opacity: 0.9;
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%;
240 - transform: translate(-50%, -50%); 265 + transform: translate(-50%, -50%);
241 - font-size: 38rpx; 266 + font-size: 38rpx;
242 - white-space: nowrap; 267 + white-space: nowrap;
243 - font-weight: bold; 268 + font-weight: bold;
244 - z-index: 10; 269 + z-index: 10;
245 - } 270 + }
246 } 271 }
247 } 272 }
248 } 273 }
...@@ -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 {
...@@ -251,12 +275,12 @@ const formatStatus = (status) => { ...@@ -251,12 +275,12 @@ const formatStatus = (status) => {
251 value: '退款中' 275 value: '退款中'
252 } 276 }
253 default: 277 default:
254 - return { key: '', value: '' } 278 + return { key: '', value: '' }
255 } 279 }
256 } 280 }
257 281
258 const status_info = computed(() => { 282 const status_info = computed(() => {
259 - return formatStatus(reserve_info.value?.status) || { key: '', value: '' } 283 + return formatStatus(reserve_info.value?.status) || { key: '', value: '' }
260 }) 284 })
261 285
262 /** 286 /**
...@@ -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(
282 - if (val) { 310 + is_pay_pending,
283 - start_countdown() 311 + val => {
284 - } else { 312 + if (val) {
285 - countdown_seconds.value = 0 313 + start_countdown()
286 - stop_countdown() 314 + } else {
287 - } 315 + countdown_seconds.value = 0
288 -}, { immediate: true }) 316 + stop_countdown()
317 + }
318 + },
319 + { immediate: true }
320 +)
289 321
290 onUnmounted(() => { 322 onUnmounted(() => {
291 stop_countdown() 323 stop_countdown()
...@@ -294,71 +326,73 @@ onUnmounted(() => { ...@@ -294,71 +326,73 @@ 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;
312 color: #333; 344 color: #333;
313 345
314 .status { 346 .status {
315 - font-size: 27rpx; 347 + font-size: 27rpx;
316 - font-weight: normal; 348 + font-weight: normal;
317 - padding: 4rpx 12rpx; 349 + padding: 4rpx 12rpx;
318 - border-radius: 8rpx; 350 + border-radius: 8rpx;
319 -
320 - &.offline {
321 - color: #999;
322 - background-color: #EEE;
323 - }
324 351
325 - &.success { 352 + &.offline {
326 - color: #A67939; 353 + color: #999;
327 - background-color: #FBEEDC; 354 + background-color: #eee;
328 - } 355 + }
329 - &.cancel { 356 +
330 - color: #999; 357 + &.success {
331 - background-color: #EEE; 358 + color: #a67939;
332 - } 359 + background-color: #fbeedc;
333 - &.used { 360 + }
334 - color: #477F3D; 361 + &.cancel {
335 - background-color: #E5EFE3; 362 + color: #999;
336 - } 363 + background-color: #eee;
364 + }
365 + &.used {
366 + color: #477f3d;
367 + background-color: #e5efe3;
368 + }
337 } 369 }
338 } 370 }
339 371
340 .booking-list-item-body { 372 .booking-list-item-body {
341 .booking-num { 373 .booking-num {
342 - display: flex; 374 + display: flex;
343 - justify-content: space-between; 375 + justify-content: space-between;
344 - align-items: center; 376 + align-items: center;
345 - margin-bottom: 16rpx; 377 + margin-bottom: 16rpx;
346 - color: #666; 378 + color: #666;
347 - 379 +
348 - .num-body { 380 + .num-body {
349 - span, text { 381 + span,
350 - color: #A67939;
351 - font-weight: bold;
352 - }
353 - }
354 - }
355 - .booking-price, .booking-time {
356 - color: #999;
357 - font-size: 29rpx;
358 - margin-bottom: 10rpx;
359 text { 382 text {
360 - color: #333; 383 + color: #a67939;
384 + font-weight: bold;
361 } 385 }
386 + }
387 + }
388 + .booking-price,
389 + .booking-time {
390 + color: #999;
391 + font-size: 29rpx;
392 + margin-bottom: 10rpx;
393 + text {
394 + color: #333;
395 + }
362 } 396 }
363 } 397 }
364 398
...@@ -369,7 +403,7 @@ onUnmounted(() => { ...@@ -369,7 +403,7 @@ onUnmounted(() => {
369 margin-top: 16rpx; 403 margin-top: 16rpx;
370 404
371 .countdown { 405 .countdown {
372 - color: #A67939; 406 + color: #a67939;
373 font-size: 28rpx; 407 font-size: 28rpx;
374 408
375 &.timeout { 409 &.timeout {
...@@ -380,8 +414,8 @@ onUnmounted(() => { ...@@ -380,8 +414,8 @@ onUnmounted(() => {
380 .repay-btn { 414 .repay-btn {
381 padding: 8rpx 20rpx; 415 padding: 8rpx 20rpx;
382 border-radius: 12rpx; 416 border-radius: 12rpx;
383 - background-color: #A67939; 417 + background-color: #a67939;
384 - color: #FFF; 418 + color: #fff;
385 font-size: 28rpx; 419 font-size: 28rpx;
386 } 420 }
387 } 421 }
......
1 -var getDaysInOneMonth = function (year, month) { 1 +const getDaysInOneMonth = function (year, month) {
2 - let _month = parseInt(month, 10); 2 + const _month = parseInt(month, 10)
3 - let d = new Date(year, _month, 0); 3 + const d = new Date(year, _month, 0)
4 - return d.getDate(); 4 + return d.getDate()
5 } 5 }
6 -var dateDate = function (date) { 6 +const dateDate = function (date) {
7 - let year = date && date.getFullYear(); 7 + const year = date && date.getFullYear()
8 - let month = date && date.getMonth() + 1; 8 + const month = date && date.getMonth() + 1
9 - let day = date && date.getDate(); 9 + const day = date && date.getDate()
10 - let hours = date && date.getHours(); 10 + const hours = date && date.getHours()
11 - let minutes = date && date.getMinutes(); 11 + const minutes = date && date.getMinutes()
12 return { 12 return {
13 - year, month, day, hours, minutes 13 + year,
14 + month,
15 + day,
16 + hours,
17 + minutes
14 } 18 }
15 } 19 }
16 -var dateTimePicker = function (startyear, endyear) { 20 +const dateTimePicker = function (startyear, endyear) {
17 // 获取date time 年份,月份,天数,小时,分钟推后30分 21 // 获取date time 年份,月份,天数,小时,分钟推后30分
18 - const years = []; 22 + const years = []
19 - const months = []; 23 + const months = []
20 - const hours = []; 24 + const hours = []
21 - const minutes = []; 25 + const minutes = []
22 for (let i = startyear; i <= endyear; i++) { 26 for (let i = startyear; i <= endyear; i++) {
23 years.push({ 27 years.push({
24 - name: i + '年', 28 + name: `${i}年`,
25 id: i 29 id: i
26 - }); 30 + })
27 } 31 }
28 //获取月份 32 //获取月份
29 for (let i = 1; i <= 12; i++) { 33 for (let i = 1; i <= 12; i++) {
30 if (i < 10) { 34 if (i < 10) {
31 - i = "0" + i; 35 + i = `0${i}`
32 } 36 }
33 months.push({ 37 months.push({
34 - name: i + '月', 38 + name: `${i}月`,
35 id: i 39 id: i
36 - }); 40 + })
37 } 41 }
38 //获取小时 42 //获取小时
39 for (let i = 0; i < 24; i++) { 43 for (let i = 0; i < 24; i++) {
40 if (i < 10) { 44 if (i < 10) {
41 - i = "0" + i; 45 + i = `0${i}`
42 } 46 }
43 hours.push({ 47 hours.push({
44 - name: i + '时', 48 + name: `${i}时`,
45 id: i 49 id: i
46 - }); 50 + })
47 } 51 }
48 //获取分钟 52 //获取分钟
49 for (let i = 0; i < 60; i++) { 53 for (let i = 0; i < 60; i++) {
50 if (i < 10) { 54 if (i < 10) {
51 - i = "0" + i; 55 + i = `0${i}`
52 } 56 }
53 minutes.push({ 57 minutes.push({
54 - name: i + '分', 58 + name: `${i}分`,
55 id: i 59 id: i
56 - }); 60 + })
57 } 61 }
58 return function (_year, _month) { 62 return function (_year, _month) {
59 - const days = []; 63 + const days = []
60 - _year = parseInt(_year); 64 + _year = parseInt(_year)
61 - _month = parseInt(_month); 65 + _month = parseInt(_month)
62 //获取日期 66 //获取日期
63 for (let i = 1; i <= getDaysInOneMonth(_year, _month); i++) { 67 for (let i = 1; i <= getDaysInOneMonth(_year, _month); i++) {
64 if (i < 10) { 68 if (i < 10) {
65 - i = "0" + i; 69 + i = `0${i}`
66 } 70 }
67 days.push({ 71 days.push({
68 - name: i + '日', 72 + name: `${i}日`,
69 id: i 73 id: i
70 - }); 74 + })
71 } 75 }
72 - return [years, months, days, hours, minutes]; 76 + return [years, months, days, hours, minutes]
73 } 77 }
74 } 78 }
75 -export { 79 +export { dateTimePicker, getDaysInOneMonth, dateDate }
76 - dateTimePicker,
77 - getDaysInOneMonth,
78 - dateDate
79 -}
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
...@@ -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
......
This diff is collapsed. Click to expand it.
1 export default { 1 export default {
2 navigationBarTitleText: '授权页', 2 navigationBarTitleText: '授权页',
3 - usingComponents: { 3 + usingComponents: {}
4 - },
5 } 4 }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
8 <template> 8 <template>
9 <view class="auth-page"> 9 <view class="auth-page">
10 <view class="loading"> 10 <view class="loading">
11 - <view>正在授权登录...</view> 11 + <view>正在授权登录...</view>
12 </view> 12 </view>
13 </view> 13 </view>
14 </template> 14 </template>
...@@ -22,41 +22,47 @@ let has_shown_fail_modal = false ...@@ -22,41 +22,47 @@ 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 - const now = Date.now() 26 + return
27 - if (now - last_try_at < 1200) return 27 + }
28 - last_try_at = now 28 + const now = Date.now()
29 + if (now - last_try_at < 1200) {
30 + return
31 + }
32 + last_try_at = now
29 33
30 - /** 34 + /**
31 - * 尝试静默授权 35 + * 尝试静默授权
32 - * - 授权成功后回跳到来源页 36 + * - 授权成功后回跳到来源页
33 - * - 授权失败则跳转至授权页面 37 + * - 授权失败则跳转至授权页面
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) {
40 - has_shown_fail_modal = true 44 + return
41 - await Taro.showModal({ 45 + }
42 - title: '提示', 46 + has_shown_fail_modal = true
43 - content: error?.message || '授权失败,请稍后再尝试', 47 + await Taro.showModal({
44 - showCancel: false, 48 + title: '提示',
45 - confirmText: '我知道了', 49 + content: error?.message || '授权失败,请稍后再尝试',
46 - }) 50 + showCancel: false,
51 + confirmText: '我知道了'
47 }) 52 })
53 + })
48 }) 54 })
49 </script> 55 </script>
50 56
51 <style lang="less"> 57 <style lang="less">
52 .auth-page { 58 .auth-page {
53 - min-height: 100vh; 59 + min-height: 100vh;
54 - display: flex; 60 + display: flex;
55 - align-items: center; 61 + align-items: center;
56 - justify-content: center; 62 + justify-content: center;
57 - .loading { 63 + .loading {
58 - text-align: center; 64 + text-align: center;
59 - color: #999; 65 + color: #999;
60 - } 66 + }
61 } 67 }
62 </style> 68 </style>
......
This diff is collapsed. Click to expand it.
...@@ -7,12 +7,14 @@ ...@@ -7,12 +7,14 @@
7 --> 7 -->
8 <template> 8 <template>
9 <view class="booking-code-page"> 9 <view class="booking-code-page">
10 - <view style="padding: 32rpx;"> 10 + <view style="padding: 32rpx">
11 <qrCode ref="qr_code_ref"></qrCode> 11 <qrCode ref="qr_code_ref"></qrCode>
12 <view class="warning"> 12 <view class="warning">
13 - <view style="display: flex; align-items: center; justify-content: center;"><IconFont name="tips" /><text style="margin-left: 10rpx;">温馨提示</text></view> 13 + <view style="display: flex; align-items: center; justify-content: center"
14 - <view style="margin-top: 16rpx;">一人一码,扫码或识别身份证成功后进入</view> 14 + ><IconFont name="tips" /><text style="margin-left: 10rpx">温馨提示</text></view
15 - <view style="height: 256rpx;"></view> 15 + >
16 + <view style="margin-top: 16rpx">一人一码,扫码或识别身份证成功后进入</view>
17 + <view style="height: 256rpx"></view>
16 </view> 18 </view>
17 </view> 19 </view>
18 <indexNav 20 <indexNav
...@@ -28,7 +30,7 @@ ...@@ -28,7 +30,7 @@
28 <script setup> 30 <script setup>
29 import { ref } from 'vue' 31 import { ref } from 'vue'
30 import Taro, { useDidShow, useDidHide } from '@tarojs/taro' 32 import Taro, { useDidShow, useDidHide } from '@tarojs/taro'
31 -import qrCode from '@/components/qrCode'; 33 +import qrCode from '@/components/qrCode'
32 import { IconFont } from '@nutui/icons-vue-taro' 34 import { IconFont } from '@nutui/icons-vue-taro'
33 import indexNav from '@/components/indexNav.vue' 35 import indexNav from '@/components/indexNav.vue'
34 import icon_3 from '@/assets/images/首页01@2x.png' 36 import icon_3 from '@/assets/images/首页01@2x.png'
...@@ -42,49 +44,53 @@ import { get_weak_network_modal_no_cache_options } from '@/utils/uiText' ...@@ -42,49 +44,53 @@ import { get_weak_network_modal_no_cache_options } from '@/utils/uiText'
42 const qr_code_ref = ref(null) 44 const qr_code_ref = ref(null)
43 45
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' })
53 - return 57 + return
54 - } 58 + }
55 59
56 - try { 60 + try {
57 - await Taro.showModal(get_weak_network_modal_no_cache_options()) 61 + await Taro.showModal(get_weak_network_modal_no_cache_options())
58 - } catch (e) { 62 + } catch (e) {
59 - console.error('show weak network modal failed:', e) 63 + console.error('show weak network modal failed:', e)
60 - } 64 + }
61 - Taro.redirectTo({ url: '/pages/index/index' }) 65 + Taro.redirectTo({ url: '/pages/index/index' })
62 - }, 66 + },
63 - fail: async () => { 67 + fail: async () => {
64 - if (has_offline_booking_cache()) { 68 + if (has_offline_booking_cache()) {
65 - Taro.redirectTo({ url: '/pages/offlineBookingList/index' }) 69 + Taro.redirectTo({ url: '/pages/offlineBookingList/index' })
66 - return 70 + return
67 - } 71 + }
68 - try { 72 + try {
69 - await Taro.showModal(get_weak_network_modal_no_cache_options()) 73 + await Taro.showModal(get_weak_network_modal_no_cache_options())
70 - } catch (e) { 74 + } catch (e) {
71 - console.error('show weak network modal failed:', e) 75 + console.error('show weak network modal failed:', e)
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 /**
...@@ -75,7 +78,7 @@ const CodeStatus = { ...@@ -75,7 +78,7 @@ const CodeStatus = {
75 * @returns {string} 状态文案 78 * @returns {string} 状态文案
76 */ 79 */
77 const qrCodeStatusText = computed(() => { 80 const qrCodeStatusText = computed(() => {
78 - return get_bill_status_text(billInfo.value?.status) 81 + return get_bill_status_text(billInfo.value?.status)
79 }) 82 })
80 83
81 /** 84 /**
...@@ -84,99 +87,99 @@ const qrCodeStatusText = computed(() => { ...@@ -84,99 +87,99 @@ const qrCodeStatusText = computed(() => {
84 * @returns {Promise<void>} 无返回值 87 * @returns {Promise<void>} 无返回值
85 */ 88 */
86 const cancelBooking = async () => { 89 const cancelBooking = async () => {
87 - const { confirm } = await Taro.showModal({ 90 + const { confirm } = await Taro.showModal({
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 - }
106 } 108 }
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 - }
119 } 121 }
122 + }
120 }) 123 })
121 124
122 useDidHide(() => { 125 useDidHide(() => {
123 - qr_code_ref.value?.stop_polling?.() 126 + qr_code_ref.value?.stop_polling?.()
124 }) 127 })
125 </script> 128 </script>
126 129
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;
142 - justify-content: space-between; 145 + justify-content: space-between;
143 - margin-bottom: 26rpx; 146 + margin-bottom: 26rpx;
144 - color: #333; 147 + color: #333;
145 - font-size: 30rpx; 148 + font-size: 30rpx;
146 - 149 +
147 - &:last-child { 150 + &:last-child {
148 - margin-bottom: 0; 151 + margin-bottom: 0;
149 - } 152 + }
150 - 153 +
151 - view:first-child { 154 + view:first-child {
152 - color: #999; 155 + color: #999;
153 - width: 160rpx; 156 + width: 160rpx;
154 - } 157 + }
155 - view:last-child { 158 + view:last-child {
156 - flex: 1; 159 + flex: 1;
157 - text-align: right; 160 + text-align: right;
158 - } 161 + }
159 - }
160 } 162 }
161 - 163 + }
162 - .cancel-wrapper { 164 +
163 - position: fixed; 165 + .cancel-wrapper {
164 - bottom: 0; 166 + position: fixed;
165 - left: 0; 167 + bottom: 0;
166 - width: 750rpx; 168 + left: 0;
167 - background-color: #FFF; 169 + width: 750rpx;
168 - padding: 32rpx; 170 + background-color: #fff;
169 - box-sizing: border-box; 171 + padding: 32rpx;
170 - 172 + box-sizing: border-box;
171 - .cancel-btn { 173 +
172 - background-color: #FFF; 174 + .cancel-btn {
173 - color: #A67939; 175 + background-color: #fff;
174 - border: 2rpx solid #A67939; 176 + color: #a67939;
175 - text-align: center; 177 + border: 2rpx solid #a67939;
176 - padding: 26rpx 0; 178 + text-align: center;
177 - border-radius: 16rpx; 179 + padding: 26rpx 0;
178 - font-size: 35rpx; 180 + border-radius: 16rpx;
179 - } 181 + font-size: 35rpx;
180 } 182 }
183 + }
181 } 184 }
182 </style> 185 </style>
......
...@@ -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 - }
72 } 80 }
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,9 +104,9 @@ useReachBottom(() => { ...@@ -95,9 +104,9 @@ 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 }
102 } 111 }
103 } 112 }
......
...@@ -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,26 +49,28 @@ const billInfo = ref({}) ...@@ -35,26 +49,28 @@ 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
49 - const { code, data } = await onAuthBillInfoAPI({ order_id: out_trade_no }) 65 + const { code, data } = await onAuthBillInfoAPI({ order_id: out_trade_no })
50 - if (code && data) { 66 + if (code && data) {
51 - data.datetime = data && formatDatetime(data) 67 + data.datetime = data && formatDatetime(data)
52 - billInfo.value = data 68 + billInfo.value = data
53 - } else { 69 + } else {
54 - // Handle error if needed 70 + // Handle error if needed
55 - } 71 + }
56 } catch (e) { 72 } catch (e) {
57 - console.error(e) 73 + console.error(e)
58 } 74 }
59 } 75 }
60 76
...@@ -63,51 +79,51 @@ const returnMerchant = () => { ...@@ -63,51 +79,51 @@ const returnMerchant = () => {
63 } 79 }
64 80
65 onMounted(() => { 81 onMounted(() => {
66 - getBillInfo() 82 + getBillInfo()
67 }) 83 })
68 </script> 84 </script>
69 85
70 <style lang="less"> 86 <style lang="less">
71 .callback-page { 87 .callback-page {
72 - padding: 32rpx; 88 + padding: 32rpx;
73 - background: #fff; 89 + background: #fff;
74 - min-height: 100vh; 90 + min-height: 100vh;
75 91
76 - .text-prompts { 92 + .text-prompts {
77 - display: flex; 93 + display: flex;
78 - flex-direction: column; 94 + flex-direction: column;
79 - align-items: center; 95 + align-items: center;
80 - margin-bottom: 64rpx; 96 + margin-bottom: 64rpx;
81 - padding-top: 64rpx; 97 + padding-top: 64rpx;
82 98
83 - .status-icon { 99 + .status-icon {
84 - width: 200rpx; 100 + width: 200rpx;
85 - height: 200rpx; 101 + height: 200rpx;
86 - } 102 + }
87 103
88 - .text { 104 + .text {
89 - margin-top: 32rpx; 105 + margin-top: 32rpx;
90 - font-size: 38rpx; 106 + font-size: 38rpx;
91 - color: #333; 107 + color: #333;
92 - }
93 } 108 }
109 + }
94 110
95 - .appointment-information { 111 + .appointment-information {
96 - background: #f8f8f8; 112 + background: #f8f8f8;
97 - padding: 32rpx; 113 + padding: 32rpx;
98 - border-radius: 16rpx; 114 + border-radius: 16rpx;
99 115
100 - .info-item { 116 + .info-item {
101 - margin-bottom: 16rpx; 117 + margin-bottom: 16rpx;
102 - font-size: 29rpx; 118 + font-size: 29rpx;
103 - color: #666; 119 + color: #666;
104 120
105 - text { 121 + text {
106 - color: #333; 122 + color: #333;
107 - font-weight: 500; 123 + font-weight: 500;
108 - margin-left: 16rpx; 124 + margin-left: 16rpx;
109 - } 125 + }
110 - }
111 } 126 }
127 + }
112 } 128 }
113 </style> 129 </style>
......
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>
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
2 * index页面样式 2 * index页面样式
3 */ 3 */
4 .index { 4 .index {
5 - padding: 40rpx; 5 + padding: 40rpx;
6 - 6 +
7 - .nut-button { 7 + .nut-button {
8 - margin-bottom: 40rpx; 8 + margin-bottom: 40rpx;
9 - } 9 + }
10 } 10 }
......
...@@ -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 = [
82 - icon: icon_booking, 93 + {
83 - name: '预约记录', 94 + icon: icon_booking,
84 - to: '/pages/bookingList/index' 95 + name: '预约记录',
85 -}, { 96 + to: '/pages/bookingList/index'
86 - icon: icon_visitor, 97 + },
87 - name: '参观者', 98 + {
88 - to: '/pages/visitorList/index' 99 + icon: icon_visitor,
89 -}, { 100 + name: '参观者',
90 - icon: icon_invite, 101 + to: '/pages/visitorList/index'
91 - name: '邀请码', 102 + },
92 - to: '/pages/search/index' 103 + {
93 -}] 104 + icon: icon_invite,
105 + name: '邀请码',
106 + to: '/pages/search/index'
107 + }
108 +]
94 </script> 109 </script>
95 110
96 <style lang="less"> 111 <style lang="less">
97 .my-page { 112 .my-page {
98 position: relative; 113 position: relative;
99 min-height: 100vh; 114 min-height: 100vh;
100 - background-color: #F6F6F6; 115 + background-color: #f6f6f6;
101 padding: 32rpx; 116 padding: 32rpx;
102 117
103 .my-item { 118 .my-item {
104 padding: 32rpx; 119 padding: 32rpx;
105 display: flex; 120 display: flex;
106 - justify-content:space-between; 121 + justify-content: space-between;
107 align-items: center; 122 align-items: center;
108 margin-bottom: 32rpx; 123 margin-bottom: 32rpx;
109 - background-color: #FFF; 124 + background-color: #fff;
110 border-radius: 10rpx; 125 border-radius: 10rpx;
111 .left { 126 .left {
112 - color: #A67939; 127 + color: #a67939;
113 display: flex; 128 display: flex;
114 align-items: center; 129 align-items: center;
115 } 130 }
......
1 export default { 1 export default {
2 - navigationBarTitleText: 'NFC测试', 2 + navigationBarTitleText: 'NFC测试'
3 } 3 }
......
This diff is collapsed. Click to expand it.
...@@ -8,18 +8,20 @@ ...@@ -8,18 +8,20 @@
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">
20 <nut-checkbox-group v-model="checked"> 22 <nut-checkbox-group v-model="checked">
21 <nut-checkbox label="1" icon-size="32rpx"> 23 <nut-checkbox label="1" icon-size="32rpx">
22 - <text style="color: #a67939; font-size: 32rpx">我已阅读并同意以上内容</text> 24 + <text style="color: #a67939; font-size: 32rpx">我已阅读并同意以上内容</text>
23 </nut-checkbox> 25 </nut-checkbox>
24 </nut-checkbox-group> 26 </nut-checkbox-group>
25 <view @tap="confirmBtn" class="confirm-btn">确认,下一步</view> 27 <view @tap="confirmBtn" class="confirm-btn">确认,下一步</view>
...@@ -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;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
6 * @Description: 线下预约码页面 6 * @Description: 线下预约码页面
7 --> 7 -->
8 <template> 8 <template>
9 - <view class="offline-booking-code-page"></view> 9 + <view class="offline-booking-code-page"></view>
10 </template> 10 </template>
11 11
12 <script setup> 12 <script setup>
...@@ -14,18 +14,17 @@ import { onMounted } from 'vue' ...@@ -14,18 +14,17 @@ 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">
28 .offline-booking-code-page { 27 .offline-booking-code-page {
29 - min-height: 100vh; 28 + min-height: 100vh;
30 } 29 }
31 </style> 30 </style>
......
1 export default { 1 export default {
2 - navigationBarTitleText: '离线预约详情' 2 + navigationBarTitleText: '离线预约详情'
3 } 3 }
4 -
......
1 <template> 1 <template>
2 - <view class="offline-booking-detail-page"> 2 + <view class="offline-booking-detail-page">
3 - <view class="header-tip"> 3 + <view class="header-tip">
4 - <IconFont name="tips" size="15" color="#A67939" />&nbsp; 4 + <IconFont name="tips" size="15" color="#A67939" />&nbsp;
5 - <text>您当前处于离线模式,仅展示本地缓存的数据</text> 5 + <text>您当前处于离线模式,仅展示本地缓存的数据</text>
6 - </view> 6 + </view>
7 +
8 + <view class="content">
9 + <offlineQrCode :list="qr_list" />
7 10
8 - <view class="content"> 11 + <view v-if="bill_info && bill_info.pay_id" class="detail-wrapper">
9 - <offlineQrCode :list="qr_list" /> 12 + <view class="detail-item">
10 - 13 + <view>参访时间:</view>
11 - <view v-if="bill_info && bill_info.pay_id" class="detail-wrapper"> 14 + <view>{{ bill_info.datetime }}</view>
12 - <view class="detail-item"> 15 + </view>
13 - <view>参访时间:</view> 16 + <view class="detail-item">
14 - <view>{{ bill_info.datetime }}</view> 17 + <view>参访人数:</view>
15 - </view> 18 + <view>{{ bill_info.total_qty }} 人</view>
16 - <view class="detail-item"> 19 + </view>
17 - <view>参访人数:</view> 20 + <view class="detail-item">
18 - <view>{{ bill_info.total_qty }} 人</view> 21 + <view>支付金额:</view>
19 - </view> 22 + <view>¥ {{ bill_info.total_amt }}</view>
20 - <view class="detail-item"> 23 + </view>
21 - <view>支付金额:</view> 24 + <view class="detail-item">
22 - <view>¥ {{ bill_info.total_amt }}</view> 25 + <view>下单时间:</view>
23 - </view> 26 + <view>{{ bill_info.order_time }}</view>
24 - <view class="detail-item"> 27 + </view>
25 - <view>下单时间:</view> 28 + <view class="detail-item">
26 - <view>{{ bill_info.order_time }}</view> 29 + <view>订单编号:</view>
27 - </view> 30 + <view>{{ bill_info.pay_id }}</view>
28 - <view class="detail-item"> 31 + </view>
29 - <view>订单编号:</view> 32 + <!-- <view class="detail-item">
30 - <view>{{ bill_info.pay_id }}</view>
31 - </view>
32 - <!-- <view class="detail-item">
33 <view>订单状态:</view> 33 <view>订单状态:</view>
34 <view>{{ status_text }}</view> 34 <view>{{ status_text }}</view>
35 </view> --> 35 </view> -->
36 - </view> 36 + </view>
37 - </view> 37 + </view>
38 38
39 - <view class="action-area"> 39 + <view class="action-area">
40 - <button class="back-btn" @tap="toList">返回列表</button> 40 + <button class="back-btn" @tap="toList">返回列表</button>
41 - </view>
42 </view> 41 </view>
42 + </view>
43 </template> 43 </template>
44 44
45 <script setup> 45 <script setup>
...@@ -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)
...@@ -78,95 +81,95 @@ const qr_list = ref([]) ...@@ -78,95 +81,95 @@ const qr_list = ref([])
78 // }) 81 // })
79 82
80 const toList = () => { 83 const toList = () => {
81 - Taro.navigateBack({ 84 + Taro.navigateBack({
82 - fail: () => { 85 + fail: () => {
83 - Taro.reLaunch({ url: '/pages/offlineBookingList/index' }) 86 + Taro.reLaunch({ url: '/pages/offlineBookingList/index' })
84 - } 87 + }
85 - }) 88 + })
86 } 89 }
87 90
88 const load_cache = () => { 91 const load_cache = () => {
89 - const pay_id = router.params.pay_id 92 + const pay_id = router.params.pay_id
90 - const data = get_offline_booking_by_pay_id(pay_id) 93 + const data = get_offline_booking_by_pay_id(pay_id)
91 - if (!data) { 94 + if (!data) {
92 - Taro.showToast({ title: '本地无该订单缓存', icon: 'none' }) 95 + Taro.showToast({ title: '本地无该订单缓存', icon: 'none' })
93 - Taro.reLaunch({ url: '/pages/offlineBookingList/index' }) 96 + Taro.reLaunch({ url: '/pages/offlineBookingList/index' })
94 - return 97 + return
95 - } 98 + }
96 - bill_info.value = data 99 + bill_info.value = data
97 - qr_list.value = build_offline_qr_list(data) 100 + qr_list.value = build_offline_qr_list(data)
98 } 101 }
99 102
100 useDidShow(() => { 103 useDidShow(() => {
101 - load_cache() 104 + load_cache()
102 }) 105 })
103 </script> 106 </script>
104 107
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;
120 + }
121 +
122 + .content {
123 + padding: 32rpx;
124 + padding-bottom: 180rpx;
125 + }
126 +
127 + .detail-wrapper {
128 + background-color: #fff;
129 + border-radius: 16rpx;
130 + padding: 32rpx;
131 + margin-top: 32rpx;
132 + box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.1);
133 +
134 + .detail-item {
135 + display: flex;
136 + justify-content: space-between;
137 + margin-bottom: 26rpx;
138 + color: #333;
139 + font-size: 30rpx;
140 +
141 + &:last-child {
142 + margin-bottom: 0;
143 + }
144 +
145 + view:first-child {
146 + color: #999;
147 + width: 160rpx;
148 + }
149 + view:last-child {
150 + flex: 1;
151 + text-align: right;
152 + }
117 } 153 }
118 - 154 + }
119 - .content { 155 +
120 - padding: 32rpx; 156 + .action-area {
121 - padding-bottom: 180rpx; 157 + position: fixed;
122 - } 158 + bottom: 0;
123 - 159 + left: 0;
124 - .detail-wrapper { 160 + width: 750rpx;
125 - background-color: #FFF; 161 + padding: 24rpx 32rpx;
126 - border-radius: 16rpx; 162 + background: #fff;
127 - padding: 32rpx; 163 + box-sizing: border-box;
128 - margin-top: 32rpx; 164 + box-shadow: 0 -10rpx 8rpx 0 rgba(0, 0, 0, 0.06);
129 - box-shadow: 0 0 29rpx 0 rgba(106,106,106,0.1); 165 +
130 - 166 + .back-btn {
131 - .detail-item { 167 + background-color: #a67939;
132 - display: flex; 168 + color: #fff;
133 - justify-content: space-between; 169 + border-radius: 16rpx;
134 - margin-bottom: 26rpx; 170 + font-size: 32rpx;
135 - color: #333; 171 + padding: 12rpx 0;
136 - font-size: 30rpx;
137 -
138 - &:last-child {
139 - margin-bottom: 0;
140 - }
141 -
142 - view:first-child {
143 - color: #999;
144 - width: 160rpx;
145 - }
146 - view:last-child {
147 - flex: 1;
148 - text-align: right;
149 - }
150 - }
151 - }
152 -
153 - .action-area {
154 - position: fixed;
155 - bottom: 0;
156 - left: 0;
157 - width: 750rpx;
158 - padding: 24rpx 32rpx;
159 - background: #FFF;
160 - box-sizing: border-box;
161 - box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.06);
162 -
163 - .back-btn {
164 - background-color: #A67939;
165 - color: #FFF;
166 - border-radius: 16rpx;
167 - font-size: 32rpx;
168 - padding: 12rpx 0;
169 - }
170 } 172 }
173 + }
171 } 174 }
172 </style> 175 </style>
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.