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