Ver código fonte

基础架构+散户加气3.1

chenlei 1 ano atrás
pai
commit
13b04ff92e
100 arquivos alterados com 32937 adições e 2 exclusões
  1. 106 0
      .commitlintrc.cjs
  2. 13 0
      .editorconfig
  3. 1 0
      .eslintignore
  4. 98 0
      .eslintrc-auto-import.json
  5. 97 0
      .eslintrc.cjs
  6. 39 0
      .gitignore
  7. 6 0
      .npmrc
  8. 9 0
      .prettierignore
  9. 19 0
      .prettierrc.cjs
  10. 1 0
      .stylelintignore
  11. 58 0
      .stylelintrc.cjs
  12. 17 0
      .vscode/extensions.json
  13. 15 0
      .vscode/launch.json
  14. 65 0
      .vscode/settings.json
  15. 56 0
      .vscode/vue3.code-snippets
  16. 60 2
      README.md
  17. 15 0
      env/.env
  18. 11 0
      env/.env.development
  19. 8 0
      env/.env.production
  20. 6 0
      env/.env.test
  21. BIN
      favicon.ico
  22. 28 0
      index.html
  23. 135 0
      manifest.config.ts
  24. 149 0
      package.json
  25. 63 0
      pages.config.ts
  26. 12074 0
      pnpm-lock.yaml
  27. 91 0
      scripts/common.js
  28. 276 0
      scripts/getInterFace.js
  29. 36 0
      scripts/postupgrade.js
  30. 12 0
      src/App.vue
  31. 344 0
      src/components/business/carNumber.vue
  32. 91 0
      src/components/business/station/index.vue
  33. 21 0
      src/components/container/index.vue
  34. 117 0
      src/components/flowLine/index.vue
  35. 58 0
      src/components/pull/index.vue
  36. 175 0
      src/components/skeletons/index.vue
  37. 11 0
      src/directives/shortcutKeys/index.ts
  38. 80 0
      src/enums/index.ts
  39. 31 0
      src/env.d.ts
  40. 2 0
      src/interceptors/index.ts
  41. 22 0
      src/interceptors/prototype.ts
  42. 26 0
      src/interceptors/route.ts
  43. 31 0
      src/main.ts
  44. 111 0
      src/manifest.json
  45. 114 0
      src/pages.json
  46. 52 0
      src/pages/account/index.vue
  47. 56 0
      src/pages/createOrder/index.vue
  48. 534 0
      src/pages/index/index.vue
  49. 64 0
      src/pages/list/index.vue
  50. 150 0
      src/pages/login/index.vue
  51. 303 0
      src/pages/orderList/index.vue
  52. 27 0
      src/pages/personCenter/index.vue
  53. 222 0
      src/pages/prePay/index.vue
  54. 14 0
      src/pages/webview/index.vue
  55. 23 0
      src/pages/webview/login.vue
  56. 61 0
      src/pagesSubExample/index.vue
  57. 63 0
      src/pagesSubExample/list/index.vue
  58. 63 0
      src/pagesSubExample/login/components/login.vue
  59. 29 0
      src/pagesSubExample/login/components/upload.vue
  60. 60 0
      src/pagesSubExample/login/index.vue
  61. 16 0
      src/pagesSubExample/webview/index.vue
  62. BIN
      src/static/images/icons/card.png
  63. BIN
      src/static/images/icons/firm.png
  64. BIN
      src/static/images/icons/payhistory.png
  65. BIN
      src/static/images/icons/perpay.png
  66. BIN
      src/static/images/icons/turnk_number_head.png
  67. BIN
      src/static/images/qr@3x.png
  68. 11 0
      src/static/images/truck.svg
  69. BIN
      src/static/logo.png
  70. 33 0
      src/style/_variables.scss
  71. 246 0
      src/style/index.scss
  72. 171 0
      src/types/api.d.ts
  73. 277 0
      src/types/auto-import.d.ts
  74. 104 0
      src/types/components.ts
  75. 16 0
      src/types/global.d.ts
  76. 52 0
      src/types/page.d.ts
  77. 1079 0
      src/types/schemas/account.d.ts
  78. 793 0
      src/types/schemas/allinpay.d.ts
  79. 8 0
      src/types/schemas/custom.d.ts
  80. 1071 0
      src/types/schemas/gasdata.d.ts
  81. 576 0
      src/types/schemas/message.d.ts
  82. 1110 0
      src/types/schemas/pay.d.ts
  83. 1451 0
      src/types/schemas/settle.d.ts
  84. 5194 0
      src/types/schemas/strategy.d.ts
  85. 1124 0
      src/types/schemas/tms.d.ts
  86. 2369 0
      src/types/schemas/user.d.ts
  87. 46 0
      src/types/schemas/websocket.d.ts
  88. 8 0
      src/types/shims-uni.d.ts
  89. 77 0
      src/uni.scss
  90. 49 0
      src/utils/aop/index.ts
  91. 89 0
      src/utils/api/socket/stomp.ts
  92. 86 0
      src/utils/api/web/index.ts
  93. 31 0
      src/utils/api/web/request/afterReturning.ts
  94. 49 0
      src/utils/api/web/request/afterThrowing.ts
  95. 67 0
      src/utils/api/web/request/before.ts
  96. 31 0
      src/utils/api/web/request/com.ts
  97. 74 0
      src/utils/api/web/request/index.ts
  98. 11 0
      src/utils/api/web/request/preSetRAS.ts
  99. 99 0
      src/utils/config/index.ts
  100. 0 0
      src/utils/config/interFaces/account.ts

+ 106 - 0
.commitlintrc.cjs

@@ -0,0 +1,106 @@
+const fs = require('fs')
+const path = require('path')
+const { execSync } = require('child_process')
+
+const scopes = fs
+  .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
+  .filter((dirent) => dirent.isDirectory())
+  .map((dirent) => dirent.name.replace(/s$/, ''))
+
+// precomputed scope
+const scopeComplete = execSync('git status --porcelain || true')
+  .toString()
+  .trim()
+  .split('\n')
+  .find((r) => ~r.indexOf('M  src'))
+  ?.replace(/(\/)/g, '%%')
+  ?.match(/src%%((\w|-)*)/)?.[1]
+  ?.replace(/s$/, '')
+
+module.exports = {
+  ignores: [(commit) => commit.includes('init')],
+  extends: ['@commitlint/config-conventional'],
+  rules: {
+    'body-leading-blank': [2, 'always'],
+    'footer-leading-blank': [1, 'always'],
+    'header-max-length': [2, 'always', 108],
+    'subject-empty': [2, 'never'],
+    'type-empty': [2, 'never'],
+    'subject-case': [0],
+    'type-enum': [
+      2,
+      'always',
+      [
+        'feat',
+        'fix',
+        'perf',
+        'style',
+        'docs',
+        'test',
+        'refactor',
+        'build',
+        'ci',
+        'chore',
+        'revert',
+        'wip',
+        'workflow',
+        'types',
+        'release',
+      ],
+    ],
+  },
+  prompt: {
+    /** @use `pnpm commit :f` */
+    alias: {
+      f: 'docs: fix typos',
+      r: 'docs: update README',
+      s: 'style: update code format',
+      b: 'build: bump dependencies',
+      c: 'chore: update config',
+    },
+    customScopesAlign: !scopeComplete ? 'top' : 'bottom',
+    defaultScope: scopeComplete,
+    scopes: [...scopes, 'mock'],
+    allowEmptyIssuePrefixs: false,
+    allowCustomIssuePrefixs: false,
+
+    // English
+    typesAppend: [
+      { value: 'wip', name: 'wip:      work in process' },
+      { value: 'workflow', name: 'workflow: workflow improvements' },
+      { value: 'types', name: 'types:    type definition file changes' },
+    ],
+
+    // 中英文对照版
+    // messages: {
+    //   type: '选择你要提交的类型 :',
+    //   scope: '选择一个提交范围 (可选):',
+    //   customScope: '请输入自定义的提交范围 :',
+    //   subject: '填写简短精炼的变更描述 :\n',
+    //   body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
+    //   breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
+    //   footerPrefixsSelect: '选择关联issue前缀 (可选):',
+    //   customFooterPrefixs: '输入自定义issue前缀 :',
+    //   footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
+    //   confirmCommit: '是否提交或修改commit ?',
+    // },
+    // types: [
+    //   { value: 'feat', name: 'feat:     新增功能' },
+    //   { value: 'fix', name: 'fix:      修复缺陷' },
+    //   { value: 'docs', name: 'docs:     文档变更' },
+    //   { value: 'style', name: 'style:    代码格式' },
+    //   { value: 'refactor', name: 'refactor: 代码重构' },
+    //   { value: 'perf', name: 'perf:     性能优化' },
+    //   { value: 'test', name: 'test:     添加疏漏测试或已有测试改动' },
+    //   { value: 'build', name: 'build:    构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
+    //   { value: 'ci', name: 'ci:       修改 CI 配置、脚本' },
+    //   { value: 'revert', name: 'revert:   回滚 commit' },
+    //   { value: 'chore', name: 'chore:    对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
+    //   { value: 'wip', name: 'wip:      正在开发中' },
+    //   { value: 'workflow', name: 'workflow: 工作流程改进' },
+    //   { value: 'types', name: 'types:    类型定义文件修改' },
+    // ],
+    // emptyScopesAlias: 'empty:      不填写',
+    // customScopesAlias: 'custom:     自定义',
+  },
+}

+ 13 - 0
.editorconfig

@@ -0,0 +1,13 @@
+root = true
+
+[*] # 表示所有文件适用
+charset = utf-8 # 设置文件字符集为 utf-8
+indent_style = space # 缩进风格(tab | space)
+indent_size = 2 # 缩进大小
+end_of_line = lf # 控制换行类型(lf | cr | crlf)
+trim_trailing_whitespace = true # 去除行首的任意空白字符
+insert_final_newline = true # 始终在文件末尾插入一个新行
+
+[*.md] # 表示仅 md 文件适用以下规则
+max_line_length = off # 关闭最大行长度限制
+trim_trailing_whitespace = false # 关闭末尾空格修剪

+ 1 - 0
.eslintignore

@@ -0,0 +1 @@
+src/uni_modules/

+ 98 - 0
.eslintrc-auto-import.json

@@ -0,0 +1,98 @@
+{
+  "globals": {
+    "Component": true,
+    "ComponentPublicInstance": true,
+    "ComputedRef": true,
+    "EffectScope": true,
+    "ExtractDefaultPropTypes": true,
+    "ExtractPropTypes": true,
+    "ExtractPublicPropTypes": true,
+    "InjectionKey": true,
+    "PropType": true,
+    "Ref": true,
+    "VNode": true,
+    "WritableComputedRef": true,
+    "ay": true,
+    "computed": true,
+    "config": true,
+    "createApp": true,
+    "customRef": true,
+    "defineAsyncComponent": true,
+    "defineComponent": true,
+    "effectScope": true,
+    "enums": true,
+    "getCurrentInstance": true,
+    "getCurrentScope": true,
+    "h": true,
+    "inject": true,
+    "isProxy": true,
+    "isReactive": true,
+    "isReadonly": true,
+    "isRef": true,
+    "markRaw": true,
+    "nextTick": true,
+    "onActivated": true,
+    "onAddToFavorites": true,
+    "onBackPress": true,
+    "onBeforeMount": true,
+    "onBeforeUnmount": true,
+    "onBeforeUpdate": true,
+    "onDeactivated": true,
+    "onError": true,
+    "onErrorCaptured": true,
+    "onHide": true,
+    "onLaunch": true,
+    "onLoad": true,
+    "onMounted": true,
+    "onNavigationBarButtonTap": true,
+    "onNavigationBarSearchInputChanged": true,
+    "onNavigationBarSearchInputClicked": true,
+    "onNavigationBarSearchInputConfirmed": true,
+    "onNavigationBarSearchInputFocusChanged": true,
+    "onPageNotFound": true,
+    "onPageScroll": true,
+    "onPullDownRefresh": true,
+    "onReachBottom": true,
+    "onReady": true,
+    "onRenderTracked": true,
+    "onRenderTriggered": true,
+    "onResize": true,
+    "onScopeDispose": true,
+    "onServerPrefetch": true,
+    "onShareAppMessage": true,
+    "onShareTimeline": true,
+    "onShow": true,
+    "onTabItemTap": true,
+    "onThemeChange": true,
+    "onUnhandledRejection": true,
+    "onUnload": true,
+    "onUnmounted": true,
+    "onUpdated": true,
+    "provide": true,
+    "reactive": true,
+    "readonly": true,
+    "ref": true,
+    "resolveComponent": true,
+    "shallowReactive": true,
+    "shallowReadonly": true,
+    "shallowRef": true,
+    "store": true,
+    "toRaw": true,
+    "toRef": true,
+    "toRefs": true,
+    "toValue": true,
+    "triggerRef": true,
+    "unref": true,
+    "useAttrs": true,
+    "useCssModule": true,
+    "useCssVars": true,
+    "useSlots": true,
+    "watch": true,
+    "watchEffect": true,
+    "watchPostEffect": true,
+    "watchSyncEffect": true,
+    "webapi": true,
+    "func": true,
+    "aop": true
+  }
+}

+ 97 - 0
.eslintrc.cjs

@@ -0,0 +1,97 @@
+module.exports = {
+  env: {
+    browser: true,
+    es2021: true,
+    node: true,
+  },
+  extends: [
+    'eslint:recommended',
+    'plugin:@typescript-eslint/recommended',
+    'plugin:vue/vue3-essential',
+    // eslint-plugin-import 插件, @see https://www.npmjs.com/package/eslint-plugin-import
+    'plugin:import/recommended',
+    // eslint-config-airbnb-base 插件 已经改用 eslint-config-standard 插件
+    'standard',
+    // 1. 接入 prettier 的规则
+    'prettier',
+    'plugin:prettier/recommended',
+    './.eslintrc-auto-import.json',
+  ],
+  overrides: [
+    {
+      env: {
+        node: true,
+      },
+      files: ['.eslintrc.{js,cjs}'],
+      parserOptions: {
+        sourceType: 'script',
+      },
+    },
+  ],
+  parserOptions: {
+    ecmaVersion: 'latest',
+    parser: '@typescript-eslint/parser',
+    sourceType: 'module',
+  },
+  plugins: [
+    '@typescript-eslint',
+    'vue',
+    // 2. 加入 prettier 的 eslint 插件
+    'prettier',
+    // eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript
+    'import',
+  ],
+  rules: {
+    // 3. 注意要加上这一句,开启 prettier 自动修复的功能
+    'prettier/prettier': 'error',
+    // turn on errors for missing imports
+    'import/no-unresolved': 'off',
+    // 对后缀的检测,否则 import 一个ts文件也会报错,需要手动添加'.ts', 增加了下面的配置后就不用了
+    'import/extensions': [
+      'error',
+      'ignorePackages',
+      { js: 'never', jsx: 'never', ts: 'never', tsx: 'never' },
+    ],
+    // 只允许1个默认导出,关闭,否则不能随意export xxx
+    'import/prefer-default-export': ['off'],
+    'no-console': ['off'],
+    // 'no-unused-vars': ['off'],
+    // '@typescript-eslint/no-unused-vars': ['off'],
+    // 解决vite.config.ts报错问题
+    'import/no-extraneous-dependencies': 'off',
+    'no-plusplus': 'off',
+    'no-shadow': 'off',
+    'vue/multi-word-component-names': 'off',
+    '@typescript-eslint/no-explicit-any': 'off',
+    'no-underscore-dangle': 'off',
+    'no-use-before-define': 'off',
+    'no-undef': 'off',
+    'no-unused-vars': 'off',
+    'no-param-reassign': 'off',
+    '@typescript-eslint/no-unused-vars': 'off',
+    // 避免 `eslint` 对于 `typescript` 函数重载的误报
+    'no-redeclare': 'off',
+    '@typescript-eslint/no-redeclare': 'error',
+  },
+  // eslint-import-resolver-typescript 插件,@see https://www.npmjs.com/package/eslint-import-resolver-typescript
+  settings: {
+    'import/parsers': {
+      '@typescript-eslint/parser': ['.ts', '.tsx'],
+    },
+    'import/resolver': {
+      typescript: {},
+    },
+  },
+  globals: {
+    $t: true,
+    uni: true,
+    UniApp: true,
+    wx: true,
+    WechatMiniprogram: true,
+    getCurrentPages: true,
+    UniHelper: true,
+    Page: true,
+    App: true,
+    NodeJS: true,
+  },
+}

+ 39 - 0
.gitignore

@@ -0,0 +1,39 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.DS_Store
+dist
+*.local
+
+# Editor directories and files
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+.hbuilderx
+temp
+
+.stylelintcache
+
+# lock 文件还是不要了,我主要的版本写死就好了
+# pnpm-lock.yaml
+# package-lock.json
+
+# TIPS:如果某些文件已经加入了版本管理,现在重新加入 .gitignore 是不生效的,需要执行下面的操作
+# `git rm -r --cached .` 然后提交 commit 即可。
+
+# git rm -r --cached file1 file2  ## 针对某些文件
+# git rm -r --cached dir1 dir2  ## 针对某些文件夹
+# git rm -r --cached .  ## 针对所有文件
+
+# 更新 uni-app 官方版本
+# npx @dcloudio/uvm@latest

+ 6 - 0
.npmrc

@@ -0,0 +1,6 @@
+# registry = https://registry.npmjs.org
+registry = https://registry.npmmirror.com
+
+strict-peer-dependencies=false
+auto-install-peers=true
+shamefully-hoist=true

+ 9 - 0
.prettierignore

@@ -0,0 +1,9 @@
+# unplugin-auto-import 生成的类型文件,每次提交都改变,所以加入这里吧,与 .gitignore 配合使用
+auto-import.d.ts
+
+# vite-plugin-uni-pages 生成的类型文件,每次切换分支都一堆不同的,所以直接 .gitignore
+uni-pages.d.ts
+
+# 插件生成的文件
+src/pages.json
+src/manifest.json

+ 19 - 0
.prettierrc.cjs

@@ -0,0 +1,19 @@
+// @see https://prettier.io/docs/en/options
+module.exports = {
+  singleQuote: true,
+  printWidth: 100,
+  tabWidth: 2,
+  useTabs: false,
+  semi: false,
+  trailingComma: 'all',
+  endOfLine: 'auto',
+  htmlWhitespaceSensitivity: 'ignore',
+  overrides: [
+    {
+      files: '*.json',
+      options: {
+        trailingComma: 'none',
+      },
+    },
+  ],
+}

+ 1 - 0
.stylelintignore

@@ -0,0 +1 @@
+src/uni_modules/

+ 58 - 0
.stylelintrc.cjs

@@ -0,0 +1,58 @@
+// .stylelintrc.cjs
+
+module.exports = {
+  root: true,
+  extends: [
+    // stylelint-config-standard 替换成了更宽松的 stylelint-config-recommended
+    'stylelint-config-recommended',
+    // stylelint-config-standard-scss 替换成了更宽松的 stylelint-config-recommended-scss
+    'stylelint-config-recommended-scss',
+    'stylelint-config-recommended-vue/scss',
+    'stylelint-config-html/vue',
+    'stylelint-config-recess-order',
+  ],
+  plugins: ['stylelint-prettier'],
+  overrides: [
+    // 扫描 .vue/html 文件中的<style>标签内的样式
+    {
+      files: ['**/*.{vue,html}'],
+      customSyntax: 'postcss-html',
+    },
+    {
+      files: ['**/*.{css,scss}'],
+      customSyntax: 'postcss-scss',
+    },
+  ],
+  // 自定义规则
+  rules: {
+    'prettier/prettier': true,
+    // 允许 global 、export 、v-deep等伪类
+    'selector-pseudo-class-no-unknown': [
+      true,
+      {
+        ignorePseudoClasses: ['global', 'export', 'v-deep', 'deep'],
+      },
+    ],
+    'unit-no-unknown': [
+      true,
+      {
+        ignoreUnits: ['rpx'],
+      },
+    ],
+    // 处理小程序page标签不认识的问题
+    'selector-type-no-unknown': [
+      true,
+      {
+        ignoreTypes: ['page'],
+      },
+    ],
+    'comment-empty-line-before': 'never', // never|always|always-multi-line|never-multi-line
+    'custom-property-empty-line-before': 'never',
+    'no-empty-source': null,
+    'comment-no-empty': null,
+    'no-duplicate-selectors': null,
+    'scss/comment-no-empty': null,
+    'selector-class-pattern': null,
+    'font-family-no-missing-generic-family-keyword': null,
+  },
+}

+ 17 - 0
.vscode/extensions.json

@@ -0,0 +1,17 @@
+{
+  "recommendations": [
+    "vue.volar",
+    "stylelint.vscode-stylelint",
+    "esbenp.prettier-vscode",
+    "dbaeumer.vscode-eslint",
+    "antfu.unocss",
+    "antfu.iconify",
+    "evils.uniapp-vscode",
+    "uni-helper.uni-helper-vscode",
+    "uni-helper.uni-app-schemas-vscode",
+    "uni-helper.uni-highlight-vscode",
+    "uni-helper.uni-ui-snippets-vscode",
+    "uni-helper.uni-app-snippets-vscode",
+    "mrmlnc.vscode-json5"
+  ]
+}

+ 15 - 0
.vscode/launch.json

@@ -0,0 +1,15 @@
+{
+    // 使用 IntelliSense 了解相关属性。 
+    // 悬停以查看现有属性的描述。
+    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "msedge",
+            "request": "launch",
+            "name": "针对 localhost 启动 Edge",
+            "url": "http://localhost:8080",
+            "webRoot": "${workspaceFolder}"
+        }
+    ]
+}

+ 65 - 0
.vscode/settings.json

@@ -0,0 +1,65 @@
+{
+  // 默认格式化工具选择prettier
+  "editor.defaultFormatter": "esbenp.prettier-vscode",
+  // 保存的时候自动格式化
+  "editor.formatOnSave": true,
+  //开启自动修复
+  "editor.codeActionsOnSave": {
+    "source.fixAll": "explicit",
+    "source.fixAll.eslint": "explicit",
+    "source.fixAll.stylelint": "explicit"
+  },
+  // 配置stylelint检查的文件类型范围
+  "stylelint.validate": ["css", "scss", "vue", "html"], // 与package.json的scripts对应
+  "stylelint.enable": true,
+  "css.validate": false,
+  "less.validate": false,
+  "scss.validate": false,
+  "[shellscript]": {
+    "editor.defaultFormatter": "foxundermoon.shell-format"
+  },
+  "[dotenv]": {
+    "editor.defaultFormatter": "foxundermoon.shell-format"
+  },
+  "[vue]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[typescript]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  "[jsonc]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
+  // 配置语言的文件关联
+  "files.associations": {
+    "pages.json": "jsonc", // pages.json 可以写注释
+    "manifest.json": "jsonc" // manifest.json 可以写注释
+  },
+  "cSpell.words": [
+    "climblee",
+    "commitlint",
+    "dcloudio",
+    "iconfont",
+    "qrcode",
+    "refresherrefresh",
+    "scrolltolower",
+    "tabbar",
+    "auyen-mobile",
+    "uvui",
+    "WechatMiniprogram"
+  ],
+  "typescript.tsdk": "node_modules\\typescript\\lib",
+  // 控制相关文件嵌套展示
+  "explorer.fileNesting.enabled": true,
+  "explorer.fileNesting.expand": false,
+  "explorer.fileNesting.patterns": {
+    "*.ts": "$(capture).test.ts, $(capture).test.tsx",
+    "*.tsx": "$(capture).test.ts, $(capture).test.tsx",
+    "*.env": "$(capture).env.*",
+    "CHANGELOG.md": "CHANGELOG*",
+    "package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,README*,.npmrc,.browserslistrc",
+    ".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*,.eslintrc-auto-import.json,.editorconfig,.commitlint.cjs",
+    "vite.config.ts": "tsconfig.*.json,uno.config.ts,tsconfig.json,uni-pages.d.ts,vitePlugin.ts",
+    "manifest.config.ts": "manifest.config.ts,pages.config.ts"
+  }
+}

+ 56 - 0
.vscode/vue3.code-snippets

@@ -0,0 +1,56 @@
+{
+  // Place your auyen-mobile 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
+  // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
+  // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
+  // used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
+  // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
+  // Placeholders with the same ids are connected.
+  // Example:
+  // "Print to console": {
+  // 	"scope": "javascript,typescript",
+  // 	"prefix": "log",
+  // 	"body": [
+  // 		"console.log('$1');",
+  // 		"$2"
+  // 	],
+  // 	"description": "Log output to console"
+  // }
+  "Print auyen-mobile Vue3 SFC": {
+    "scope": "vue",
+    "prefix": "v3",
+    "body": [
+      "<route lang=\"json5\" type=\"page\">",
+      "{",
+      "  layout: 'default',",
+      "  style: {",
+      "    navigationBarTitleText: '$1',",
+      "  },",
+      "}",
+      "</route>\n",
+      "<template>",
+      "  <view class=\"\">$2</view>",
+      "</template>\n",
+      "<script lang=\"ts\" setup>",
+      "//$3",
+      "</script>\n",
+      "<style lang=\"scss\" scoped>",
+      "//$4",
+      "</style>\n",
+    ],
+  },
+  "Print auyen-mobile style": {
+    "scope": "vue",
+    "prefix": "st",
+    "body": ["<style lang=\"scss\" scoped>", "//", "</style>\n"],
+  },
+  "Print auyen-mobile script": {
+    "scope": "vue",
+    "prefix": "sc",
+    "body": ["<script lang=\"ts\" setup>", "//$3", "</script>\n"],
+  },
+  "Print auyen-mobile template": {
+    "scope": "vue",
+    "prefix": "te",
+    "body": ["<template>", "  <view class=\"\">$1</view>", "</template>\n"],
+  },
+}

+ 60 - 2
README.md

@@ -1,3 +1,61 @@
-# mobile
+由 `uniapp` + `Vue3` + `Ts` + `Vite5` + `UnoCss` + `uni-ui` + `z-paging` 构成,使用了最新的前端技术栈,无需依靠 `HBuilderX`,通过命令行方式运行 `web`、`小程序` 和 `App`(编辑器推荐 `VSCode`,可选 `webstorm`)。
 
-移动端
+内置了 `页面底座`、`公共请求框架`、`公共状态中心`、 `配置中心`、`UnoCSS`、`i18n多语言` 等基础功能,提供了 `代码提示`、`自动格式化`、`接口信息一键导入`、`自动生成路由` 等辅助功能。
+
+## ⚙️ 环境
+
+- node>=18
+- pnpm>=7.30
+- 稳定版本:node = 20.7.0 pnpm = 9.4.0
+
+## &#x1F4C2; 快速开始
+
+执行 `pnpm i` 安装依赖
+
+?执行 `pnpm gif` 导入接口配置信息
+
+执行 `pnpm dev` 运行 `H5`
+
+## 📦 常见问题
+
+如果出现这类错误
+`uni-app 有新版本发布,请执行 `npx @dcloudio/uvm@latest alpha` 更新,更新日志详见:https://download1.dcloud.net.cn/hbuilderx/changelog/4.22.2024062415-alpha.html`
+
+执行 `pnpm uvm`
+
+## 📦 运行(支持热更新)
+
+- web平台: `pnpm dev:h5`, 然后打开 [http://localhost:9000/](http://localhost:9000/)。
+- weixin平台:`pnpm dev:mp-weixin` 然后打开微信开发者工具,导入本地文件夹,选择本项目的`dist/dev/mp-weixin` 文件。
+- APP平台:`pnpm dev:app`, 然后打开 `HBuilderX`,导入刚刚生成的`dist/dev/app` 文件夹,选择运行到模拟器(开发时优先使用),或者运行的安卓/ios基座。
+
+## 🔗 发布
+
+- web平台: `pnpm build:h5`,打包后的文件在 `dist/build/h5`,可以放到web服务器,如nginx运行。如果最终不是放在根目录,可以在 `manifest.config.ts` 文件的 `h5.router.base` 属性进行修改。
+- weixin平台:`pnpm build:mp-weixin`, 打包后的文件在 `dist/build/mp-weixin`,然后通过微信开发者工具导入,并点击右上角的“上传”按钮进行上传。
+- APP平台:`pnpm build:app`, 然后打开 `HBuilderX`,导入刚刚生成的`dist/build/app` 文件夹,选择发行 - APP云打包。
+
+## 📦 TODO
+
+- 1.下拉更新、上拉加载移动端组件 √
+- 2.页面生命周期管理中心,默认拦截enums.LoadType.onLoad,通知容器数据加载完毕 √
+- 3.公共请求框架,接口信息自动装配 √
+- 4.公共状态管理中心,接口请求状态跟踪,身份存储 √
+- 5.公共请求框架,类型推导智能提示 √
+- 6.公共请求框架,身份认证 √
+- 7.公共请求框架,根据swagger导入接口信息,包括接口组、接口入参结构,接口出参结构 √
+- 8.调试、打包时过滤掉未用到的接口配置信息,微信小程序,√
+- 9.调试、打包时过滤掉未用到的接口配置信息,支付宝小程序 √
+- 10.调试、打包时过滤掉未用到的接口配置信息,通过拦截watchChange、generateBundle 减少文件重复写入 √
+- 11.通过UniPages的onBeforeWriteFile钩子函数,自动生成页面路由信息 √
+- 12.页面跳转公共方法,结合页面配置信息判断身份过期登录、页面参数传递等 √
+- 13.微信小程序环境以及真机验证容器组件分页,生命周期管理,页面状态管理,并做兼容性调整 √
+- 14.通过UniPages的onBeforeWriteFile钩子函数,自动生成页面路由信息-支持分包 √
+- 15.公共请求框架支持文件上传,swagger导入接口信息识别是否是上传接口,调用接口时自动唤起选择文件窗口
+- 16.公共请求方法,支持类型修饰,深度合并两个ts对象类型 √
+- 17.全局防抖函数,支持常规等待和立即执行,目标方法哈希计算,追加防抖函数细粒度标签;已应用于页面生命周期管理中心,避免init方法重复执行;页面公共跳转方法,避免页面重复跳转。√
+- 18.开发环境,通过generateBundle钩子函数实现增量修改微信小程序的js文件,以便提高小程序ide工具的编译速度。
+- 19.全局sass变量自动引入,全局sass变量、样式表定义。
+- 20.公共请求框架,根据swagger导入接口信息支持增量导入。
+- 21.页面方法公共初始化,对页面方法进行集中拦截、公共管控,已支持自动为对象内所有方法增加防重提功能(同步方法、异步方法执行中再次触发不执行) 。
+- 22.微信小程序环境支持websocket-stomp协议,收银员扫描驾驶员二维码创建订单后,驾驶员端自动跳转待支付页面。

+ 15 - 0
env/.env

@@ -0,0 +1,15 @@
+VITE_APP_TITLE = 'auyen-mobile'
+VITE_APP_PORT = 9000
+
+VITE_UNI_APPID = ''
+VITE_WX_APPID = 'wxf69daeba7aec5be4'
+
+# h5部署网站的base,配置到 manifest.config.ts 里的 h5.router.base
+VITE_APP_PUBLIC_BASE=/auyen-mobile/
+
+VITE_SERVER_BASEURL = 'https://dapi.auyen.com'
+VITE_RESOURCE_BASEURL = 'https://dwx.auyen.com'
+
+# h5是否需要配置代理
+VITE_APP_PROXY=true
+VITE_APP_PROXY_PREFIX = '/api'

+ 11 - 0
env/.env.development

@@ -0,0 +1,11 @@
+# 变量必须以 VITE_ 为前缀才能暴露给外部读取
+NODE_ENV = 'development'
+VITE_WX_APPID = 'wxf69daeba7aec5be4'
+
+# 是否去除console 和 debugger
+VITE_DELETE_CONSOLE = false
+# 是否开启sourcemap
+VITE_SHOW_SOURCEMAP = true
+
+VITE_SERVER_BASEURL = 'https://dapi.auyen.com'
+# VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'

+ 8 - 0
env/.env.production

@@ -0,0 +1,8 @@
+# 变量必须以 VITE_ 为前缀才能暴露给外部读取
+NODE_ENV = 'production'
+# 是否去除console 和 debugger
+VITE_DELETE_CONSOLE = true
+# 是否开启sourcemap
+VITE_SHOW_SOURCEMAP = false
+
+VITE_SERVER_BASEURL = 'https://api.auyen.com'

+ 6 - 0
env/.env.test

@@ -0,0 +1,6 @@
+# 变量必须以 VITE_ 为前缀才能暴露给外部读取
+NODE_ENV = 'test'
+# 是否去除console 和 debugger
+VITE_DELETE_CONSOLE = false
+
+VITE_SERVER_BASEURL = 'https://tapi.auyen.com'

BIN
favicon.ico


+ 28 - 0
index.html

@@ -0,0 +1,28 @@
+<!doctype html>
+<html build-time="%BUILD_TIME%">
+
+<head>
+  <meta charset="UTF-8" />
+  <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
+  <script>
+    var coverSupport =
+      'CSS' in window &&
+      typeof CSS.supports === 'function' &&
+      (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
+    document.write(
+      '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+      (coverSupport ? ', viewport-fit=cover' : '') +
+      '" />',
+    )
+  </script>
+  <title>auyen-mobile</title>
+  <!--preload-links-->
+  <!--app-context-->
+</head>
+
+<body>
+  <div id="app"><!--app-html--></div>
+  <script type="module" src="/src/main.ts"></script>
+</body>
+
+</html>

+ 135 - 0
manifest.config.ts

@@ -0,0 +1,135 @@
+// manifest.config.ts
+import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
+import path from 'node:path'
+import { loadEnv } from 'vite'
+
+// 获取环境变量的范例
+const env = loadEnv(process.env.NODE_ENV!, path.resolve(process.cwd(), 'env'))
+const {
+  VITE_APP_TITLE,
+  VITE_UNI_APPID,
+  VITE_WX_APPID,
+  VITE_APP_PUBLIC_BASE,
+  VITE_FALLBACK_LOCALE,
+} = env
+
+export default defineManifestConfig({
+  name: VITE_APP_TITLE,
+  appid: VITE_UNI_APPID,
+  description: '',
+  versionName: '1.0.0',
+  versionCode: '100',
+  transformPx: false,
+  locale: VITE_FALLBACK_LOCALE, // 'zh-Hans'
+  h5: {
+    router: {
+      // template: 'src/main.ts',
+      base: VITE_APP_PUBLIC_BASE,
+    },
+  },
+  /* 5+App特有相关 */
+  'app-plus': {
+    usingComponents: true,
+    nvueStyleCompiler: 'uni-app',
+    compilerVersion: 3,
+    compatible: {
+      ignoreVersion: true,
+    },
+    splashscreen: {
+      alwaysShowBeforeRender: true,
+      waiting: true,
+      autoclose: true,
+      delay: 0,
+    },
+    /* 模块配置 */
+    modules: {},
+    /* 应用发布信息 */
+    distribute: {
+      /* android打包配置 */
+      android: {
+        minSdkVersion: 30,
+        targetSdkVersion: 30,
+        abiFilters: ['armeabi-v7a', 'arm64-v8a'],
+        permissions: [
+          '<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>',
+          '<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>',
+          '<uses-permission android:name="android.permission.VIBRATE"/>',
+          '<uses-permission android:name="android.permission.READ_LOGS"/>',
+          '<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>',
+          '<uses-feature android:name="android.hardware.camera.autofocus"/>',
+          '<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>',
+          '<uses-permission android:name="android.permission.CAMERA"/>',
+          '<uses-permission android:name="android.permission.GET_ACCOUNTS"/>',
+          '<uses-permission android:name="android.permission.READ_PHONE_STATE"/>',
+          '<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>',
+          '<uses-permission android:name="android.permission.WAKE_LOCK"/>',
+          '<uses-permission android:name="android.permission.FLASHLIGHT"/>',
+          '<uses-feature android:name="android.hardware.camera"/>',
+          '<uses-permission android:name="android.permission.WRITE_SETTINGS"/>',
+        ],
+      },
+      /* ios打包配置 */
+      ios: {},
+      /* SDK配置 */
+      sdkConfigs: {},
+      /* 图标配置 */
+      icons: {
+        android: {
+          hdpi: 'static/app/icons/72x72.png',
+          xhdpi: 'static/app/icons/96x96.png',
+          xxhdpi: 'static/app/icons/144x144.png',
+          xxxhdpi: 'static/app/icons/192x192.png',
+        },
+        ios: {
+          appstore: 'static/app/icons/1024x1024.png',
+          ipad: {
+            app: 'static/app/icons/76x76.png',
+            'app@2x': 'static/app/icons/152x152.png',
+            notification: 'static/app/icons/20x20.png',
+            'notification@2x': 'static/app/icons/40x40.png',
+            'proapp@2x': 'static/app/icons/167x167.png',
+            settings: 'static/app/icons/29x29.png',
+            'settings@2x': 'static/app/icons/58x58.png',
+            spotlight: 'static/app/icons/40x40.png',
+            'spotlight@2x': 'static/app/icons/80x80.png',
+          },
+          iphone: {
+            'app@2x': 'static/app/icons/120x120.png',
+            'app@3x': 'static/app/icons/180x180.png',
+            'notification@2x': 'static/app/icons/40x40.png',
+            'notification@3x': 'static/app/icons/60x60.png',
+            'settings@2x': 'static/app/icons/58x58.png',
+            'settings@3x': 'static/app/icons/87x87.png',
+            'spotlight@2x': 'static/app/icons/80x80.png',
+            'spotlight@3x': 'static/app/icons/120x120.png',
+          },
+        },
+      },
+    },
+  },
+  /* 快应用特有相关 */
+  quickapp: {},
+  /* 小程序特有相关 */
+  'mp-weixin': {
+    appid: VITE_WX_APPID,
+    setting: {
+      urlCheck: false,
+    },
+    usingComponents: true,
+    // __usePrivacyCheck__: true,
+  },
+  'mp-alipay': {
+    usingComponents: true,
+    styleIsolation: 'shared',
+  },
+  'mp-baidu': {
+    usingComponents: true,
+  },
+  'mp-toutiao': {
+    usingComponents: true,
+  },
+  uniStatistics: {
+    enable: false,
+  },
+  vueVersion: '3',
+})

+ 149 - 0
package.json

@@ -0,0 +1,149 @@
+{
+  "name": "auyen-mobile",
+  "type": "commonjs",
+  "version": "1.0.0",
+  "description": "大象科技移动端",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://zentao.auyen.com/zentao/"
+  },
+  "engines": {
+    "node": ">=18",
+    "pnpm": ">=7.30"
+  },
+  "scripts": {
+    "gif": "node ./scripts/getInterFace.js",
+    "uvm": "npx @dcloudio/uvm@latest",
+    "uvm-rm": "node ./scripts/postupgrade.js",
+    "postuvm": "echo upgrade uni-app success!",
+    "dev:app": "uni -p app",
+    "dev:app-android": "uni -p app-android",
+    "dev:app-ios": "uni -p app-ios",
+    "dev:custom": "uni -p",
+    "dev": "uni",
+    "dev:h5": "uni",
+    "dev:h5:ssr": "uni --ssr",
+    "dev:mp": "uni -p mp-weixin",
+    "dev:mp-alipay": "uni -p mp-alipay",
+    "dev:mp-baidu": "uni -p mp-baidu",
+    "dev:mp-jd": "uni -p mp-jd",
+    "dev:mp-kuaishou": "uni -p mp-kuaishou",
+    "dev:mp-lark": "uni -p mp-lark",
+    "dev:mp-qq": "uni -p mp-qq",
+    "dev:mp-toutiao": "uni -p mp-toutiao",
+    "dev:mp-weixin": "uni -p mp-weixin",
+    "dev:quickapp-webview": "uni -p quickapp-webview",
+    "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
+    "dev:quickapp-webview-union": "uni -p quickapp-webview-union",
+    "build:app": "uni build -p app",
+    "build:app-android": "uni build -p app-android",
+    "build:app-ios": "uni build -p app-ios",
+    "build:custom": "uni build -p",
+    "build:h5": "uni build",
+    "build": "uni build",
+    "build:h5:ssr": "uni build --ssr",
+    "build:mp-alipay": "uni build -p mp-alipay",
+    "build:mp": "uni build -p mp-weixin",
+    "build:mp-baidu": "uni build -p mp-baidu",
+    "build:mp-jd": "uni build -p mp-jd",
+    "build:mp-kuaishou": "uni build -p mp-kuaishou",
+    "build:mp-lark": "uni build -p mp-lark",
+    "build:mp-qq": "uni build -p mp-qq",
+    "build:mp-toutiao": "uni build -p mp-toutiao",
+    "build:mp-weixin": "uni build -p mp-weixin",
+    "build:quickapp-webview": "uni build -p quickapp-webview",
+    "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
+    "build:quickapp-webview-union": "uni build -p quickapp-webview-union",
+    "prepare": "git init && husky install ",
+    "type-check": "vue-tsc --noEmit",
+    "cz": "czg"
+  },
+  "lint-staged": {
+    "**/*.{html,vue,ts,cjs,json,md}": [
+      "prettier --write"
+    ],
+    "**/*.{vue,js,ts,jsx,tsx}": [
+      "eslint --fix"
+    ],
+    "**/*.{vue,css,scss,html}": [
+      "stylelint --fix"
+    ]
+  },
+  "resolutions": {
+    "bin-wrapper": "npm:bin-wrapper-china"
+  },
+  "dependencies": {
+    "@dcloudio/uni-app": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/uni-app-plus": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/uni-components": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/uni-h5": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/uni-mp-weixin": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/uni-ui": "^1.5.5",
+    "czg": "^1.9.3",
+    "dayjs": "1.11.10",
+    "js-base64": "^3.7.7",
+    "pinia": "2.0.36",
+    "pinia-plugin-persistedstate": "3.2.1",
+    "qs": "6.5.3",
+    "stompjs": "^2.3.3",
+    "vant": "3.6.12",
+    "vue": "3.4.21",
+    "z-paging": "^2.7.10"
+  },
+  "devDependencies": {
+    "@commitlint/cli": "^18.6.1",
+    "@commitlint/config-conventional": "^18.6.3",
+    "@dcloudio/types": "^3.4.8",
+    "@dcloudio/uni-automator": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/uni-cli-shared": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/uni-stacktracey": "3.0.0-alpha-4020220240624001",
+    "@dcloudio/vite-plugin-uni": "3.0.0-alpha-4020220240624001",
+    "@esbuild/darwin-arm64": "0.20.2",
+    "@esbuild/darwin-x64": "0.20.2",
+    "@iconify-json/carbon": "^1.1.35",
+    "@rollup/rollup-darwin-x64": "^4.18.0",
+    "@types/node": "^20.14.2",
+    "@types/wechat-miniprogram": "^3.4.7",
+    "@typescript-eslint/eslint-plugin": "^6.21.0",
+    "@typescript-eslint/parser": "^6.21.0",
+    "@uni-helper/vite-plugin-uni-layouts": "^0.1.10",
+    "@uni-helper/vite-plugin-uni-manifest": "^0.2.6",
+    "@uni-helper/vite-plugin-uni-pages": "0.2.20",
+    "@uni-helper/vite-plugin-uni-platform": "^0.0.4",
+    "@unocss/preset-legacy-compat": "^0.59.4",
+    "@vue/runtime-core": "^3.4.29",
+    "@vue/tsconfig": "^0.1.3",
+    "autoprefixer": "^10.4.19",
+    "axios": "^1.7.2",
+    "commitlint": "^18.6.1",
+    "eslint": "^8.57.0",
+    "eslint-config-prettier": "^9.1.0",
+    "eslint-config-standard": "^17.1.0",
+    "eslint-import-resolver-typescript": "^3.6.1",
+    "eslint-plugin-import": "^2.29.1",
+    "eslint-plugin-prettier": "^5.1.3",
+    "eslint-plugin-vue": "^9.26.0",
+    "husky": "^8.0.3",
+    "lint-staged": "^15.2.7",
+    "postcss": "^8.4.38",
+    "postcss-html": "^1.7.0",
+    "postcss-scss": "^4.0.9",
+    "rollup-plugin-visualizer": "^5.12.0",
+    "sass": "^1.77.5",
+    "stylelint": "^16.6.1",
+    "stylelint-config-html": "^1.1.0",
+    "stylelint-config-recess-order": "^4.6.0",
+    "stylelint-config-recommended": "^14.0.0",
+    "stylelint-config-recommended-scss": "^14.0.0",
+    "stylelint-config-recommended-vue": "^1.5.0",
+    "stylelint-prettier": "^5.0.0",
+    "terser": "^5.31.1",
+    "typescript": "^4.9.5",
+    "unocss": "^0.58.9",
+    "unocss-applet": "^0.7.8",
+    "unplugin-auto-import": "^0.17.6",
+    "vite": "5.2.8",
+    "vite-plugin-restart": "^0.4.0",
+    "vue-tsc": "^1.8.27"
+  }
+}

+ 63 - 0
pages.config.ts

@@ -0,0 +1,63 @@
+import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'
+
+export default defineUniPages({
+  globalStyle: {
+    navigationStyle: 'default',
+    // navigationBarTitleText: 'auyen-mobile',
+    navigationBarBackgroundColor: '#f8f8f8',
+    navigationBarTextStyle: 'black',
+    backgroundColor: '#FFFFFF',
+    enablePullDownRefresh: false,
+    onReachBottomDistance: 50,
+  },
+  easycom: {
+    autoscan: true,
+    custom: {
+      '^wd-(.*)': 'wot-design-uni/components/wd-$1/wd-$1.vue',
+      '^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)':
+        'z-paging/components/z-paging$1/z-paging$1.vue',
+      // uni-ui 规则如下配置
+      '^uni-(.*)': '@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue',
+      '^ay-(.*)': '@/components/$1/index.vue',
+      '^ayb-(.*)': '@/components/business/$1',
+      // '^van-(.*)': '@/wxcomponents/vant/$1/index.vue', // 匹配components目录内的vue文件
+    },
+  },
+  // tabBar: {
+  //   color: '#999999',
+  //   selectedColor: '#018d71',
+  //   backgroundColor: '#F8F8F8',
+  //   borderStyle: 'black',
+  //   height: '50px',
+  //   fontSize: '10px',
+  //   iconWidth: '24px',
+  //   spacing: '3px',
+  //   list: [
+  //     {
+  //       iconPath: 'static/tabbar/home.png',
+  //       selectedIconPath: 'static/tabbar/homeHL.png',
+  //       pagePath: 'pages/index/index',
+  //       text: '首页',
+  //     },
+  //     {
+  //       iconPath: 'static/tabbar/example.png',
+  //       selectedIconPath: 'static/tabbar/exampleHL.png',
+  //       pagePath: 'pages/list/index',
+  //       text: '列表',
+  //     },
+  //     {
+  //       iconPath: 'static/tabbar/example.png',
+  //       selectedIconPath: 'static/tabbar/exampleHL.png',
+  //       pagePath: 'pages/login/index',
+  //       text: '登录',
+  //     },
+  //   ],
+  // },
+  pages: [],
+  requiredPrivateInfos: ['getLocation'],
+  permission: {
+    'scope.userLocation': {
+      desc: '当前位置信息将用于附近加气站搜索',
+    },
+  },
+})

Diferenças do arquivo suprimidas por serem muito extensas
+ 12074 - 0
pnpm-lock.yaml


+ 91 - 0
scripts/common.js

@@ -0,0 +1,91 @@
+/* eslint-disable @typescript-eslint/no-var-requires */
+const path = require('node:path')
+const fs = require('fs')
+const Axios = require('axios')
+const axios = Axios.create({
+  timeout: 30000,
+  baseURL: 'https://swagger.auyen.com',
+})
+/** 色彩打印 */
+const cl = {
+  colors: {
+    reset: '\x1b[0m',
+    red: '\x1b[31m',
+    green: '\x1b[32m',
+    yellow: '\x1b[33m',
+  },
+  /** 成功消息 */
+  logs() {
+    console.log(`${this.colors.green}%s${this.colors.reset}`, ...arguments)
+  },
+  /** 错误消息 */
+  loge() {
+    console.log(`${this.colors.red}%s${this.colors.reset}`, ...arguments)
+  },
+  /** 警告消息 */
+  logw() {
+    console.log(`${this.colors.yellow}%s${this.colors.reset}`, ...arguments)
+  },
+}
+
+const request = {
+  get(path) {
+    return axios(path).then((res) => res.data)
+  },
+}
+
+const files = {
+  path,
+  basename(filePath, extname = true) {
+    let rv = path.basename(filePath)
+    if (!extname) {
+      rv = rv.replace(/\..*$/, '')
+    }
+    return rv
+  },
+  /**
+   * 遍历指定目录下的所有文件
+   * @param {*} dir
+   */
+  getAllFile(dir) {
+    const res = []
+    function traverse(dir) {
+      fs.readdirSync(dir).forEach((file) => {
+        const pathname = path.join(dir, file)
+        if (fs.statSync(pathname).isDirectory()) {
+          traverse(pathname)
+        } else {
+          res.push(pathname)
+        }
+      })
+    }
+    traverse(dir)
+    return res
+  },
+  getPath(relPath) {
+    return path.resolve(process.cwd(), relPath)
+  },
+  getIFPath(fileName) {
+    const rv = {
+      schemaPath: this.getPath(`src/types/schemas/${fileName}.d.ts`),
+      webApiPath: this.getPath(`src/utils/config/interFaces/${fileName}.ts`),
+    }
+    return rv
+  },
+  write(path, content) {
+    try {
+      fs.writeFileSync(path, content, 'utf-8')
+    } catch {}
+  },
+  read(path) {
+    try {
+      return fs.readFileSync(path, 'utf-8')
+    } catch {}
+  },
+}
+
+module.exports = {
+  cl,
+  request,
+  files,
+}

+ 276 - 0
scripts/getInterFace.js

@@ -0,0 +1,276 @@
+/* eslint-disable import/extensions */
+/* eslint-disable @typescript-eslint/no-var-requires */
+const common = require('./common.js')
+const { cl, request, files } = common
+
+const convert = {
+  /** 特殊替换时使用 */
+  _placeholder: '_',
+  _maps: {
+    baseTypes: ['integer', 'int', 'long', 'bigdecimal', 'string'],
+    /** 需要替换的类型 */
+    dataTypes: {
+      number: ['integer', 'int', 'long', 'bigdecimal'],
+      Array: ['Collection', 'List'],
+      Record: ['Map'],
+      IPage: ['Page'],
+      IPageParams: ['分页请求参数'],
+      AnyObject: ['object', 'JSONObject'],
+    },
+    scheamas: {},
+    /** 完整替换的类型 */
+    completes: Object.entries({
+      'Array<any>': ['array'],
+      any: ['Result', '返回值'],
+      'Record<any, any>': ['Record', 'Map'],
+      'IPageParams<any>': ['IPageParams'],
+    }),
+  },
+  /** 修正被占位符替换破坏的类型修饰 */
+  correct(str) {
+    /** 修正被替换的基础类型后面的, */
+    convert._maps.baseTypes.forEach((f) => {
+      const cs = `${f}${convert._placeholder}`
+      if (str.includes(cs)) {
+        str = str.replace(cs, `${f}, `)
+      }
+    })
+    return str
+  },
+  /** 转换类型定义 */
+  definitions(str) {
+    str = str.replace('#/definitions/', '')
+    str = convert.getSafeStr(str)
+    str = convert.correct(str)
+    str = convert.dataTypesMap(str, 1)
+    str = str.replace(/«/g, '<')
+    str = str.replace(/»/g, '>')
+    for (const [k, v] of convert._maps.completes) {
+      v.forEach((f) => {
+        if (str === f) {
+          str = k
+        }
+      })
+    }
+    return str
+    // ms = ['返回值','List','Ipage']
+    // str = '返回值«IPage«UserAccount对象»»'
+    // function ffff(str) {
+    //     const rg = new RegExp(`([${ms.join('|')}])«(.+)»`)
+    //     const strm = str.match(rg)
+    //     if (strm && strm.length == 3) {
+    //         switch (strm[1]) {
+    //             case 'List':
+    //                 str = `${strm[2]}[]`
+    //                 defa
+    //         }
+    //         ffff(strm[2])
+    //         console.log(strm)
+    //     }
+    // }
+  },
+  /** 类型替换
+   * type 0:字符串完全替换,1:正则替换
+   */
+  dataTypesMap(str, type = 0) {
+    if (!str) return ''
+    for (const [k, v] of Object.entries(this._maps.dataTypes)) {
+      v.forEach((f) => {
+        if (type === 0) {
+          str = str.replace(f, k)
+        }
+        if (type === 1) {
+          // 脱壳
+          str = str.replace(/^返回值«(.+)»/, '$1')
+          str = str.replace(/^Result«(.+)»/, '$1')
+          // 取出被«»包裹的类型
+          const rg = new RegExp(`(^|«+)${f}([,«»]+|$)`)
+          if (rg.test(str)) {
+            // 替换这种类型
+            str = str.replace(rg, `$1${k}$2`)
+            // // 被特殊替换了的, 替换回来
+            // const srp = `${k}${convert._placeholder}`
+            // if (str.includes(srp)) {
+            //   str = str.replace(srp, `${k}, `)
+            // }
+          }
+        }
+      })
+    }
+    return str
+  },
+  _dirtyChars: ['-', ',', '、', '/', '(', ')', ','],
+  getSafeStr(str) {
+    this._dirtyChars.forEach((f) => {
+      str = str.replaceAll(f, convert._placeholder)
+    })
+    return str
+  },
+  main({ name, url, basePath }) {
+    basePath = basePath.replace(/^\//, '')
+    return request
+      .get(url)
+      .then((res) => {
+        // const tt = files.getIFPath(basePath + '_raw')
+        // files.write(tt.webApiPath, res)
+        // try {
+        const data = res
+        this.scheama({ name, basePath, data })
+        this.webapi({ name, basePath, data })
+        // } catch (e) {
+        //   return Promise.resolve({ errInfo: e })
+        // }
+      })
+      .catch((e) => {
+        cl.logw(`${name}-${basePath}:${e}`)
+        return Promise.resolve({ errInfo: e })
+      })
+  },
+  /** 生成 scheama文件 .d.ts */
+
+  scheama({ name, basePath, data }) {
+    const curps = files.getIFPath(basePath)
+    const tss = Object.values(data.definitions)
+      // 忽略嵌套类型
+      .filter((f) => !f.title.includes('«'))
+      .map((m) => {
+        let descriptions = ''
+        if (m.properties) {
+          descriptions = '\n'
+          for (const [k, v] of Object.entries(m.properties)) {
+            let curType = ''
+            if (v.$ref) {
+              curType = convert.definitions(v.$ref)
+            } else if (v.type === 'array' && v.items.$ref) {
+              curType = convert.definitions(v.items.$ref) + '[]'
+            } else {
+              curType = convert.dataTypesMap(v.type)
+            }
+            descriptions += `  /** ${v.description} */\n  ${k}?: ${curType}\n`
+          }
+        }
+        return `interface ${convert.getSafeStr(m.title)} {${descriptions}}`
+      })
+    files.write(curps.schemaPath, `/** ${name} */\n${tss.join('\n')}\n`)
+  },
+  /** 生成接口配置信息 */
+  webapi({ name, basePath, data }) {
+    const curps = files.getIFPath(basePath)
+    const paths = data.paths
+    let urlsStr = ''
+    const urlNameMap = {}
+    const getUrlName = (url) => {
+      url = url.replace(/.+\//, '')
+
+      if (urlNameMap.hasOwnProperty(url)) {
+        urlNameMap[url]++
+      } else {
+        urlNameMap[url] = 0
+      }
+      return url + (urlNameMap[url] ? '_' + urlNameMap[url] : '')
+    }
+    for (const [k, v] of Object.entries(paths)) {
+      const curPostInfo = v.post
+      if (!curPostInfo) continue
+      // const urlName = curPostInfo.operationId.replace('UsingPOST', '')
+      if (k.includes('{')) continue
+      const urlName = getUrlName(k)
+
+      let isUploadStr = ''
+      let reqTypeStr = ''
+      let resTypeStr = ''
+      // 存在入参定义
+      if (curPostInfo.parameters && curPostInfo.parameters.length) {
+        /** body类型入参 */
+        const bodyParameter = curPostInfo.parameters.find((f) => f.in === 'body')
+        if (bodyParameter) {
+          const curSchema = bodyParameter.schema
+          if (curSchema && curSchema.$ref) {
+            reqTypeStr = `    reqType: {} as ${convert.definitions(curSchema.$ref)},`
+          }
+        }
+        /** query类型入参 */
+        const queryParameters = curPostInfo.parameters.filter((f) => f.in === 'query')
+        if (queryParameters.length) {
+          const curReqType = queryParameters
+            .map(
+              (m) =>
+                `\n      /** ${m.description} */\n      ${m.name}${m.required ? '' : '?'}: ${convert.dataTypesMap(m.type)}`,
+            )
+            .join('')
+          reqTypeStr = `    reqType: {} as {${curReqType}\n    },`
+        }
+        /** formData类型入参-- 上传文件 */
+        const formDataParameters = curPostInfo.parameters.find((f) => f.in === 'formData')
+        if (formDataParameters) {
+          isUploadStr = '\n    isUpload: true,'
+          // reqTypeStr = `    reqType: {} as {${`\n      /** ${formDataParameters.description} */\n      ${formDataParameters.name}${formDataParameters.required ? '' : '?'}: File`}\n    },`
+        }
+      }
+      if (
+        curPostInfo.responses &&
+        curPostInfo.responses[200] &&
+        curPostInfo.responses[200].schema &&
+        curPostInfo.responses[200].schema.$ref
+      ) {
+        /** 出参 类型 */
+        const resTypeSchema = convert.definitions(curPostInfo.responses[200].schema.$ref)
+        resTypeStr = `    resType: {} as ${resTypeSchema},`
+      }
+      urlsStr += `\n  /** ${curPostInfo.summary || curPostInfo.summary} */\n  ${urlName}: {\n    realUrl: '${k}' as const,${isUploadStr}\n${reqTypeStr}\n${resTypeStr}\n  },`
+    }
+    files.write(
+      curps.webApiPath,
+      `export default {${urlsStr}\n}\n`,
+      // `const ${basePath} = {${urlsStr}\n}\nexport default ${basePath}\n`,
+    )
+  },
+}
+
+const main = () => {
+  request.get('/json/group.json').then((res) => {
+    // res=  [{
+    //     "name": "账户中心",
+    //     "url": "/account/v2/api-docs",
+    //     "swaggerVersion": "2.0",
+    //     "location": "/account/v2/api-docs",
+    //     "basePath": "/account"
+    // }]
+    // 获取所有控制台参数
+    const args = process.argv.slice(2) // 去掉第一个和第二个参数(node路径和脚本路径)
+    // 分组名称-模糊
+    const gn = args[0]
+    const groups = gn ? res.filter((f) => f.basePath.includes(gn)) : res
+    let importStr = ''
+    let exportStr = ''
+    Promise.all(
+      groups.map((f) => {
+        f.basePath = f.basePath.replace('/', '')
+        return convert.main(f).then((res) => {
+          if (res && res.errInfo) {
+            cl.loge(`${f.name}-${f.basePath}:导入失败×`)
+            return
+          } else {
+            cl.logs(`${f.name}-${f.basePath}:导入成功√`)
+          }
+          importStr += `import ${f.basePath} from './${f.basePath}'\n`
+          exportStr += `  /** ${f.name} */\n  ${f.basePath},\n`
+        })
+      }),
+    ).then(() => {
+      // 根据名称模糊搜索 不写入index.ts
+      if (gn) return
+      // 写入 src\utils\config\interFaces\index.ts
+      const exportFileStr = `${importStr}\nexport default {\n${exportStr}}\n`
+      const exportsPath = files.getIFPath('index')
+      files.write(exportsPath.webApiPath, exportFileStr)
+    })
+  })
+}
+main()
+
+const test = () => {
+  // 获取所有控制台参数
+  const args = process.argv.slice(2) // 去掉第一个和第二个参数(node路径和脚本路径)
+}
+// test()

+ 36 - 0
scripts/postupgrade.js

@@ -0,0 +1,36 @@
+// # 执行 `pnpm upgrade` 后会升级 `uniapp` 相关依赖
+// # 在升级完后,会自动添加很多无用依赖,这需要删除以减小依赖包体积
+// # 只需要执行下面的命令即可
+
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+const { exec } = require('child_process')
+
+// 定义要执行的命令
+const dependencies = [
+  '@dcloudio/uni-app-harmony',
+  // TODO: 如果需要某个平台的小程序,请手动删除或注释掉
+  '@dcloudio/uni-mp-alipay',
+  '@dcloudio/uni-mp-baidu',
+  '@dcloudio/uni-mp-jd',
+  '@dcloudio/uni-mp-kuaishou',
+  '@dcloudio/uni-mp-lark',
+  '@dcloudio/uni-mp-qq',
+  '@dcloudio/uni-mp-toutiao',
+  '@dcloudio/uni-mp-xhs',
+  '@dcloudio/uni-quickapp-webview',
+  // i18n模板要注释掉下面的
+  'vue-i18n',
+]
+
+// 使用exec执行命令
+exec(`pnpm un ${dependencies.join(' ')}`, (error, stdout, stderr) => {
+  if (error) {
+    // 如果有错误,打印错误信息
+    console.error(`执行出错: ${error}`)
+    return
+  }
+  // 打印正常输出
+  console.log(`stdout: ${stdout}`)
+  // 如果有错误输出,也打印出来
+  console.error(`stderr: ${stderr}`)
+})

+ 12 - 0
src/App.vue

@@ -0,0 +1,12 @@
+<script setup lang="ts">
+onLaunch(() => {
+  //   uni.hideHomeButton()
+})
+// onShow(() => {
+//   console.log('App Show')
+// })
+// onHide(() => {
+//   console.log('App Hide')
+// })
+</script>
+<style></style>

+ 344 - 0
src/components/business/carNumber.vue

@@ -0,0 +1,344 @@
+<template>
+  <div class="keyboards">
+    <div class="keyboards_title">
+      输入车牌
+      <span>(绿色背景为新能源车牌)</span>
+    </div>
+    <div>
+      <ul class="input_box" @click="methods.clickShowKeyboard">
+        <li>{{ data.first }}</li>
+        <li>{{ data.numArr[0] }}</li>
+        <span style="font-size: 50rpx; line-height: 100rpx; color: #ced0d2">•</span>
+        <li>{{ data.numArr[1] }}</li>
+        <li>{{ data.numArr[2] }}</li>
+        <li>{{ data.numArr[3] }}</li>
+        <li>{{ data.numArr[4] }}</li>
+        <li>{{ data.numArr[5] }}</li>
+        <li>{{ data.numArr[6] }}</li>
+      </ul>
+    </div>
+    <div class="keySure" @click="methods.submitNumber">确定</div>
+    <!-- 键盘-中英文 -->
+    <uni-popup ref="popup" background-color="#fff">
+      <div class="keyboards_keys">
+        <div class="finish_key"><span @click="methods.hidekeyboards">完成</span></div>
+        <div class="finish_line"></div>
+        <div class="key_box">
+          <!-- 中文 -->
+          <div v-if="data.checkLangages" class="chinese">
+            <ul v-for="(item, index) in data.chineseList" :key="index">
+              <li
+                v-for="val in item"
+                :key="val.id"
+                :class="{ del: val.id === 99 || val.id === 98 }"
+                @click="methods.chooseChinese(val)"
+              >
+                {{ val.name }}
+              </li>
+            </ul>
+          </div>
+          <!-- 数字英文 -->
+          <div v-else class="english">
+            <ul v-for="(item, index) in data.englishList" :key="index">
+              <li
+                v-for="val in item"
+                :key="val.id"
+                :class="{ del: val.id === 99 || val.id === 97 }"
+                @click="methods.chooseEnglish(val)"
+              >
+                {{ val.name }}
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+    </uni-popup>
+  </div>
+</template>
+
+<script lang="ts" setup>
+const popup = ref()
+const data = reactive({
+  first: '',
+  numArr: [],
+  checkLangages: true,
+  chineseList: [
+    [
+      { name: '京', id: 1 },
+      { name: '津', id: 2 },
+      { name: '冀', id: 3 },
+      { name: '晋', id: 4 },
+      { name: '蒙', id: 5 },
+      { name: '辽', id: 6 },
+      { name: '吉', id: 7 },
+      { name: '黑', id: 8 },
+      { name: '沪', id: 9 },
+      { name: '苏', id: 10 },
+    ],
+    [
+      { name: '浙', id: 11 },
+      { name: '皖', id: 12 },
+      { name: '闽', id: 13 },
+      { name: '赣', id: 14 },
+      { name: '鲁', id: 15 },
+      { name: '豫', id: 16 },
+      { name: '鄂', id: 17 },
+      { name: '湘', id: 18 },
+      { name: '粤', id: 19 },
+      { name: '桂', id: 20 },
+    ],
+    [
+      { name: '琼', id: 21 },
+      { name: '渝', id: 22 },
+      { name: '川', id: 23 },
+      { name: '贵', id: 24 },
+      { name: '云', id: 25 },
+      { name: '藏', id: 26 },
+      { name: '陕', id: 27 },
+      { name: '甘', id: 28 },
+      { name: '青', id: 29 },
+      { name: '宁', id: 30 },
+    ],
+    [
+      { name: 'ABC', id: 98 },
+      { name: '新', id: 31 },
+      { name: '使', id: 32 },
+      { name: '领', id: 33 },
+      { name: '警', id: 34 },
+      { name: '学', id: 35 },
+      { name: '港', id: 36 },
+      { name: '澳', id: 37 },
+      { name: '删除', id: 99 },
+    ],
+  ],
+  englishList: [
+    [
+      { name: '1', id: 40 },
+      { name: '2', id: 41 },
+      { name: '3', id: 42 },
+      { name: '4', id: 43 },
+      { name: '5', id: 44 },
+      { name: '6', id: 45 },
+      { name: '7', id: 46 },
+      { name: '8', id: 47 },
+      { name: '9', id: 48 },
+      { name: '0', id: 49 },
+    ],
+    [
+      { name: 'Q', id: 38 },
+      { name: 'W', id: 39 },
+      { name: 'E', id: 40 },
+      { name: 'R', id: 41 },
+      { name: 'T', id: 42 },
+      { name: 'Y', id: 43 },
+      { name: 'U', id: 44 },
+      { name: 'I', id: 45 },
+      { name: 'O', id: 46 },
+      { name: 'P', id: 47 },
+    ],
+    [
+      { name: 'A', id: 48 },
+      { name: 'S', id: 49 },
+      { name: 'D', id: 50 },
+      { name: 'F', id: 51 },
+      { name: 'G', id: 52 },
+      { name: 'H', id: 53 },
+      { name: 'J', id: 54 },
+      { name: 'K', id: 55 },
+      { name: 'L', id: 56 },
+    ],
+    [
+      { name: '地区', id: 97 },
+      { name: 'Z', id: 57 },
+      { name: 'X', id: 58 },
+      { name: 'C', id: 59 },
+      { name: 'V', id: 60 },
+      { name: 'B', id: 61 },
+      { name: 'N', id: 62 },
+      { name: 'M', id: 63 },
+      { name: '删除', id: 99 },
+    ],
+  ],
+  carNUmber: '',
+})
+
+onMounted(() => {
+  popup.value.open('bottom')
+})
+const methods = {
+  // 唤醒键盘
+  clickShowKeyboard() {
+    popup.value.open('bottom')
+    if (!data.first) {
+      data.checkLangages = true
+    } else {
+      data.checkLangages = false
+    }
+  },
+  // 选择车牌号前面的汉字
+  chooseChinese(val) {
+    if (val.id === 97 || val.id === 98) {
+      data.checkLangages = !data.checkLangages
+    } else if (val.id === 99) {
+      if (data.numArr.length === 0) {
+        data.first = ''
+      }
+    } else {
+      // 把选中的字赋值给第一个格,并且切换键盘
+      data.first = val.name
+      data.checkLangages = false
+    }
+  },
+  // 选择车牌后面的数字和字母
+  chooseEnglish(val) {
+    if (val.id === 97 || val.id === 98) {
+      data.checkLangages = !data.checkLangages
+    } else if (val.id === 99) {
+      data.numArr.pop()
+
+      // 如果数字,字母被删光了,则切换到中文键盘
+      if (data.numArr.length === 0) {
+        data.checkLangages = true
+      }
+    } else {
+      // 把选中的值push到data.numArr里面
+      data.numArr.push(val.name)
+      if (data.numArr.length > 7) {
+        data.numArr.pop()
+      }
+    }
+    data.carNUmber = data.first + data.numArr.join('')
+    // console.log(data.carNUmber)
+  },
+  // 完成,隐藏键盘
+  hidekeyboards() {
+    popup.value.close()
+  },
+  // 提交车牌号
+  submitNumber() {
+    const carNumberReg =
+      /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/
+    if (carNumberReg.test(data.carNUmber)) {
+      // console.log(data.carNUmber, '确定按钮')
+      // data.show_chinese = false;
+      popup.value.close()
+      // data.$emit('sendCarNumber', data.carNUmber)
+      // 清空上一次输入的车牌
+      data.first = ''
+      data.numArr = []
+    } else {
+      func.native.showToast('请输入正确的车牌号')
+    }
+    data.first = ''
+    data.numArr = []
+    data.checkLangages = true
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.keyboards {
+  box-sizing: border-box;
+  width: 100%;
+
+  .keyboards_title {
+    margin: 15rpx 25rpx;
+    font-size: 20rpx;
+    text-align: left;
+    span {
+      margin-left: 5rpx;
+      font-size: 16rpx;
+      color: #45b94d;
+    }
+  }
+
+  .input_box {
+    box-sizing: border-box;
+    display: flex;
+    justify-content: center;
+    margin: 0 auto 25rpx;
+
+    li {
+      flex: 1;
+      margin: 2rpx;
+      font-size: 48rpx;
+      line-height: 100rpx;
+      text-align: center;
+      border: 1rpx solid #ced0d2;
+      border-radius: 4rpx;
+    }
+
+    li:last-child {
+      background-color: #9eefa4;
+    }
+
+    // 动态样式
+    .li_focus {
+      border: 1rpx solid orange;
+    }
+  }
+
+  .keySure {
+    margin: auto;
+    font-size: 20rpx;
+    line-height: 40rpx;
+    color: #fff;
+    text-align: center;
+    background-color: #333333;
+    border-radius: 20rpx;
+  }
+
+  .keyboards_keys {
+    margin: 10rpx auto 0;
+    background-color: rgb(211, 214, 221);
+
+    .finish_key {
+      font-size: 16rpx;
+      line-height: 30rpx;
+      color: rgb(104, 105, 105);
+
+      span {
+        position: absolute;
+        right: 20rpx;
+      }
+    }
+
+    .finish_line {
+      width: 375rpx;
+      border-bottom: 1rpx solid rgb(178, 179, 180);
+    }
+
+    .key_box {
+      ul {
+        box-sizing: border-box;
+        display: flex;
+        justify-content: center;
+        margin: 10rpx auto 10rpx;
+
+        li {
+          // flex: 1;
+          width: 62rpx;
+          padding: 4rpx;
+          margin: 4rpx;
+          font-size: 36rpx;
+          line-height: 80rpx;
+          text-align: center;
+          // border: 1rpx solid red;
+          background-color: #fff;
+          border-radius: 5rpx;
+          box-shadow: 1rpx 3rpx 1rpx #aaa;
+        }
+
+        .del {
+          width: 96rpx;
+          background-color: rgb(177, 183, 197);
+        }
+
+        .area {
+          width: 90rpx;
+        }
+      }
+    }
+  }
+}
+</style>

+ 91 - 0
src/components/business/station/index.vue

@@ -0,0 +1,91 @@
+<template>
+  <div class="center justify-between chunk station">
+    <div>
+      <image class="mr-spac sta-img" :src="props.stationInfo.url" mode="scaleToFill" />
+    </div>
+    <div class="flex-1 mr-spac">
+      <div class="mb-spacd2 center justify-between">
+        <div class="ellipsis mr-spacd2">{{ props.stationInfo.nickName }}</div>
+        <div class="whitespace-nowrap s-fz">{{ props.stationInfo.distance }} km</div>
+      </div>
+      <div class="mb-spacd2 s-fz ellipsis gray-color sta-addr">
+        {{ props.stationInfo.address }}
+      </div>
+      <div class="flex items-baseline">
+        <span class="font-bold mr-spacd2 price-color">
+          {{ props.stationInfo.actualPrice }}
+        </span>
+        <span class="s-fz">元/公斤</span>
+      </div>
+    </div>
+    <div>
+      <!-- <div class="s-fz distance">{{ props.stationInfo.distance }} km</div> -->
+      <div class="p-color s-fz detail" v-if="props.type === '2'">
+        详情
+        <uni-icons type="right" color="" size="12" />
+      </div>
+      <div
+        class="center p-color s-fz location"
+        @click="methods.openLocation"
+        v-if="props.type === '1'"
+      >
+        导航
+        <uni-icons type="paperplane" color="" size="12" />
+      </div>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+defineOptions({
+  name: 'station',
+})
+type PropTypes = {
+  /** 类型 1:列表页面,2:待支付页面 */
+  type: '1' | '2'
+  stationInfo: GasstationVO对象
+}
+const props = withDefaults(defineProps<PropTypes>(), {
+  type: '1',
+})
+const data = {}
+const methods = {
+  openLocation() {
+    uni.openLocation({
+      latitude: Number(props.stationInfo.latitude),
+      longitude: Number(props.stationInfo.longitude),
+      name: props.stationInfo.nickName,
+      address: props.stationInfo.address,
+    })
+  },
+}
+</script>
+<style lang="scss" scoped>
+.station {
+  position: relative;
+  padding: 0;
+}
+.sta-img {
+  width: 160rpx;
+  height: 160rpx;
+}
+
+.distance {
+  position: absolute;
+  top: $p-spac;
+  right: $p-spac;
+}
+.detail {
+  position: absolute;
+  right: $p-spacd2;
+  bottom: $p-spacd2;
+}
+.location {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  width: 100rpx;
+  height: 50rpx;
+  background-color: rgba($p-color, 0.2);
+  border-top-left-radius: $p-spacd2;
+}
+</style>

+ 21 - 0
src/components/container/index.vue

@@ -0,0 +1,21 @@
+<template>
+  <div class="container">
+    <!-- 小程序内只能用v-if移除组件,如果用v-show条件false时,整个页面不显示。。 -->
+    <ay-pull v-if="store.curPage.pageConfig?.isPager">
+      <slot />
+    </ay-pull>
+    <slot v-else />
+  </div>
+</template>
+<script lang="ts" setup>
+defineOptions({
+  name: 'container',
+})
+</script>
+<style lang="scss" scoped>
+.container {
+  box-sizing: border-box;
+  height: 100vh;
+  padding: $p-spac;
+}
+</style>

+ 117 - 0
src/components/flowLine/index.vue

@@ -0,0 +1,117 @@
+<template>
+  <div class="flow-line">
+    <span class="line"></span>
+    <span class="line"></span>
+    <span class="line"></span>
+    <span class="line"></span>
+    <slot />
+  </div>
+</template>
+<script lang="ts" setup>
+defineOptions({
+  name: 'flow-line',
+})
+
+const data = {}
+const methods = {}
+</script>
+<style lang="scss" scoped>
+.flow-line {
+  position: relative;
+  overflow: hidden;
+  border-radius: $p-spacd2;
+}
+
+// .box {
+//   position: relative;
+//   // width: 420px;
+//   // height: 210px;
+//   margin: 100px auto;
+//   overflow: hidden;
+//   font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
+//   font-size: 40px;
+//   font-weight: 700;
+//   line-height: 210px;
+//   text-align: center;
+//   letter-spacing: 0.6em;
+//   border: 1px solid #eee;
+// }
+.line {
+  position: absolute;
+  z-index: 1;
+}
+
+// $map:(1:(top:0,left:0))
+.line:nth-child(1) {
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 4px;
+  background: linear-gradient(90deg, transparent, $p-color);
+  animation: move1 0.8s linear infinite;
+}
+@keyframes move1 {
+  0% {
+    left: -100%;
+  }
+  50%,
+  100% {
+    left: 100%;
+  }
+}
+.line:nth-child(2) {
+  top: -100%;
+  right: 0;
+  width: 4px;
+  height: 100%;
+  background: linear-gradient(180deg, transparent, $p-color);
+  animation: move2 0.8s linear infinite;
+  animation-delay: 0.2s;
+}
+@keyframes move2 {
+  0% {
+    top: -100%;
+  }
+  50%,
+  100% {
+    top: 100%;
+  }
+}
+
+.line:nth-child(3) {
+  right: -100%;
+  bottom: 0;
+  width: 100%;
+  height: 4px;
+  background: linear-gradient(270deg, transparent, $p-color);
+  animation: move3 0.8s linear infinite;
+  animation-delay: 0.4s;
+}
+@keyframes move3 {
+  0% {
+    right: -100%;
+  }
+  50%,
+  100% {
+    right: 100%;
+  }
+}
+.line:nth-child(4) {
+  bottom: -100%;
+  left: 0;
+  width: 4px;
+  height: 100%;
+  background: linear-gradient(360deg, transparent, $p-color);
+  animation: move4 0.8s linear infinite;
+  animation-delay: 0.6s;
+}
+@keyframes move4 {
+  0% {
+    bottom: -100%;
+  }
+  50%,
+  100% {
+    bottom: 100%;
+  }
+}
+</style>

+ 58 - 0
src/components/pull/index.vue

@@ -0,0 +1,58 @@
+<template>
+  <div>
+    <!-- #ifdef MP || APP-PLUS -->
+    <slot />
+    <!-- #endif -->
+    <!-- #ifdef H5 -->
+    <van-list @load="methods.onLoad">
+      <slot />
+    </van-list>
+    <!-- #endif -->
+    <uni-load-more :status="status" :content-text="contentText" />
+  </div>
+</template>
+<script lang="ts" setup>
+defineOptions({
+  name: 'pull',
+})
+let methods: AyContainerPullMethods = {}
+// 小程序环境内,多次创建本组件时data不会被清理,computed始终监听是第一页本组件的data,造成后续列表页面无uni-load-more状态的问题,改为将在store内computed
+const status = computed(() => store.curPage.loadMoreStatus)
+const contentText = computed(() => store.curPage.loadMoreContentText)
+// const data: PagerInfo = store.curPage.pageConfig.pagerInfo
+// let status = computed(() => {
+//   return ''
+// })
+// let contentText = computed(() => {
+//   return {}
+// })
+// onMounted(() => {
+//   data = store.curPage.pageConfig.pagerInfo
+//   console.log('onMounted', store.curPage.pageConfig)
+// })
+// const status = computed(() => {
+//   data = store.curPage.pageConfig.pagerInfo
+
+//   console.log(data)
+//   let rv = 'more'
+//   if (data.finished) {
+//     rv = 'noMore'
+//   }
+//   if (data.loading && data.isAdd) {
+//     rv = 'loading'
+//   }
+//   if (data.error) {
+//     rv = 'more'
+//   }
+//   return rv
+// })
+// const contentText = computed(() => {
+//   return {
+//     contentdown: data.error ? data.errorText : ' ',
+//     contentrefresh: data.loadingText,
+//     contentnomore: data.finishedText,
+//   }
+// })
+methods = store.curPage.pagerMethods
+</script>
+<style lang="scss" scoped></style>

+ 175 - 0
src/components/skeletons/index.vue

@@ -0,0 +1,175 @@
+<template>
+  <div
+    class="skeleton space-y"
+    :class="{ animated: animate }"
+    :style="`--color:${bgColor}`"
+    v-if="loading"
+  >
+    <div
+      class="skeleton-row space-x"
+      :class="[styleMaps[item.align || 'left'], styleMaps[item.verticalAlign || 'middle']]"
+      v-for="(item, index) in rowList"
+      :style="item.style || {}"
+      :key="index"
+    >
+      <div
+        class="skeleton-row-item space-y"
+        v-for="(item1, index1) in item.colItems"
+        :class="[item1.shape || '', item1.childRowItems ? 'no-height' : '']"
+        :key="index1"
+        :style="item1.style || { width: `${100 / item.colItems}%` }"
+      >
+        <template v-if="item1.childRowItems">
+          <div
+            class="skeleton-col-item"
+            v-for="(item2, index2) in item1.childRowItems"
+            :class="item2.shape || ''"
+            :key="index2"
+            :style="item2.style || {}"
+          ></div>
+        </template>
+      </div>
+    </div>
+  </div>
+  <div v-else><slot></slot></div>
+</template>
+
+<script>
+export default {
+  name: 'Skeleton',
+  props: {
+    bgColor: {
+      type: String,
+      default: '#f1f1f1',
+    },
+    rowList: {
+      type: Array,
+      default: () => [],
+    },
+    loading: {
+      type: Boolean,
+      default: true,
+    },
+    animate: {
+      type: Boolean,
+      default: true,
+    },
+    scale: {
+      type: String,
+    },
+  },
+  data() {
+    return {
+      styleMaps: {
+        left: 'justify-start',
+        center: 'justify-center',
+        right: 'justify-end',
+        between: 'justify-between',
+        around: 'justify-around',
+        top: 'items-start',
+        middle: 'items-center',
+        bottom: 'items-end',
+      },
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.skeleton {
+  width: 100%;
+
+  &.animated {
+    animation: blink 1.2s ease-in-out infinite;
+  }
+  & div {
+    box-sizing: border-box;
+  }
+}
+
+.skeleton-row {
+  display: flex;
+  align-content: space-between;
+  width: 100%;
+}
+
+.skeleton-row-item,
+.skeleton-col-item {
+  //   display: inline-block;
+  height: $p-spac * 2;
+  border-radius: 6rpx;
+
+  &:not(.no-height) {
+    background: var(--color);
+  }
+  &.round {
+    border-radius: 999px;
+  }
+
+  &.circle {
+    border-radius: 50%;
+  }
+  &.no-height {
+    height: auto;
+  }
+}
+.skeleton-col-item:last-child {
+  margin: 0;
+}
+.space-x > div,
+.space-x > view {
+  --tw-space-x-reverse: 0;
+  margin-right: calc($p-spacd2 * var(--tw-space-x-reverse));
+  margin-left: calc($p-spacd2 * calc(1 - var(--tw-space-x-reverse)));
+}
+
+.space-y > div,
+.space-y > view {
+  --tw-space-y-reverse: 0;
+  margin-top: calc($p-spacd2 * var(--tw-space-y-reverse));
+  margin-bottom: calc($p-spacd2 * calc(1 - var(--tw-space-y-reverse)));
+}
+
+.justify-start {
+  justify-content: flex-start;
+}
+
+.justify-end {
+  justify-content: flex-end;
+}
+
+.justify-center {
+  justify-content: center;
+}
+.justify-between {
+  justify-content: space-between;
+}
+
+.justify-around {
+  justify-content: space-around;
+}
+.items-start {
+  align-items: flex-start;
+}
+
+.items-end {
+  align-items: flex-end;
+}
+
+.items-center {
+  align-items: center;
+}
+@keyframes blink {
+  0% {
+    opacity: 1;
+  }
+
+  50% {
+    opacity: 0.6;
+  }
+
+  100% {
+    opacity: 1;
+  }
+}
+</style>

+ 11 - 0
src/directives/shortcutKeys/index.ts

@@ -0,0 +1,11 @@
+import { Directive } from 'vue'
+
+export const flowLine: Directive = {
+  mounted(el, binding, vnode) {
+    const span = document.createElement('span')
+    span.innerText = '11'
+    span.style = `position: absolute; 
+        background: red;`
+    el.appendChild(span)
+  },
+}

+ 80 - 0
src/enums/index.ts

@@ -0,0 +1,80 @@
+enum FormatType {
+  YMD = 'YYYY-MM-DD',
+  YMDHMS = 'YYYY-MM-DD HH:mm:ss',
+  YMD000 = 'YYYY-MM-DD 00:00:00',
+}
+/** 页面跳转类型 */
+enum GoPageType {
+  /** 关闭所有页面,打开到应用内的某个页面 */
+  reLaunch = 'reLaunch',
+  /** 关闭当前页面,跳转到应用内的某个页面 */
+  redirectTo = 'redirectTo',
+  /** 保留当前页面,跳转到应用内的某个页面 */
+  navigateTo = 'navigateTo',
+}
+/** 页面类型 */
+enum PageType {
+  /** 首页 */
+  home = 'home',
+  /** 底部tab页面 */
+  tabPage = 'tabPage',
+  /** 普通页面 */
+  page = 'page',
+}
+enum Events {}
+// /** 通知容器数据加载完毕 */
+// containerLoaded = 'container:loaded',
+// /** 容器通知页面加载数据 */
+// containerRefresh = 'container:refresh',
+enum LoadType {
+  /** 监听页面加载 */
+  onLoad,
+  /** 监听页面显示 */
+  onShow,
+  /** 监听页面初次渲染完成 */
+  onReady,
+  /** 下拉、上拉更新数据 */
+  refresh,
+  /** 页面返回时刷新数据 */
+  backReload,
+}
+enum ReqState {
+  /**
+   * 请求中
+   */
+  ing,
+  /**
+   * 请求成功
+   */
+  success,
+  /**
+   * 请求失败
+   */
+  fail,
+  /**
+   * 请求取消
+   */
+  cancel,
+}
+enum ErrorType {
+  /** 业务逻辑错误 */
+  business,
+  /** 网络错误 */
+  net,
+}
+const enums = {
+  FormatType,
+  PageType,
+  LoadType,
+  ReqState,
+  ErrorType,
+  Events,
+  GoPageType,
+}
+/**
+ * 生命周期类型
+ */
+export default enums
+/**
+ * 接口请求状态
+ */

+ 31 - 0
src/env.d.ts

@@ -0,0 +1,31 @@
+/// <reference types="vite/client" />
+/// <reference types="vite-svg-loader" />
+
+declare module '*.vue' {
+  import { DefineComponent } from 'vue'
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
+  const component: DefineComponent<{}, {}, any>
+  export default component
+}
+
+interface ImportMetaEnv {
+  /** 网站标题,应用名称 */
+  readonly VITE_APP_TITLE: string
+  /** 服务端口号 */
+  readonly VITE_SERVER_PORT: string
+  /** 后台接口地址 */
+  readonly VITE_SERVER_BASEURL: string
+  /** H5是否需要代理 */
+  readonly VITE_APP_PROXY: 'true' | 'false'
+  /** H5是否需要代理,需要的话有个前缀 */
+  readonly VITE_APP_PROXY_PREFIX: string // 一般是/api
+  /** 资源地址域名 */
+  readonly VITE_RESOURCE_BASEURL: string
+  /** 是否清除console */
+  readonly VITE_DELETE_CONSOLE: string
+  // 更多环境变量...
+}
+
+interface ImportMeta {
+  readonly env: ImportMetaEnv
+}

+ 2 - 0
src/interceptors/index.ts

@@ -0,0 +1,2 @@
+export { routeInterceptor } from './route'
+export { prototypeInterceptor } from './prototype'

+ 22 - 0
src/interceptors/prototype.ts

@@ -0,0 +1,22 @@
+import dayjs from 'dayjs'
+export const prototypeInterceptor = {
+  install() {
+    const orgFormat = dayjs.prototype.format
+    dayjs.prototype.format = function (...args) {
+      return orgFormat.apply(this, args.length ? args : [enums.FormatType.YMDHMS])
+    }
+
+    // 基础类型原型添加自定义方法会造成,app环境运行报错: r.onFieldChange is not a function
+    // https://ask.dcloud.net.cn/question/169588
+    // 项目中其他插件,给Array的原型增加了自定义的方法,uni-forms用的是for-in遍历的,会把这个自定义方法也遍历出来,导致也去执行 child.onFieldChange,所以报错了。
+    // 解决低版本手机不识别 array.at() 导致运行报错的问题
+    // if (typeof Array.prototype.at !== 'function') {
+    //   // eslint-disable-next-line no-extend-native
+    //   Array.prototype.at = function (index: number) {
+    //     if (index < 0) return this[this.length + index]
+    //     if (index >= this.length) return undefined
+    //     return this[index]
+    //   }
+    // }
+  },
+}

+ 26 - 0
src/interceptors/route.ts

@@ -0,0 +1,26 @@
+/**
+ * 路由拦截,通常也是登录拦截
+ */
+const navigateToInterceptor = {
+  invoke({ url }: { url: string }) {
+    let rv = true
+    const curPage = store.curPage.getPageInfo(url)
+    // 未登录 进入需要身份的页面 跳登录
+    if (curPage.identity) {
+      if (!store.user.isLogined) {
+        rv = false
+        ay.goLogin()
+      }
+    }
+    return rv
+  },
+}
+
+export const routeInterceptor = {
+  install() {
+    uni.addInterceptor('navigateTo', navigateToInterceptor)
+    uni.addInterceptor('reLaunch', navigateToInterceptor)
+    uni.addInterceptor('redirectTo', navigateToInterceptor)
+    uni.addInterceptor('switchTab', navigateToInterceptor)
+  },
+}

+ 31 - 0
src/main.ts

@@ -0,0 +1,31 @@
+import { createSSRApp } from 'vue'
+import App from './App.vue'
+import { routeInterceptor, prototypeInterceptor } from './interceptors'
+import 'virtual:uno.css'
+import '@/style/index.scss'
+import { initStore } from './utils/store'
+// #ifdef H5
+import { List } from 'vant'
+import 'vant/lib/index.css'
+// 小程序环境不支持自定义指令
+// const directives = import.meta.glob('./directives/**/*.ts', { eager: true })
+// console.log(directives)
+// #endif
+export function createApp() {
+  const app = createSSRApp(App)
+  app.use(routeInterceptor)
+  app.use(prototypeInterceptor)
+  app.use(initStore)
+  // app.mount('#app')
+  // #ifdef H5
+  app.use(List)
+  // #endif
+  // for (const [gk, gv] of Object.entries(directives)) {
+  //   for (const [k, v] of Object.entries(gv as AnyObject)) {
+  //     app.directive(k, v)
+  //   }
+  // }
+  return {
+    app,
+  }
+}

+ 111 - 0
src/manifest.json

@@ -0,0 +1,111 @@
+{
+  "name": "auyen-mobile",
+  "appid": "",
+  "description": "",
+  "versionName": "1.0.0",
+  "versionCode": "100",
+  "transformPx": false,
+  "app-plus": {
+    "usingComponents": true,
+    "nvueStyleCompiler": "uni-app",
+    "compilerVersion": 3,
+    "splashscreen": {
+      "alwaysShowBeforeRender": true,
+      "waiting": true,
+      "autoclose": true,
+      "delay": 0
+    },
+    "modules": {},
+    "distribute": {
+      "android": {
+        "permissions": [
+          "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+          "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+          "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+          "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+          "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+          "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+          "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+          "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+          "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+          "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+          "<uses-feature android:name=\"android.hardware.camera\"/>",
+          "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+        ],
+        "minSdkVersion": 30,
+        "targetSdkVersion": 30,
+        "abiFilters": [
+          "armeabi-v7a",
+          "arm64-v8a"
+        ]
+      },
+      "ios": {},
+      "sdkConfigs": {},
+      "icons": {
+        "android": {
+          "hdpi": "static/app/icons/72x72.png",
+          "xhdpi": "static/app/icons/96x96.png",
+          "xxhdpi": "static/app/icons/144x144.png",
+          "xxxhdpi": "static/app/icons/192x192.png"
+        },
+        "ios": {
+          "appstore": "static/app/icons/1024x1024.png",
+          "ipad": {
+            "app": "static/app/icons/76x76.png",
+            "app@2x": "static/app/icons/152x152.png",
+            "notification": "static/app/icons/20x20.png",
+            "notification@2x": "static/app/icons/40x40.png",
+            "proapp@2x": "static/app/icons/167x167.png",
+            "settings": "static/app/icons/29x29.png",
+            "settings@2x": "static/app/icons/58x58.png",
+            "spotlight": "static/app/icons/40x40.png",
+            "spotlight@2x": "static/app/icons/80x80.png"
+          },
+          "iphone": {
+            "app@2x": "static/app/icons/120x120.png",
+            "app@3x": "static/app/icons/180x180.png",
+            "notification@2x": "static/app/icons/40x40.png",
+            "notification@3x": "static/app/icons/60x60.png",
+            "settings@2x": "static/app/icons/58x58.png",
+            "settings@3x": "static/app/icons/87x87.png",
+            "spotlight@2x": "static/app/icons/80x80.png",
+            "spotlight@3x": "static/app/icons/120x120.png"
+          }
+        }
+      }
+    },
+    "compatible": {
+      "ignoreVersion": true
+    }
+  },
+  "quickapp": {},
+  "mp-weixin": {
+    "appid": "wxf69daeba7aec5be4",
+    "setting": {
+      "urlCheck": false
+    },
+    "usingComponents": true
+  },
+  "mp-alipay": {
+    "usingComponents": true,
+    "styleIsolation": "shared"
+  },
+  "mp-baidu": {
+    "usingComponents": true
+  },
+  "mp-toutiao": {
+    "usingComponents": true
+  },
+  "uniStatistics": {
+    "enable": false
+  },
+  "vueVersion": "3",
+  "h5": {
+    "router": {
+      "base": "/auyen-mobile/"
+    }
+  }
+}

+ 114 - 0
src/pages.json

@@ -0,0 +1,114 @@
+{
+  "globalStyle": {
+    "navigationStyle": "default",
+    "navigationBarBackgroundColor": "#f8f8f8",
+    "navigationBarTextStyle": "black",
+    "backgroundColor": "#FFFFFF",
+    "enablePullDownRefresh": false,
+    "onReachBottomDistance": 50
+  },
+  "easycom": {
+    "autoscan": true,
+    "custom": {
+      "^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue",
+      "^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)": "z-paging/components/z-paging$1/z-paging$1.vue",
+      "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
+      "^ay-(.*)": "@/components/$1/index.vue",
+      "^ayb-(.*)": "@/components/business/$1"
+    }
+  },
+  "pages": [
+    {
+      "path": "pages/index/index",
+      "type": "home",
+      "style": {
+        "enablePullDownRefresh": true
+      }
+    },
+    {
+      "path": "pages/account/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/createOrder/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/list/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/login/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/orderList/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/personCenter/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/prePay/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/webview/index",
+      "type": "page"
+    },
+    {
+      "path": "pages/webview/login",
+      "type": "page"
+    }
+  ],
+  "requiredPrivateInfos": [
+    "getLocation"
+  ],
+  "permission": {
+    "scope.userLocation": {
+      "desc": "当前位置信息将用于附近加气站搜索"
+    }
+  },
+  "subPackages": [
+    {
+      "root": "pagesSubExample",
+      "pages": [
+        {
+          "path": "index",
+          "type": "page"
+        },
+        {
+          "path": "list/index",
+          "type": "page"
+        },
+        {
+          "path": "login/index",
+          "type": "page"
+        },
+        {
+          "path": "webview/index",
+          "type": "page"
+        }
+      ],
+      "cusPages": [
+        {
+          "path": "pagesSubExample/index",
+          "type": "page"
+        },
+        {
+          "path": "pagesSubExample/list/index",
+          "type": "page"
+        },
+        {
+          "path": "pagesSubExample/login/index",
+          "type": "page"
+        },
+        {
+          "path": "pagesSubExample/webview/index",
+          "type": "page"
+        }
+      ]
+    }
+  ]
+}

+ 52 - 0
src/pages/account/index.vue

@@ -0,0 +1,52 @@
+<template>
+  <ay-container>
+    <!-- <uni-title type="h2" :title="userTitle"></uni-title> -->
+    <span class="font-bold">{{ userTitle }}</span>
+    <uni-section title="所属物流 · 可用余额" type="line"></uni-section>
+    <div class="chunk relative s-fz">
+      <div class="yebz absolute" v-if="data.accountInfo.flag === 0">[余额不足]</div>
+      <div class="flex items-baseline mb-spacd2">
+        <span class="font-bold b-fz">{{ data.accountInfo.showBalance.balance }}</span>
+        <span class="font-bold">{{ data.accountInfo.showBalance.suffix }}</span>
+        <span class="unit">{{ data.accountInfo.unit }}</span>
+        <span v-if="data.accountInfo.showDet">
+          (直销{{ data.accountInfo.carrierDirectBalance }} | 经销{{
+            data.accountInfo.carrierBalance
+          }})
+        </span>
+      </div>
+      <div class="mb-spacd4">所属物流:{{ data.accountInfo.orgName }}</div>
+      <div>车牌号{{ data.accountInfo.carNumber }}</div>
+    </div>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const methods = {}
+const userTitle = computed(() => {
+  const ui = store.user.userInfo
+  return `${ui.user_name}[${ui.mobile}]`
+})
+const data = reactive({
+  accountInfo: { showBalance: {} } as IAccountInfo,
+})
+
+ay.entrance((args) => {
+  webapi.strategy.get_driver_balance().then((res) => {
+    data.accountInfo = {
+      ...res,
+      ...aop.request.AR.getAccountInfo(res),
+    }
+  })
+})
+</script>
+<style lang="scss">
+.yebz {
+  top: $p-spac;
+  right: $p-spac;
+  color: #b8741a;
+}
+.unit {
+  margin: 0 $p-spacd2;
+}
+</style>

+ 56 - 0
src/pages/createOrder/index.vue

@@ -0,0 +1,56 @@
+<template>
+  <ay-container>
+    <div class="station">站信息</div>
+    <div class="station">驾驶员信息</div>
+    <div class="station">
+      本次加气量(公斤):
+      <uni-easyinput
+        v-model="data.gasQty"
+        type="number"
+        placeholder="请输入"
+        @confirm="methods.confirm"
+      />
+    </div>
+    <button @click="methods.confirm">确定</button>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  gasQty: 0,
+})
+const user = computed(() => store.user.userInfo)
+const pageConfig = computed(() => store.curPage.pageConfig)
+const methods = {
+  confirm() {
+    if (data.gasQty <= 0) {
+      func.native.showToast('加气量需大于零')
+      return false
+    }
+    if (data.gasQty > store.common.data.preferWeight) {
+      func.native.showToast('加气量不能超过' + store.common.data.preferWeight)
+      return
+    }
+
+    webapi.pay
+      .add({
+        cashierId: pageConfig.value.params.cashierId,
+        driverId: user.value.user_id,
+        gasQty: data.gasQty,
+        gasstationId: pageConfig.value.params.gasstationId,
+        createRole: 'driver', // 1 平台管理员 2 平台运营人员 filler 加气站企业管理者 cashier 收银员 carrier 物流公司管理者 driver 司机
+        creater: user.value.user_id,
+        createrName: user.value.user_name,
+      })
+      .then((res) => {
+        ay.goPage(config.pages.prePay_index, { params: { orderId: res.orderId } })
+      })
+  },
+}
+
+ay.entrance((args) => {
+  console.log('oncload66', args)
+})
+</script>
+
+<style lang="scss"></style>

+ 534 - 0
src/pages/index/index.vue

@@ -0,0 +1,534 @@
+<template>
+  <ay-container>
+    <div class="chunk">
+      <div class="center justify-between top">
+        <div class="center" @click="methods.goPerson">
+          <image
+            class="personal"
+            v-if="store.user.userInfo.head_url"
+            :src="store.user.userInfo.head_url"
+            mode="scaleToFill"
+          />
+          <image
+            class="personal"
+            v-else
+            src="@img/icons/turnk_number_head.png"
+            mode="scaleToFill"
+          />
+          <!-- <uni-icons type="contact" size="50" class="personal"></uni-icons> -->
+          <div>
+            <div>{{ store.user.userInfo.user_name }}</div>
+            <div class="mobile">{{ store.user.userInfo.mobile }}</div>
+          </div>
+        </div>
+        <uni-icons
+          type="scan"
+          color=""
+          class="p-color"
+          size="40"
+          @click="methods.scanCode"
+        ></uni-icons>
+      </div>
+      <div class="center">
+        <ay-flowLine class="mt-spac mb-spac">
+          <div class="qrcode">
+            <image
+              src="@img/qr@3x.png"
+              class="image"
+              mode="aspectFit"
+              v-if="data.qrcode.expire"
+              @click="methods.getQrcode"
+            />
+            <image :src="data.qrcode.img" class="image" mode="aspectFit" v-else />
+          </div>
+        </ay-flowLine>
+      </div>
+      <div class="center">
+        <template v-if="data.qrcode.expire">
+          二维码已失效
+          <div class="center p-color" @click="methods.getQrcode">
+            <uni-icons type="refresh" color="" size="24"></uni-icons>
+            刷新
+          </div>
+        </template>
+        <template v-else>有效时间:{{ data.qrcode.countdown }}</template>
+      </div>
+    </div>
+    <div class="flex">
+      <div class="chunk flex-1 s-fz mr-spac account" @click="methods.goAccount">
+        <div class="mb-spacd4">可用余额</div>
+        <div class="">
+          <span class="font-bold b-fz">{{ data.accountInfo.showBalance.balance }}</span>
+          <span class="font-bold">{{ data.accountInfo.showBalance.suffix }}</span>
+          <span class="unit">{{ data.accountInfo.unit }}</span>
+        </div>
+      </div>
+
+      <div class="chunk flex-1 center justify-start s-fz cars" @click="">
+        <div class="p-color" v-if="false">添加车辆</div>
+        <div v-else>
+          <div class="mb-spacd4">车辆管理</div>
+          <div>
+            <span class="font-bold b-fz">1</span>
+            辆
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="center justify-around mt-spac">
+      <div
+        class="text-center menu"
+        v-for="(m, i) in data.menus"
+        :key="i"
+        @click="methods.goPage(m)"
+      >
+        <img class="icon" :src="m.icon" />
+        <div>{{ m.name }}</div>
+      </div>
+    </div>
+    <div class="chuck list-app">
+      <div class="center justify-between mb-spac">
+        <div class="title">附近加气站</div>
+        <div v-if="data.userLocation" @click="methods.drawerOpen">
+          {{ data.station.curCity }}
+          <uni-icons type="down" size="12" />
+        </div>
+      </div>
+      <template v-if="data.userLocation">
+        <ayb-station
+          v-for="(la, i) in data.station.listApp"
+          :key="i"
+          :stationInfo="la"
+        ></ayb-station>
+      </template>
+      <div class="center p-color" v-else @click="methods.getListApp({ first: true })">
+        查看附近加气站
+      </div>
+    </div>
+
+    <uni-drawer ref="drawer" mode="right" :maskClick="true" :width="320">
+      <uni-indexed-list
+        :options="data.station.cityList"
+        :show-select="false"
+        @click="methods.bindClick"
+        v-if="data.station.showIndexedList"
+      />
+    </uni-drawer>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+import stompSocket from '@/utils/api/socket/stomp'
+import perpay from '@img/icons/perpay.png'
+import payhistory from '@img/icons/payhistory.png'
+import firm from '@img/icons/firm.png'
+import card from '@img/icons/card.png'
+const drawer = ref()
+const staticData = {
+  client: null,
+  entranceArgs: null as AyContainerEntryArgs,
+  location: { longitude: '', latitude: '' } as any,
+}
+const data = reactive({
+  accountInfo: { showBalance: { balance: '', suffix: '' } } as IAccountInfo,
+  /** 用户已授权定位 */
+  userLocation: false,
+  /** 二维码相关 */
+  qrcode: {
+    /** 二维码过期倒计时 */
+    countdown: '',
+    /** 二维码 */
+    img: null,
+    /** 已过期 */
+    expire: false,
+  },
+  /** 菜单列表 */
+  menus: [
+    {
+      id: 0,
+      icon: perpay,
+      name: '待支付订单',
+    },
+    {
+      id: 1,
+      name: '加气订单',
+      icon: payhistory,
+    },
+    {
+      id: 2,
+      name: '所属物流',
+      icon: firm,
+    },
+    {
+      id: 3,
+      name: '优惠卡/券',
+      icon: card,
+    },
+  ],
+  station: {
+    /** 首次呈现,解决索引滑动失效问题 */
+    showIndexedList: false,
+    cityList: [] /** 附近加气站列表 */,
+    curCity: '全部',
+    listApp: [],
+  },
+})
+const methods = ay.initMethods(
+  {
+    goPerson() {
+      ay.goPage(config.pages.personCenter_index)
+    },
+    goPage(menu) {
+      const maps = {
+        0() {
+          methods.goPrePay()
+        },
+        1() {
+          ay.goPage(config.pages.orderList_index)
+        },
+      }
+      maps[menu.id]()
+    },
+    drawerOpen() {
+      drawer.value.open()
+      data.station.showIndexedList = true
+    },
+    bindClick(args) {
+      drawer.value.close()
+      data.station.curCity = args.item.name
+      methods.getListApp()
+    },
+    goAccount() {
+      ay.goPage(config.pages.account_index)
+    },
+    /** 初始化ws */
+    initWS() {
+      stompSocket
+        .init(
+          'wss://dwx.auyen.com/websocket/sockjs',
+          // 传参
+          {
+            access_token: store.user.userInfo.token,
+            identifier: store.user.userInfo.Identifier,
+          },
+          // ws断开回调
+          () => {
+            methods.initWS()
+          },
+        )
+        .then((client) => {
+          staticData.client = client
+          // 订阅
+          const subscription = client.subscribe(
+            // 路径
+            '/user/' + store.user.userInfo.user_id + '/msg',
+            // 接收到的数据
+            (res) => {
+              const body = JSON.parse(res.body)
+              if (body.type === 1) {
+                ay.goPage(config.pages.prePay_index, { params: JSON.parse(body.content) })
+              } else if (body.type === 0) {
+                const content = JSON.parse(body.content)
+                uni
+                  .showModal({
+                    title: content.data,
+                    message: content.message,
+                  })
+                  .then(() => {})
+              }
+            },
+          )
+        })
+    },
+    // 直接调用发送即可
+    send() {
+      staticData.client.send(
+        // 路径
+        '/user/' + store.user.userInfo.user_id + '/msg',
+        {},
+        // 发送文本
+        JSON.stringify({ content: '1212' }),
+      )
+    },
+    async goPrePay() {
+      const nopayfordriver = await webapi.pay.find_unpayfordriver()
+      if (nopayfordriver) {
+        // 跳未支付
+        ay.goPage(config.pages.prePay_index, { params: { orderId: nopayfordriver.orderId } })
+        return true
+      } else {
+        func.native.showToast('暂无待支付订单!')
+        return false
+      }
+    },
+    async scanCode() {
+      if (await methods.goPrePay()) {
+        return
+      }
+      const reqStr = await uni
+        .scanCode({
+          scanType: ['qrcode'],
+        })
+        .catch((err) => {
+          func.native.showToast('二维码无效')
+          return Promise.reject(err)
+        })
+      let ret = { gasstationId: '', cashierId: '' }
+      try {
+        ret = JSON.parse(reqStr.result)
+      } catch {
+        func.native.showToast('二维码无效')
+        return
+      }
+      // const ret = {
+      //   cashierId: '710613333157822464',
+      //   gasstationId: '710613333157822464',
+      // }
+      const user = await webapi.user.find_6({ userId: ret.cashierId })
+      if (ret.gasstationId === user.user.orgId) {
+        const price = await webapi.strategy.find_price({
+          gasstationId: ret.gasstationId,
+          driverId: user.user.userId,
+        })
+        if (
+          ((price.qrcode === 0 || price.qrcode === 1) && ret.gasstationId !== ret.cashierId) || // 设置的加气站收款码
+          (price.qrcode === 2 && ret.gasstationId === ret.cashierId) // 设置的收银员
+        ) {
+          func.native.showModal({
+            title: '错误提示',
+            content: '加气站收款码已禁用,请选择收银员收款码扫码。',
+          })
+        } else {
+          const gasJudge = await webapi.strategy.driver_gas_judge({
+            driverId: user.user.userId,
+            gasstationId: ret.gasstationId,
+          })
+          if (gasJudge === 1) {
+            // 创建订单
+            ay.goPage(config.pages.createOrder_index, { params: ret })
+          } else if (gasJudge === 2) {
+            func.native.showModal({
+              title: '错误提示',
+              content:
+                '该加气站未及时补充平台气源,已无法通过大象平台为您提供优质气源,给您带来的不便深感其歉意,如有疑问可以与加气站沟通,亦可拨打大象加气平台客服电话:"400-0165388"',
+            })
+          }
+        }
+      } else {
+        func.native.showModal({
+          title: '错误提示',
+          content: '当前收银员所属企业和二维码对应的企业不一致,请联系加气站管理员。',
+        })
+      }
+    },
+    sdfsdf() {
+      webapi.strategy.get_truck_info().then((res) => {})
+    },
+    getCityList() {
+      webapi.strategy.city_list().then((res) => {
+        res.unshift({ text: '全部', children: [{ text: '全部' }] })
+        data.station.cityList = res.map((m) => {
+          return {
+            letter: m.text,
+            data: m.children.map((cm) => cm.text),
+          }
+        })
+      })
+    },
+    async getListApp({ cras = config.common.defAyContainerRefreshArgs, first = false } = {}) {
+      // 非首次 && 未授权
+      if (!first && !data.userLocation) {
+        // 取消加载中效果
+        ay.containerLoaded({
+          reqState: enums.ReqState.cancel,
+        })
+        return
+      }
+      let location = staticData.location
+      // 上拉不重新获取位置
+      if (!cras.isAdd) {
+        location = await uni.getLocation()
+        staticData.location = location
+      }
+      data.userLocation = true
+      webapi.strategy
+        .list_mini(
+          {
+            page: cras.page,
+            size: cras.size,
+            param: {
+              city: data.station.curCity === '全部' ? '' : data.station.curCity,
+              longitude: location.longitude.toString(),
+              latitude: location.latitude.toString(),
+            },
+          },
+          { showLoading: first || !cras.isAdd },
+        )
+        .then((res) => {
+          if (cras.isAdd) {
+            data.station.listApp.push(...res.records)
+          } else {
+            data.station.listApp = res.records
+          }
+        })
+    },
+
+    /** 时长处理 */
+    duration(times) {
+      if (times) {
+        let m: number | string = Math.floor(Number(times) / 60)
+        let s: number | string = Math.floor(Number(times) % 60)
+        if (s < 10) {
+          s = `0${s}`
+        }
+        if (m < 10) {
+          m = `0${m}`
+        }
+        return `${m}:${s}`
+      }
+    },
+    getQrcode() {
+      return webapi.strategy.get_user_qrcode().then(async (res) => {
+        // await func.awaiter()
+        data.qrcode.img = res
+        data.qrcode.expire = false
+        func.timer({
+          seconds: 300,
+          ticker(tick) {
+            data.qrcode.countdown = methods.duration(tick)
+          },
+          ender() {
+            data.qrcode.expire = true
+          },
+        })
+      })
+    },
+  },
+  {
+    scanCode: { showLoading: true },
+  },
+)
+ay.entrance(
+  (args) => {
+    staticData.entranceArgs = args
+    // webapi.strategy.getCarNumber<null, { truckId: string }>().then((res) => {
+    //   webapi.strategy.getQrcode({}, { appendUrl: '/' + res.truckId }).then((resq) => {
+    //     data.qrcode = resq
+    //   })
+    // })
+    const init = async () => {
+      // #ifdef MP
+      await uni
+        .getSetting()
+        .then((res) => {
+          if (res.authSetting['scope.userLocation']) {
+            data.userLocation = true
+          }
+        })
+        .catch()
+      // #endif
+      methods.getListApp({ cras: args.cras })
+      webapi.strategy.get_driver_balance().then((res) => {
+        data.accountInfo = {
+          ...res,
+          ...aop.request.AR.getAccountInfo(res),
+        }
+      })
+    }
+    if (args.loadType === enums.LoadType.onLoad) {
+      methods.initWS()
+      methods.getQrcode()
+      methods.getCityList()
+      init()
+    }
+
+    if (args.loadType === enums.LoadType.refresh) {
+      if (args.cras.isAdd) {
+        methods.getListApp({ cras: args.cras })
+      } else {
+        init()
+      }
+    }
+  },
+  {
+    // addLoadTypes: [enums.LoadType.onLoad],
+  },
+)
+</script>
+
+<style lang="scss">
+.top {
+  padding-bottom: $p-spac;
+  border-bottom: 1px dashed;
+  .personal {
+    width: 100rpx;
+    height: 100rpx;
+    margin-right: $p-spac;
+    border-radius: $p-spac;
+  }
+  .mobile {
+    margin-top: $p-spacd2;
+    font-size: $s-fz;
+  }
+}
+.qrcode {
+  width: 400rpx;
+  height: 400rpx;
+  overflow: hidden;
+  border-radius: $p-spacd2;
+  .image {
+    width: 480rpx;
+    height: 480rpx;
+    margin: -40rpx;
+  }
+}
+.truck {
+  width: 152rpx;
+  height: 116rpx;
+}
+
+.unit {
+  margin: 0 $p-spacd2;
+}
+$bgc: rgba($p-color, 0.4);
+.account {
+  background-color: rgba($p-price-color, 0.1);
+}
+.cars {
+  position: relative;
+  overflow: hidden;
+  &::after {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    content: '';
+    background-image: linear-gradient($bgc, $bgc), url('@img/truck.svg');
+    background-repeat: no-repeat;
+    background-position: right;
+    background-size: contain;
+    opacity: 0.2;
+  }
+}
+.menu {
+  font-size: $s-fz;
+  .icon {
+    width: 80rpx;
+    height: 80rpx;
+    margin-bottom: $p-spacd2;
+    border-radius: 50%;
+  }
+}
+.list-app {
+  margin-top: $p-spac * 2;
+  .title {
+    font-size: $p-fz * 1.2;
+    font-weight: bold;
+  }
+}
+// 为了让左侧索引中文竖排
+::v-deep .uni-indexed-list__menu-item {
+  width: 20px;
+}
+</style>

+ 64 - 0
src/pages/list/index.vue

@@ -0,0 +1,64 @@
+<template>
+  <ay-container>
+    {{ store.webapi.strategy.list_app.ing }}
+    <!-- <button @click="methods.test">aaa</button> -->
+    <div class="item" v-for="item in data.list" :key="item">
+      <!-- {{ item }} -->
+      <img class="img" mode="aspectFit" :src="item.url" />
+    </div>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  list: [] as GasstationVO对象[],
+  loading: false,
+  pageInfo: {},
+})
+const methods = {}
+
+ay.entrance(
+  (args) => {
+    console.log('oncload66', args)
+
+    webapi.strategy.list_app
+      .post<{ param: { truckId } }>(
+        {
+          page: args.cras.page,
+          size: args.cras.size,
+          param: {
+            city: '',
+            longitude: '',
+            latitude: '',
+            truckId: '800136756804452355',
+          },
+        },
+        { showLoading: !args.cras.isAdd },
+      )
+      .then((res) => {
+        if (args.cras.isAdd) {
+          data.list.push(...res.records)
+        } else {
+          data.list = res.records
+        }
+      })
+  },
+  {
+    // defAyContainerRefreshArgs: {
+    //   size: 10,
+    // },
+    // addLoadTypes: [enums.LoadType.onShow],
+  },
+)
+</script>
+
+<style lang="scss">
+.item {
+  width: 100%;
+  text-wrap: wrap;
+  .img {
+    width: 200rpx;
+    height: 300rpx;
+  }
+}
+</style>

+ 150 - 0
src/pages/login/index.vue

@@ -0,0 +1,150 @@
+<template>
+  <ay-container>
+    <div class="flex-col center justify-around login-con">
+      <div class="center">
+        <image class="logo" src="/static/logo.png" mode="scaleToFill" />
+        <span class="title">优质加气 大象帮你</span>
+      </div>
+      <div class="p-spac login-phone">
+        <button
+          class="login-btn"
+          :loading="store.webapi.user.token.ing"
+          :disabled="store.webapi.user.token.ing"
+          :open-type="data.check ? 'getPhoneNumber' : ''"
+          :phone-number-no-quota-toast="false"
+          @getphonenumber="methods.getphonenumber"
+          @click="methods.clickLogin"
+        >
+          手机号快捷登录
+        </button>
+        <div class="center" :class="{ 'accet-button-shake': data.shake }">
+          <checkbox-group @change="methods.checkChange">
+            <label class="center">
+              <checkbox value="check" :checked="data.check" class="checkbox" />
+              <span>已阅读并同意:</span>
+            </label>
+          </checkbox-group>
+
+          <span class="p-color" @click="methods.agreement">服务条款、隐私协议</span>
+        </div>
+      </div>
+      <div class="p-color login-H5" @click="methods.goLoginH5">大象加气“驾驶员”账号登录</div>
+    </div>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  check: false,
+  shake: false,
+})
+const methods = {
+  checkChange(e) {
+    data.check = !!e.detail.value.length
+  },
+  async clickLogin() {
+    if (data.check) return
+    func.native.showToast('请阅读并同意服务条款和隐私协议')
+    data.shake = true
+    await func.awaiter(400)
+    data.shake = false
+  },
+  async getphonenumber(e) {
+    if (e.detail.errno) {
+      // func.native.showToast(e.detail.errMsg)
+      return
+    }
+    const loginRes = await uni.login()
+    const si = config.common.SystemInfo
+    webapi.user
+      .token({
+        auth_type: 'mini',
+        // 模拟设备唯一性
+        grant_type: si.model + func.newGuid(),
+        // 临时登录凭证
+        password: loginRes.code,
+        // 加密手机号信息
+        username: e.detail.code,
+      })
+      .then((res) => {
+        store.user.initUserInfo(res)
+        ay.goHome()
+      })
+  },
+  agreement() {
+    ay.goPage(config.pages.webview_index, {
+      params: {
+        url: ay.getResourceUrl('#/agreement'),
+      },
+    })
+  },
+  goLoginH5() {
+    ay.goPage(config.pages.webview_login)
+  },
+}
+ay.entrance(({ exts }) => {
+  // #ifdef MP
+  uni.hideHomeButton()
+  // #endif
+  if (exts) {
+    // store.user.initUserInfo(exts.detail.data[0])
+    // ay.goPage(config.pages.index_index)
+    // store.curPage.pageConfig.prePage.onceBackReloadArgs = {}
+    // ay.navigateBack()
+  }
+})
+</script>
+<style lang="scss" scoped>
+.sss11 {
+  color: red;
+}
+.login-con {
+  height: 100%;
+}
+.login-phone {
+  box-sizing: border-box;
+  width: 100%;
+  font-size: 26rpx;
+  .login-btn {
+    margin-bottom: 20rpx;
+    color: #fff;
+    background: #00ad65;
+    border-radius: 50rpx;
+  }
+  .checkbox {
+    transform: scale(0.6);
+  }
+}
+.logo {
+  width: 100rpx;
+  height: 100rpx;
+}
+.title {
+  margin-left: 30rpx;
+  font-size: 40rpx;
+  font-weight: bold;
+}
+.login-H5 {
+  margin-top: 300rpx;
+}
+.accet-button-shake {
+  animation: shake 0.4s infinite;
+}
+@keyframes shake {
+  0% {
+    transform: translate(6rpx, 4rpx);
+  }
+  25% {
+    transform: translate(-6rpx, -4rpx);
+  }
+  50% {
+    transform: translate(6rpx, 4rpx);
+  }
+  75% {
+    transform: translate(-6rpx, -4rpx);
+  }
+  100% {
+    transform: translate(6rpx, 4rpx);
+  }
+}
+</style>

+ 303 - 0
src/pages/orderList/index.vue

@@ -0,0 +1,303 @@
+<template>
+  <ay-container>
+    <div>
+      <div class="center mb-spac">
+        <uni-datetime-picker
+          v-model="data.range"
+          type="daterange"
+          :clearIcon="false"
+          @change="methods.changeDate"
+        />
+        <uni-badge type="primary" :text="data.checkCount" absolute="rightTop" :offset="[-3, 3]">
+          <uni-icons
+            class="ml-spacd2"
+            type="settings"
+            color=""
+            size="24"
+            @click="methods.showFilters"
+          />
+        </uni-badge>
+      </div>
+      <div class="chunk child-c-jb" v-for="(o, i) in data.orderList" :key="i">
+        <div>
+          <div class="font-bold p-fz">{{ o.nickName }}</div>
+          <div>{{ func.convert.getOrderStatusStr(o.orderStatus) }}</div>
+        </div>
+        <div>
+          <div>加气量(公斤)</div>
+          <div>{{ o.gasQty }}</div>
+        </div>
+        <div>
+          <div>小计(元)</div>
+          <div class="font-bold bs-fz">¥{{ o.allAmount }}</div>
+        </div>
+        <div>
+          <div class="gray-color">{{ func.getDate(o.createDate).format() }}</div>
+        </div>
+      </div>
+    </div>
+    <uni-drawer
+      ref="drawer"
+      mode="right"
+      :maskClick="true"
+      :width="config.common.SystemInfo.windowWidth"
+      @change="methods.drawerChange"
+    >
+      <div class="m-spac">
+        <div class="center justify-between b-fz mb-spac">
+          <span></span>
+          <!-- <uni-icons class="hidden" type="closeempty" color="" size="24" /> -->
+
+          <div class="font-bold">
+            <span>筛选</span>
+            <span v-if="checkCount">
+              <span>·</span>
+              <span class="p-color">{{ checkCount }}</span>
+            </span>
+          </div>
+
+          <uni-icons type="closeempty" color="" size="24" @click="methods.closeFilters" />
+        </div>
+        <div>
+          <div>
+            <div v-for="(f, i) in filtersView" :key="i">
+              <uni-section
+                :class="'section' + f.type"
+                :title="f.label"
+                titleFontSize="18px"
+                type="line"
+              ></uni-section>
+              <!-- type="circle" -->
+              <!-- <div class="font-bold mb-spac" v-else>{{ f.label }}</div> -->
+              <div class="center justify-between flex-wrap">
+                <div
+                  class="center whitespace-nowrap p-spacd2 chunk f-item"
+                  :class="{ checked: item.checked, isall: item.value === staticData.nullValue }"
+                  v-for="(item, ii) in f.items"
+                  :key="ii"
+                  @click="methods.filterCheck(f, item)"
+                >
+                  <!-- <div class="tag-rb" v-if="item.isPerson">个人支付</div> -->
+                  {{ item.label }}
+                </div>
+                <div class="f-item" v-if="f.items.length % 3 === 2"></div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="btns">
+          <button @click="methods.clearFilters">清空</button>
+          <button type="primary" @click="methods.saveFilters">确定</button>
+        </div>
+      </div>
+    </uni-drawer>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const staticData = {
+  // 缓存筛选条件key名
+  fcn: 'filterCheckeds',
+  // 全部选项的value值
+  nullValue: '-1',
+  payTypeGroups: [
+    { label: '支付方式', type: 0, hasStatus: ['-1', '10'] },
+    { label: '个人支付', type: 1, hasStatus: ['3'] },
+    { label: '所属物流', type: 1, hasStatus: ['0', '1', '2'] },
+  ],
+}
+const drawer = ref()
+const data = reactive({
+  /** 确定选中条件数量 */
+  checkCount: 0,
+  filters: [
+    {
+      label: '结算状态',
+      value: 'settleStatus',
+      items: func.convert.getCheckItem(config.common.orderStatus),
+    },
+    {
+      label: '支付方式',
+      value: 'payType',
+      items: func.convert.getCheckItem(config.common.payType),
+    },
+    {
+      label: '交易模式',
+      value: 'tradeType',
+      items: func.convert.getCheckItem(config.common.tradeType),
+    },
+  ] as any[],
+  range: [],
+  orderList: [] as 订单详情[],
+})
+const filtersView = computed(() => {
+  const rv = [...data.filters]
+  const payTypeIndex = rv.findIndex((f) => f.value === 'payType')
+  const payTypeItem = rv[payTypeIndex]
+  const groups = staticData.payTypeGroups.map((m) => {
+    return {
+      label: m.label,
+      type: m.type,
+      items: payTypeItem.items.filter((f) => m.hasStatus.includes(f.value)),
+      target: payTypeItem,
+    }
+  })
+
+  rv.splice(payTypeIndex, 1, ...groups)
+  return rv
+})
+/** 选中的条件 */
+const filterCheckeds = computed(() => {
+  const fcs: Record<string, string[]> = {}
+  data.filters.forEach((f) => {
+    const curItems = f.items
+      .filter((ff) => ff.checked && ff.value !== staticData.nullValue)
+      .map((m) => m.value)
+    if (curItems.length) {
+      fcs[f.value] = curItems
+    }
+  })
+  return fcs
+})
+/** 临时选中条件数量 */
+const checkCount = computed(() =>
+  Object.values(filterCheckeds.value)
+    .map((m) => m.length + (m.includes(staticData.nullValue) ? -1 : 0))
+    .reduce((a, b) => a + b, 0),
+)
+const methods = {
+  /** 从缓存 初始化查询条件选中状态 */
+  getStoreFilterCheckeds() {
+    return uni.getStorageSync(staticData.fcn) || {}
+  },
+  /** 从缓存 初始化查询条件选中状态 */
+  initFiltersCheck() {
+    const filterCheckeds: any = methods.getStoreFilterCheckeds()
+    if (filterCheckeds) {
+      data.filters.forEach((f) => {
+        f.items.forEach((ff) => {
+          ff.checked = filterCheckeds[f.value]?.includes(ff.value)
+        })
+      })
+    }
+  },
+  /** 计算条件选中数量 */
+  setCheckCount() {
+    const filterCheckeds = methods.getStoreFilterCheckeds()
+    if (filterCheckeds) {
+      data.checkCount = Object.values<string[]>(filterCheckeds)
+        .map((m) => m.length + (m.includes(staticData.nullValue) ? -1 : 0))
+        .reduce((a, b) => a + b, 0)
+    }
+  },
+  drawerChange(args) {
+    // 打开抽屉初始化条件选择状态
+    if (args) {
+      methods.initFiltersCheck()
+    } else {
+      // 关闭抽屉计算选中数量
+
+      methods.setCheckCount()
+    }
+  },
+  saveFilters() {
+    // 有选中的条件
+    if (Object.keys(filterCheckeds.value).length) {
+      uni.setStorageSync(staticData.fcn, filterCheckeds.value)
+    } else {
+      uni.removeStorageSync(staticData.fcn)
+    }
+    methods.closeFilters()
+    methods.getOrderList()
+  },
+  clearFilters() {
+    data.filters.forEach((f) => {
+      f.items.forEach((ff) => {
+        ff.checked = false
+        if (ff.value === staticData.nullValue) {
+          ff.checked = true
+        }
+      })
+    })
+  },
+  filterCheck(fg, item) {
+    // 点击全部
+    const realfg = fg.target ? fg.target : fg
+    if (item.value === staticData.nullValue) {
+      realfg.items.forEach((f) => (f.checked = false))
+      item.checked = true
+    } else {
+      item.checked = !item.checked
+
+      realfg.items[0].checked = false
+    }
+  },
+  getOrderList(cras = config.common.defAyContainerRefreshArgs) {
+    const paramFilters: Record<string, string> = {}
+    const storeFilterCheckeds = methods.getStoreFilterCheckeds()
+    Object.keys(storeFilterCheckeds).forEach(
+      (f) => (paramFilters[f] = storeFilterCheckeds[f].toString()),
+    )
+    webapi.strategy
+      .get_order_list<{ param: { gasstationId?: string } }>(
+        {
+          page: cras.page,
+          size: cras.size,
+          param: {
+            startTime: func.getDate(data.range[0]).format(enums.FormatType.YMD000),
+            endTime: func.getDate(data.range[1]).format(enums.FormatType.YMD000),
+            ...paramFilters,
+          },
+        },
+        { showLoading: !cras.isAdd },
+      )
+      .then((res) => {
+        if (cras.isAdd) {
+          data.orderList.push(...res.page.records)
+        } else {
+          data.orderList = res.page.records
+        }
+      })
+  },
+  changeDate(e) {
+    methods.getOrderList()
+  },
+  showFilters() {
+    drawer.value.open()
+  },
+  closeFilters() {
+    drawer.value.close()
+  },
+}
+
+ay.entrance((args) => {
+  if (args.loadType === enums.LoadType.onLoad) {
+    // 初始化日期范围
+    const endDate = func.getDate(Date.now())
+    data.range = [endDate.add(-30, 'day'), endDate]
+
+    methods.setCheckCount()
+  }
+  methods.getOrderList(args.cras)
+})
+</script>
+
+<style lang="scss">
+.f-item {
+  box-sizing: border-box;
+  width: 31%;
+  &.isall {
+    background: #fff;
+  }
+  &.checked {
+    color: $p-color;
+  }
+}
+::v-deep .section1.uni-section {
+  margin-top: -$p-spac;
+  margin-bottom: -$p-spacd2;
+}
+::v-deep .section0.uni-section {
+  @apply font-bold;
+}
+</style>

+ 27 - 0
src/pages/personCenter/index.vue

@@ -0,0 +1,27 @@
+<template>
+  <ay-container>
+    <button @click="methods.logout">退出</button>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({})
+const methods = {
+  logout() {
+    webapi.user
+      .logout({ client_id: store.user.service, user_id: store.user.userInfo.user_id })
+      .then((res) => {
+        store.user.clearUserInfo()
+        ay.goLogin()
+      })
+  },
+}
+
+ay.entrance((args) => {
+  webapi.user.find_6({ userId: store.user.userInfo.user_id }).then((res) => {
+    console.log(res)
+  })
+})
+</script>
+
+<style lang="scss"></style>

+ 222 - 0
src/pages/prePay/index.vue

@@ -0,0 +1,222 @@
+<template>
+  <ay-container>
+    <ay-skeletons :rowList="data.rowList" :loading="loading">
+      <div class="station">
+        <ayb-station type="2" :stationInfo="data.stationInfo" />
+      </div>
+      <div class="chunk2">
+        <span class="mr-spacd4">加气量</span>
+        <span class="font-bold b-fz mr-spacd4">{{ data.orderDetail.gasQty }}</span>
+        <span>公斤</span>
+      </div>
+      <uni-section title="选择支付方式" type="line"></uni-section>
+      <div class="flex chunk s-fz" @click="methods.choose(0)">
+        <span class="mr-spacd2 radio" :class="{ checked: data.fpayType === 0 }"></span>
+        <div class="chunk2">
+          <div>个人支付</div>
+          <div>
+            结算金额 ¥ {{ personPay?.amount }} 元 (结算价 ¥ {{ personPay?.actualPrice }} 元/公斤)
+          </div>
+        </div>
+      </div>
+      <div class="flex chunk s-fz" @click="methods.choose(1)" v-if="carrierPay">
+        <span class="mr-spacd2 radio" :class="{ checked: data.fpayType === 1 }"></span>
+        <div class="chunk2">
+          <div>所属物流支付</div>
+          <div>
+            结算金额 ¥ {{ carrierPay?.amount }} 元 (结算价 ¥
+            {{ carrierPay?.actualPrice }} 元/公斤)
+          </div>
+        </div>
+      </div>
+      <div class="chunk2">
+        <div>
+          <div>创建订单</div>
+          <div>{{ data.orderDetail.createDate }}</div>
+        </div>
+        <div>
+          <div>订单编号</div>
+          <div>{{ data.orderDetail.orderId }}</div>
+        </div>
+        <div>
+          <div>驾驶员</div>
+          <div>{{ data.orderDetail.driverName }}</div>
+        </div>
+      </div>
+      <div class="btns">
+        <button
+          type="primary"
+          :disabled="canPay"
+          :loading="store.webapi.pay.order_pay.ing"
+          @click="methods.pay()"
+        >
+          {{ curPay?.buttonMsg }}
+        </button>
+      </div>
+    </ay-skeletons>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  /** 页面选择支付类型: -1:未选择 0:个人:1:物流 */
+  fpayType: -1,
+  orderDetail: {} as 订单详情,
+  stationInfo: {} as GasstationVO对象,
+  paysel: {} as 待支付订单_可选支付方式获取实体类,
+  loading: true,
+  rowList: [
+    {
+      align: 'left',
+      verticalAlign: 'top',
+      colItems: [
+        {
+          style: {
+            width: '168rpx',
+            height: '168rpx',
+            'flex-shrink': 0,
+          },
+        },
+        {
+          style: {
+            width: '100%',
+          },
+          childRowItems: [
+            {
+              style: {
+                width: '80%',
+              },
+            },
+            {
+              style: {
+                width: '100%',
+              },
+            },
+            {
+              style: {
+                width: '100%',
+              },
+            },
+          ],
+        },
+      ],
+    },
+    ...Array(20).fill({
+      align: 'left',
+      colItems: 1,
+    }),
+    {
+      align: 'left',
+      colItems: [
+        {
+          style: {
+            width: '60%',
+          },
+        },
+      ],
+    },
+  ],
+})
+
+const loading = computed(
+  () =>
+    !(
+      store.webapi.strategy.get_order_detail.success &&
+      store.webapi.strategy.paysel.success &&
+      store.webapi.strategy.find_for_mini.success
+    ),
+)
+
+const canPay = computed(() => !curPay.value?.buttonEnable && store.webapi.pay.order_pay.ing)
+const pageParams = computed(() => store.curPage.pageConfig.params)
+const personPay = computed(() => data.paysel?.personPay)
+const carrierPay = computed(() => data.paysel?.carrierPay)
+/** 当前支付方式 */
+const curPay = computed<待支付订单_可选支付方式物流支付实体类>(() =>
+  data.fpayType === 0
+    ? {
+        ...data.paysel?.personPay,
+        wxAmount: data.paysel.personPay.amount,
+      }
+    : data.paysel?.carrierPay,
+)
+
+const methods = {
+  choose(fpayType) {
+    data.fpayType = fpayType
+  },
+  async pay() {
+    if (data.fpayType === -1) {
+      func.native.showToast('请选择支付方式')
+      return
+    }
+    const params: OrderPayParam = {
+      orderId: pageParams.value.orderId,
+      payType: personPay.value.payType,
+    }
+    // 需要微信支付
+    if ([1, 2, 3].includes(curPay.value.payType)) {
+      const li = await uni.login()
+      params.jsCode = li.code
+      params.wxAmount = curPay.value.wxAmount
+    }
+    // 物流支付
+    if (data.fpayType === 1) {
+      params.carNumber = carrierPay.value.carNumber
+      params.carrierOrgId = carrierPay.value.carrierOrgId
+      params.carrierOrgName = carrierPay.value.carrierOrgName
+      params.linked = carrierPay.value.linked
+      params.tradeType = carrierPay.value.tradeType
+      params.truckId = carrierPay.value.truckId
+    }
+    webapi.pay.order_pay(params).then((res) => {
+      console.log(res)
+      uni.requestPayment({
+        ...JSON.parse(res.payInfo),
+        success() {
+          func.native.showToast({
+            icon: 'success',
+            title: '支付成功',
+          })
+        },
+        fail() {
+          func.native.showToast({
+            icon: 'fail',
+            title: '支付失败',
+          })
+          // 上报异常
+        },
+      })
+    })
+  },
+  getOrderDetail() {
+    return webapi.strategy
+      .get_order_detail({ orderId: pageParams.value.orderId, orderType: 1 })
+      .then(async (res) => {
+        data.orderDetail = res
+        const location = await uni.getLocation()
+        data.stationInfo = await webapi.strategy.find_for_mini({
+          gasstationId: res.gasstationId,
+          longitude: location.longitude.toString(),
+          latitude: location.latitude.toString(),
+        })
+      })
+  },
+  paysel() {
+    webapi.strategy.paysel({ orderId: pageParams.value.orderId }).then((res) => {
+      data.paysel = res
+      // 仅“(散户)个人支付”选项 时,保持 其 选中
+      if (!res.carrierPay) {
+        data.fpayType = 0
+      }
+    })
+  },
+}
+
+ay.entrance(async (args) => {
+  methods.getOrderDetail()
+  methods.paysel()
+})
+</script>
+
+<style lang="scss"></style>

+ 14 - 0
src/pages/webview/index.vue

@@ -0,0 +1,14 @@
+<template>
+  <web-view :src="data.url" @message="methods.bindmessage" />
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  url: store.curPage.pageConfig.params.url,
+})
+const methods = {
+  bindmessage(e) {},
+}
+</script>
+
+<style></style>

+ 23 - 0
src/pages/webview/login.vue

@@ -0,0 +1,23 @@
+<template>
+  <web-view :src="data.url" @message="methods.bindmessage" />
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  // url: `http://localhost:8118/#/login?reLaunchPage=${config.pages.index_index._url}`,
+  url: ay.getResourceUrl(`#/login?reLaunchPage=${config.pages.index_index._url}`),
+})
+const methods = {
+  bindmessage(e) {
+    store.user.initUserInfo(e.detail.data[0])
+    // store.curPage.pageConfig.prePage.onceBackReloadArgs = { exts: e }
+    // ay.navigateBack({ aceas: { exts: e } })
+    // // 官方文档使用方式
+    // console.log('e.detail.data', e.detail.data)
+    // // 真机调试发现的方式
+    // console.log('e.target.data', e.target.data)
+  },
+}
+</script>
+
+<style></style>

+ 61 - 0
src/pagesSubExample/index.vue

@@ -0,0 +1,61 @@
+<template>
+  <ay-container>
+    <view class="mt-12">
+      <image src="/static/logo.png" alt="" class="w-28 h-28 block mx-auto" />
+    </view>
+    <view class="text-center text-4xl main-title-color mt-4">auyen-mobile</view>
+    <view class="text-center text-2xl mt-2 mb-8">最好用的 uniapp 开发模板</view>
+
+    <view class="text-justify max-w-100 m-auto text-4 indent mb-2">{{ description }}</view>
+    <view class="text-center mt-8">
+      当前平台是:
+      <text class="text-green-500">{{ PLATFORM.platform }}</text>
+    </view>
+    <button @click="methods.show">弹出日期组件</button>
+    <button @click="methods.gopage">跳转webview</button>
+    <uni-calendar ref="calendar" :insert="false" @confirm="methods.confirm" />
+    <!-- <ayb-carNumber></ayb-carNumber> -->
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+import PLATFORM from '@/utils/platform'
+import dayjs from 'dayjs'
+
+defineOptions({
+  name: 'Home',
+})
+
+// 获取屏幕边界到安全区域距离
+const { safeAreaInsets } = uni.getSystemInfoSync()
+const author = ref('大象移动端')
+const description = ref(
+  'auyen-mobile 是一个集成了多种工具和技术的 uniapp 开发模板,由 uniapp + Vue3 + Ts + Vite4 + UnoCss + UniUI + VSCode 构建,模板具有代码提示、自动格式化、统一配置、代码片段等功能,并内置了许多常用的基本组件和基本功能,让你编写 uniapp 拥有 best 体验。',
+)
+ay.entrance((args) => {
+  console.log(args)
+  // webapi.account.add().catch()
+  ay.containerLoaded()
+})
+
+const calendar = ref(null)
+
+const methods = {
+  gopage() {
+    ay.goPage(config.subPages.pagesSubExample.webview_index)
+  },
+  show() {
+    calendar.value.open()
+  },
+  confirm(date) {
+    console.log(date)
+    console.log(dayjs(date.fulldate).format('YYYY-MM-DD HH:mm:ss'), 33)
+  },
+}
+</script>
+
+<style>
+.main-title-color {
+  color: #d14328;
+}
+</style>

+ 63 - 0
src/pagesSubExample/list/index.vue

@@ -0,0 +1,63 @@
+<template>
+  <ay-container>
+    <!-- <button @click="methods.test">aaa</button> -->
+    <div v-for="item in data.list" :key="item">{{ item }}</div>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  list: [],
+  loading: false,
+  pageInfo: {},
+})
+const methods = {}
+ay.entrance(
+  (args) => {
+    console.log('oncload', args)
+    webapi.strategy.listApp
+      .post(
+        {
+          page: args.cras.page,
+          size: args.cras.size,
+          param: {
+            city: '',
+            longitude: '',
+            latitude: '',
+            truckId: '800136756804452355',
+          },
+        },
+        { showLoading: !args.cras.isAdd },
+      )
+      .then((res) => {
+        if (args.cras.isAdd) {
+          data.list.push(...res.records)
+        } else {
+          data.list = res.records
+        }
+        ay.containerLoaded({
+          reqState: enums.ReqState.success,
+          pages: res.pages,
+        })
+      })
+      .catch((err) => {
+        ay.containerLoaded({
+          // loadingText:  'sdfsdf',
+          // finishedText: 'dddddd',
+          errorText: '加载失败',
+          reqState: enums.ReqState.fail,
+        })
+        console.log('err', err)
+      })
+  },
+  {
+    // addLoadTypes: [enums.LoadType.onLoad],
+  },
+)
+</script>
+
+<style>
+.main-title-color {
+  color: #d14328;
+}
+</style>

+ 63 - 0
src/pagesSubExample/login/components/login.vue

@@ -0,0 +1,63 @@
+<template>
+  <uni-forms ref="loginForm" :modelValue="data" :rules="rules">
+    {{ store.user.userInfo.token }}
+    {{ store.webapi.user.token.ing }}
+    <!-- {{ store.webapi.user.token.fail }} -->
+    <uni-forms-item label="手机号" required name="username">
+      <uni-easyinput v-model="data.username" placeholder="请输入姓名" />
+    </uni-forms-item>
+    <uni-forms-item label="密码" required name="password">
+      <uni-easyinput type="password" v-model="data.password" placeholder="请输入密码" />
+    </uni-forms-item>
+    <button type="primary" @click="methods.login">登录</button>
+  </uni-forms>
+</template>
+<script lang="ts" setup>
+// import store from '@/store'
+const user = store.user
+const loginForm = ref()
+const rules = {
+  username: {
+    rules: [
+      {
+        required: true,
+        errorMessage: '请输入用户名',
+      },
+    ],
+  },
+}
+const data = reactive({
+  username: '',
+  password: '',
+})
+onMounted(() => {
+  console.log(store.curPage.pageConfig)
+})
+const methods = {
+  login() {
+    // webapi.user.addByOrgAdmin()
+    // return
+    loginForm.value
+      .validate()
+      .then(() => {
+        const lgd = {
+          grant_type: 'password',
+          auth_type: 'password',
+          ...data,
+        }
+        webapi.user
+          .token(lgd, { showLoading: true, loadingText: '登录中...' })
+          .then((data) => {
+            store.user.initUserInfo(data)
+            ay.goPage(store.curPage.pageConfig.params.backPage)
+          })
+          .catch((err) => {
+            console.log('err', err)
+          })
+      })
+      .catch((err) => {
+        console.log(err)
+      })
+  },
+}
+</script>

+ 29 - 0
src/pagesSubExample/login/components/upload.vue

@@ -0,0 +1,29 @@
+<template>
+  <view class="p-4 text-center">
+    <button @click="methods.run">选择图片并上传</button>
+    <view v-if="store.webapi.message.uploadFile.ing" class="text-blue h-10">上传...</view>
+    <template v-else>
+      <view class="w-full">
+        <image v-if="data.imgUrl" :src="data.imgUrl" mode="scaleToFill" />
+      </view>
+    </template>
+  </view>
+</template>
+
+<script lang="ts" setup>
+const data = reactive({
+  imgUrl: '',
+})
+const methods = {
+  run() {
+    webapi.message.uploadFile().then((res) => {
+      data.imgUrl = res
+      console.log(res)
+    })
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+//
+</style>

+ 60 - 0
src/pagesSubExample/login/index.vue

@@ -0,0 +1,60 @@
+<template>
+  <ay-container>
+    <view
+      class="bg-white overflow-hidden pt-2 px-4"
+      :style="{ marginTop: safeAreaInsets?.top + 'px' }"
+    >
+      {{ user.userInfo }}
+      <view class="text-center text-3xl mt-8">
+        我是
+        <text class="text-red-500">大象移动端</text>
+      </view>
+      <login />
+      <UploadComp />
+      <button class="chooseAvatar" open-type="chooseAvatar" @chooseavatar="methods.chooseavatar">
+        <img class="img" :src="data.avatarUrl" mode="aspectFill" />
+      </button>
+      <input type="nickname" v-model="data.nickname" />
+      <button open-type="getUserInfo" @getuserinfo="methods.getuserinfo">用户信息</button>
+    </view>
+  </ay-container>
+</template>
+
+<script lang="ts" setup>
+import login from './components/login.vue'
+import UploadComp from './components/upload.vue'
+const user = store.user
+// 获取屏幕边界到安全区域距离
+const { safeAreaInsets } = uni.getSystemInfoSync()
+const data = reactive({
+  avatarUrl: '',
+  nickname: '',
+})
+const methods = {
+  getuserinfo(res) {
+    console.log(res)
+  },
+  chooseavatar(res) {
+    data.avatarUrl = res.target.avatarUrl
+  },
+}
+ay.entrance(() => {
+  ay.containerLoaded()
+})
+</script>
+
+<style lang="scss" scoped>
+.test-css {
+  // mt-4=>1rem=>16px;
+  margin-top: 16px;
+}
+.chooseAvatar {
+  width: 100px;
+  height: 100px;
+  padding: 0;
+  border-radius: 50%;
+  .img {
+    border-radius: 50%;
+  }
+}
+</style>

+ 16 - 0
src/pagesSubExample/webview/index.vue

@@ -0,0 +1,16 @@
+<template>
+  <web-view src="https://dwx.auyen.com/#/login" @message="methods.bindmessage" />
+</template>
+
+<script lang="ts" setup>
+const methods = {
+  bindmessage(e) {
+    // 官方文档使用方式
+    console.log('e.detail.data', e.detail.data)
+    // 真机调试发现的方式
+    console.log('e.target.data', e.target.data)
+  },
+}
+</script>
+
+<style></style>

BIN
src/static/images/icons/card.png


BIN
src/static/images/icons/firm.png


BIN
src/static/images/icons/payhistory.png


BIN
src/static/images/icons/perpay.png


BIN
src/static/images/icons/turnk_number_head.png


BIN
src/static/images/qr@3x.png


Diferenças do arquivo suprimidas por serem muito extensas
+ 11 - 0
src/static/images/truck.svg


BIN
src/static/logo.png


+ 33 - 0
src/style/_variables.scss

@@ -0,0 +1,33 @@
+// 主题色
+// $p-color: #f40018;
+$p-color: #0084f4;
+// 大字体大小
+$b-fz: 40rpx;
+// 大二字体大小
+$bs-fz: 32rpx;
+// 主字体大小
+$p-fz: 28rpx;
+// 次要字体大小
+$s-fz: 24rpx;
+// 次次要字体大小
+$ss-fz: 20rpx;
+// 主间距
+$p-spac: 24rpx;
+// 主间距/2
+$p-spacd2: calc($p-spac / 2);
+$p-spacd3: calc($p-spac / 3);
+$p-spacd4: calc($p-spac / 4);
+// 价格颜色
+$p-price-color: #ec808d; //#f46d00;
+$gray-color: #868b9a;
+
+$uni-primary: $p-color;
+$uni-spacing-sm: 10rpx;
+$uni-spacing-base: 10rpx;
+
+/* 携带参数 */
+@mixin spacing($multiple) {
+    width: $width;
+    height: $height;
+    background: $bg;
+}

+ 246 - 0
src/style/index.scss

@@ -0,0 +1,246 @@
+/* stylelint-disable no-descending-specificity */
+/* stylelint-disable scss/at-extend-no-missing-placeholder */
+/* stylelint-disable prettier/prettier */
+/* stylelint-disable scss/no-global-function-names */
+.test {
+  // 可以通过 @apply 多个样式封装整体样式
+  @apply mt-4 ml-4;
+
+  padding-top: 4px;
+  color: red;
+}
+
+// 大字体大小
+.b-fz {
+  font-size: $b-fz;
+}
+
+.bs-fz {
+  font-size: $bs-fz;
+}
+
+// 次要字体大小
+.s-fz {
+  font-size: $s-fz;
+}
+
+.flex-1 {
+  width: 0;
+}
+
+
+
+// 主题色
+.p-color {
+  color: $p-color;
+}
+
+.price-color {
+  color: $p-price-color;
+}
+
+.gray-color {
+  color: $gray-color;
+}
+
+.radio {
+  display: inline-block;
+  width: $p-fz;
+  height: $p-fz;
+  border: solid $p-color 2rpx;
+  border-radius: $p-fz;
+  @apply center;
+
+  &.checked::after {
+    width: calc($p-fz / 1.5);
+    height: calc($p-fz / 1.5);
+    content: '';
+    background-color: $p-color;
+    border-radius: calc($p-fz / 1.5);
+  }
+}
+
+%chunk-base {
+  position: relative;
+  padding: $p-spac;
+  margin-bottom: $p-spac;
+  overflow: hidden;
+}
+
+.chunk {
+  @extend %chunk-base;
+  border: 1rpx solid #ccc;
+  border-radius: $p-spacd2;
+  box-shadow: 0rem 0rem 0.5rem 0rem hsla(210, 34%, 80%, 0.4);
+
+  &.checked {
+    background-color: rgba($p-color, .2);
+    border-color: $p-color;
+  }
+}
+
+.child-c-jb {
+  font-size: $s-fz;
+
+  >div,
+  >view {
+    @apply center justify-between;
+    margin-bottom: $p-spacd2;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+
+.chunk2 {
+  @extend %chunk-base;
+  @extend .child-c-jb;
+  padding-top: 0;
+  border-bottom: solid #ccc 1rpx;
+
+  >div,
+  >view {
+
+    >div:first-child,
+    >view:first-child {
+      color: $gray-color;
+    }
+  }
+}
+
+// 间距对象
+$spac-map: (
+  0: (0: 't',
+    1: 'top',
+  ),
+  1: (0: 'b',
+    1: 'bottom',
+  ),
+  2: (0: 'l',
+    1: 'left',
+  ),
+  3: (0: 'r',
+    1: 'right',
+  ),
+);
+
+
+// 循环 $p-spac除以 $j
+@for $j from 1 to 5 {
+  $suffix: if($j ==1, '', 'd' + $j);
+
+  .m-spac#{$suffix} {
+    margin:calc($p-spac / #{$j});
+  }
+
+  .p-spac#{$suffix} {
+    padding:calc($p-spac / #{$j});
+  }
+
+  //循环$spac-map
+  @for $i from 0 to 4 {
+    $t: map-get($spac-map, $i);
+
+    .m#{map-get($t,0)}-spac#{ $suffix} {
+      margin-#{map-get($t,1)}: calc($p-spac / #{$j});
+    }
+
+    .p#{map-get($t,0)}-spac#{ $suffix} {
+      padding-#{map-get($t,1)}: calc($p-spac / #{$j});
+    }
+  }
+}
+
+.tag-rb {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  font-size: $ss-fz;
+  color: #fff;
+  background-color: $p-color;
+  border-top-left-radius: $p-spacd2;
+}
+
+.btns {
+  @apply flex;
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  box-sizing: border-box;
+  width: 100%;
+  padding: $p-spac;
+
+  button {
+    margin-right: $p-spac;
+
+    &:last-child {
+      margin-right: 0;
+    }
+  }
+
+  button[type=primary] {
+    flex: 1;
+    background-color: $p-color;
+  }
+}
+
+button::after {
+  border: none;
+}
+
+// swiper,
+// scroll-view {
+//   flex: 1;
+//   height: 100%;
+//   overflow: hidden;
+// }
+
+image {
+  width: 100%;
+  height: 100%;
+  vertical-align: middle;
+}
+
+// 单行省略,优先使用 unocss: text-ellipsis
+.ellipsis {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+// 两行省略
+.ellipsis-2 {
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+}
+
+// 三行省略
+.ellipsis-3 {
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 3;
+  -webkit-box-orient: vertical;
+}
+
+:root,
+page {
+  font-size: $p-fz;
+  // line-height: 40rpx;
+
+  // 修改按主题色
+  // --wot-color-theme: #37c2bc;
+
+  // 修改按钮背景色
+  // --wot-button-primary-bg-color: green;
+}
+
+
+.uni-section {
+  margin-right: -10px;
+  margin-left: -10px;
+}

+ 171 - 0
src/types/api.d.ts

@@ -0,0 +1,171 @@
+type IFCommon = {
+  /** 是上传文件接口 */ isUpload?: boolean
+}
+
+// 接口信息
+interface IFConfig extends IFCommon {
+  realUrl: string
+  /**
+   * 接口请求参数类型
+   */
+  reqType?: QT
+  /**
+   * 接口请求参数类型
+   */
+  resType?: ST
+}
+/**
+ * 返回安全类型
+ * NT 新类型
+ * OT 旧类型
+ * 权重:新类型>旧类型,权重高的有值则使用
+ */
+// (OT extends never ? any : OT)
+// type GetSAST<NT, OT> = unknown extends NT ? OT : NT
+
+// /** 合并两个类型,新类型覆盖旧类型 */
+// type MergeType<NT, OT> = NT extends AnyObject ? MergeObjectType<NT, OT> : NT
+
+// /** 合并两个对象类型,新类型覆盖旧类型的子属性 */
+// type MergeObjectType<NT, OT> = {
+//   [P in keyof (OT & NT)]: P extends keyof NT ? MergeType<NT[P], OT[P]> : OT[P]
+// }
+/** 两个类型完全相等 */
+type IsEqual<X, Y> =
+  (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false
+// X extends Y ? (Y extends X ? true : false) : false
+
+/** 合并子属性 */
+type MargeSub<OT, NT> = {
+  [P in keyof NT]: SafeMarge<OT[P], NT[P]>
+}
+
+/** 安全合并:
+ * NT为any类型使用OT,
+ * NT为对象进行合并,删除(OT)旧类型的((NT)新类型的属性)属性 & (NT)新类型,
+ * NT为一般类型使用NT */
+type SafeMarge<OT, NT> =
+  IsEqual<NT, any> extends true
+    ? OT
+    : NT extends AnyObject
+      ? Omit<OT, keyof NT> & MargeSub<OT, NT>
+      : NT
+
+/** 未设置NT使用OT  */
+type SwitchType<OT, NT> = NT extends null ? OT : SafeMarge<OT, Omit<NT, ''>> // Omit<NT, ''> 是重点!!! 可以巧妙的避免其作为入参类型时的自动推导
+
+/** 请求方法 */
+type RequestFunc<QT, ST> = <Q = null, S = null>(
+  args?: SwitchType<QT, Q>,
+  options?: IRequestExt,
+) => PromiseExt<SwitchType<ST, S>>
+/**
+ * 接口的服务类型
+ * @generic ST:接口配置的resType类型,接口返回值类型
+ * @generic QT:接口配置的reqType类型,接口请求参数类型
+ */
+interface IServiceApi<QT, ST> {
+  /**
+   * get 请求
+   * @generic Q:对入参类型的修饰,传null不进行修饰
+   * @generic S:对出参类型的修饰,传null不进行修饰
+   */
+  get: RequestFunc<QT, ST>
+  /**
+   * post 请求
+   * @generic Q:对入参类型的修饰,传null不进行修饰
+   * @generic S:对出参类型的修饰,传null不进行修饰
+   */
+  post: RequestFunc<QT, ST>
+  // post: <S = ST, Q = QT>(args?: Q, options?: IRequestOption) => PromiseExt<S>
+}
+/** 扩展Promise定义 */
+interface PromiseExt<T> {
+  then(onfulfilled?: (value: T) => void | undefined | null): PromiseExt<T>
+
+  catch(onrejected?: ((reason: TPromiseCatchReason) => void) | undefined | null): PromiseExt<T>
+}
+/** catch回调函数入参 */
+interface TPromiseCatchReason {
+  /** 错误类型 enums.ErrorType */
+  errType: number
+  /** 公共请求入参 */
+  options: IRequestOption
+  /** 业务异常信息 */
+  res?: IResData<any>
+  /** 通讯异常信息 */
+  errInfo?: UniApp.RequestSuccessCallbackResult
+}
+/** 接口信息 */
+type IWebApi = {
+  /**
+   * 接口名称
+   */
+  name: string
+  /**
+   * 动态获取接口当前地址
+   * @returns
+   */
+  getUrl: () => string
+  /**
+   * 当前接口分组
+   */
+  group: string
+} & IFCommon
+
+/** 公共请求入参 */
+type IRequestOption = {
+  /** 接口信息 */
+  urlObj?: IWebApi
+  /** UniApp请求入参合集 */
+  uur: UUR
+  /** 扩展参数 */
+  ext: IRequestExt
+}
+
+/** UniApp请求入参合集 */
+interface UUR extends UniApp.UploadFileOption, UniApp.RequestOptions {
+  url?: string
+}
+
+/** 请求的扩展参数 */
+interface IRequestExt {
+  /** 显示loading效果 */
+  showLoading?: boolean
+  /** loading文案 */
+  loadingText?: string
+  /** 上传文件选择的文件列表 */
+  choosFiles?: string[]
+  /** 最多可以选择的文件个数,默认1 */
+  fileCount?: number
+  /** 追加url */
+  appendUrl?: string
+}
+/** 分页返回数据 */
+type IPage<T> = {
+  /** 当前页 */
+  current?: number
+  /** 总页数 */
+  pages?: number
+  /** 总条数 */
+  total?: number
+  /** 数据集合 */
+  records?: Array<T>
+}
+/** 分页请求参数 */
+interface IPageParams<T> {
+  /** 当前页面 */
+  page: number
+  /** 数据量 */
+  size: number
+  /** 请求的参数 */
+  param: T
+}
+
+/** 接口统一返回结构 */
+
+type IResData<T> = {
+  code: number
+  message: string
+  data: T
+}

+ 277 - 0
src/types/auto-import.d.ts

@@ -0,0 +1,277 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// noinspection JSUnusedGlobalSymbols
+// Generated by unplugin-auto-import
+export {}
+declare global {
+  const EffectScope: typeof import('vue')['EffectScope']
+  const aop: typeof import('@/utils/aop')['default']
+  const ay: typeof import('@/utils/container')['default']
+  const computed: typeof import('vue')['computed']
+  const config: typeof import('@/utils/config')['default']
+  const createApp: typeof import('vue')['createApp']
+  const customRef: typeof import('vue')['customRef']
+  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
+  const defineComponent: typeof import('vue')['defineComponent']
+  const effectScope: typeof import('vue')['effectScope']
+  const enums: typeof import('../enums/index')['default']
+  const func: typeof import('@/utils/func')['default']
+  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
+  const getCurrentScope: typeof import('vue')['getCurrentScope']
+  const h: typeof import('vue')['h']
+  const inject: typeof import('vue')['inject']
+  const isProxy: typeof import('vue')['isProxy']
+  const isReactive: typeof import('vue')['isReactive']
+  const isReadonly: typeof import('vue')['isReadonly']
+  const isRef: typeof import('vue')['isRef']
+  const markRaw: typeof import('vue')['markRaw']
+  const nextTick: typeof import('vue')['nextTick']
+  const onActivated: typeof import('vue')['onActivated']
+  const onAddToFavorites: typeof import('@dcloudio/uni-app')['onAddToFavorites']
+  const onBackPress: typeof import('@dcloudio/uni-app')['onBackPress']
+  const onBeforeMount: typeof import('vue')['onBeforeMount']
+  const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
+  const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
+  const onDeactivated: typeof import('vue')['onDeactivated']
+  const onError: typeof import('@dcloudio/uni-app')['onError']
+  const onErrorCaptured: typeof import('vue')['onErrorCaptured']
+  const onHide: typeof import('@dcloudio/uni-app')['onHide']
+  const onLaunch: typeof import('@dcloudio/uni-app')['onLaunch']
+  const onLoad: typeof import('@dcloudio/uni-app')['onLoad']
+  const onMounted: typeof import('vue')['onMounted']
+  const onNavigationBarButtonTap: typeof import('@dcloudio/uni-app')['onNavigationBarButtonTap']
+  const onNavigationBarSearchInputChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputChanged']
+  const onNavigationBarSearchInputClicked: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputClicked']
+  const onNavigationBarSearchInputConfirmed: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputConfirmed']
+  const onNavigationBarSearchInputFocusChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputFocusChanged']
+  const onPageNotFound: typeof import('@dcloudio/uni-app')['onPageNotFound']
+  const onPageScroll: typeof import('@dcloudio/uni-app')['onPageScroll']
+  const onPullDownRefresh: typeof import('@dcloudio/uni-app')['onPullDownRefresh']
+  const onReachBottom: typeof import('@dcloudio/uni-app')['onReachBottom']
+  const onReady: typeof import('@dcloudio/uni-app')['onReady']
+  const onRenderTracked: typeof import('vue')['onRenderTracked']
+  const onRenderTriggered: typeof import('vue')['onRenderTriggered']
+  const onResize: typeof import('@dcloudio/uni-app')['onResize']
+  const onScopeDispose: typeof import('vue')['onScopeDispose']
+  const onServerPrefetch: typeof import('vue')['onServerPrefetch']
+  const onShareAppMessage: typeof import('@dcloudio/uni-app')['onShareAppMessage']
+  const onShareTimeline: typeof import('@dcloudio/uni-app')['onShareTimeline']
+  const onShow: typeof import('@dcloudio/uni-app')['onShow']
+  const onTabItemTap: typeof import('@dcloudio/uni-app')['onTabItemTap']
+  const onThemeChange: typeof import('@dcloudio/uni-app')['onThemeChange']
+  const onUnhandledRejection: typeof import('@dcloudio/uni-app')['onUnhandledRejection']
+  const onUnload: typeof import('@dcloudio/uni-app')['onUnload']
+  const onUnmounted: typeof import('vue')['onUnmounted']
+  const onUpdated: typeof import('vue')['onUpdated']
+  const provide: typeof import('vue')['provide']
+  const reactive: typeof import('vue')['reactive']
+  const readonly: typeof import('vue')['readonly']
+  const ref: typeof import('vue')['ref']
+  const resolveComponent: typeof import('vue')['resolveComponent']
+  const shallowReactive: typeof import('vue')['shallowReactive']
+  const shallowReadonly: typeof import('vue')['shallowReadonly']
+  const shallowRef: typeof import('vue')['shallowRef']
+  const store: typeof import('@/utils/store')['default']
+  const toRaw: typeof import('vue')['toRaw']
+  const toRef: typeof import('vue')['toRef']
+  const toRefs: typeof import('vue')['toRefs']
+  const toValue: typeof import('vue')['toValue']
+  const triggerRef: typeof import('vue')['triggerRef']
+  const unref: typeof import('vue')['unref']
+  const useAttrs: typeof import('vue')['useAttrs']
+  const useCssModule: typeof import('vue')['useCssModule']
+  const useCssVars: typeof import('vue')['useCssVars']
+  const useRequest: typeof import('../hooks/useRequest')['default']
+  const useSlots: typeof import('vue')['useSlots']
+  const useUpload: typeof import('../hooks/useUpload')['default']
+  const watch: typeof import('vue')['watch']
+  const watchEffect: typeof import('vue')['watchEffect']
+  const watchPostEffect: typeof import('vue')['watchPostEffect']
+  const watchSyncEffect: typeof import('vue')['watchSyncEffect']
+  const webapi: typeof import('@/utils/api/web')['default']
+}
+// for type re-export
+declare global {
+  // @ts-ignore
+  export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
+  import('vue')
+}
+// for vue template auto import
+import { UnwrapRef } from 'vue'
+declare module 'vue' {
+  interface GlobalComponents {}
+  interface ComponentCustomProperties {
+    readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
+    readonly aop: UnwrapRef<typeof import('@/utils/aop')['default']>
+    readonly ay: UnwrapRef<typeof import('@/utils/container')['default']>
+    readonly computed: UnwrapRef<typeof import('vue')['computed']>
+    readonly config: UnwrapRef<typeof import('@/utils/config')['default']>
+    readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
+    readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
+    readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
+    readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
+    readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
+    readonly enums: UnwrapRef<typeof import('../enums/index')['default']>
+    readonly func: UnwrapRef<typeof import('@/utils/func')['default']>
+    readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
+    readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
+    readonly h: UnwrapRef<typeof import('vue')['h']>
+    readonly inject: UnwrapRef<typeof import('vue')['inject']>
+    readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
+    readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
+    readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
+    readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
+    readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
+    readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
+    readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
+    readonly onAddToFavorites: UnwrapRef<typeof import('@dcloudio/uni-app')['onAddToFavorites']>
+    readonly onBackPress: UnwrapRef<typeof import('@dcloudio/uni-app')['onBackPress']>
+    readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
+    readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
+    readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
+    readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
+    readonly onError: UnwrapRef<typeof import('@dcloudio/uni-app')['onError']>
+    readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
+    readonly onHide: UnwrapRef<typeof import('@dcloudio/uni-app')['onHide']>
+    readonly onLaunch: UnwrapRef<typeof import('@dcloudio/uni-app')['onLaunch']>
+    readonly onLoad: UnwrapRef<typeof import('@dcloudio/uni-app')['onLoad']>
+    readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
+    readonly onNavigationBarButtonTap: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarButtonTap']>
+    readonly onNavigationBarSearchInputChanged: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputChanged']>
+    readonly onNavigationBarSearchInputClicked: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputClicked']>
+    readonly onNavigationBarSearchInputConfirmed: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputConfirmed']>
+    readonly onNavigationBarSearchInputFocusChanged: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputFocusChanged']>
+    readonly onPageNotFound: UnwrapRef<typeof import('@dcloudio/uni-app')['onPageNotFound']>
+    readonly onPageScroll: UnwrapRef<typeof import('@dcloudio/uni-app')['onPageScroll']>
+    readonly onPullDownRefresh: UnwrapRef<typeof import('@dcloudio/uni-app')['onPullDownRefresh']>
+    readonly onReachBottom: UnwrapRef<typeof import('@dcloudio/uni-app')['onReachBottom']>
+    readonly onReady: UnwrapRef<typeof import('@dcloudio/uni-app')['onReady']>
+    readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
+    readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
+    readonly onResize: UnwrapRef<typeof import('@dcloudio/uni-app')['onResize']>
+    readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
+    readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
+    readonly onShareAppMessage: UnwrapRef<typeof import('@dcloudio/uni-app')['onShareAppMessage']>
+    readonly onShareTimeline: UnwrapRef<typeof import('@dcloudio/uni-app')['onShareTimeline']>
+    readonly onShow: UnwrapRef<typeof import('@dcloudio/uni-app')['onShow']>
+    readonly onTabItemTap: UnwrapRef<typeof import('@dcloudio/uni-app')['onTabItemTap']>
+    readonly onThemeChange: UnwrapRef<typeof import('@dcloudio/uni-app')['onThemeChange']>
+    readonly onUnhandledRejection: UnwrapRef<typeof import('@dcloudio/uni-app')['onUnhandledRejection']>
+    readonly onUnload: UnwrapRef<typeof import('@dcloudio/uni-app')['onUnload']>
+    readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
+    readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
+    readonly provide: UnwrapRef<typeof import('vue')['provide']>
+    readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
+    readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
+    readonly ref: UnwrapRef<typeof import('vue')['ref']>
+    readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
+    readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
+    readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
+    readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
+    readonly store: UnwrapRef<typeof import('@/utils/store')['default']>
+    readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
+    readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
+    readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
+    readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
+    readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
+    readonly unref: UnwrapRef<typeof import('vue')['unref']>
+    readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
+    readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
+    readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
+    readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
+    readonly watch: UnwrapRef<typeof import('vue')['watch']>
+    readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
+    readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
+    readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
+    readonly webapi: UnwrapRef<typeof import('@/utils/api/web')['default']>
+  }
+}
+declare module '@vue/runtime-core' {
+  interface GlobalComponents {}
+  interface ComponentCustomProperties {
+    readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
+    readonly aop: UnwrapRef<typeof import('@/utils/aop')['default']>
+    readonly ay: UnwrapRef<typeof import('@/utils/container')['default']>
+    readonly computed: UnwrapRef<typeof import('vue')['computed']>
+    readonly config: UnwrapRef<typeof import('@/utils/config')['default']>
+    readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
+    readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
+    readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
+    readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
+    readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
+    readonly enums: UnwrapRef<typeof import('../enums/index')['default']>
+    readonly func: UnwrapRef<typeof import('@/utils/func')['default']>
+    readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
+    readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
+    readonly h: UnwrapRef<typeof import('vue')['h']>
+    readonly inject: UnwrapRef<typeof import('vue')['inject']>
+    readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
+    readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
+    readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
+    readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
+    readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
+    readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
+    readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
+    readonly onAddToFavorites: UnwrapRef<typeof import('@dcloudio/uni-app')['onAddToFavorites']>
+    readonly onBackPress: UnwrapRef<typeof import('@dcloudio/uni-app')['onBackPress']>
+    readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
+    readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
+    readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
+    readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
+    readonly onError: UnwrapRef<typeof import('@dcloudio/uni-app')['onError']>
+    readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
+    readonly onHide: UnwrapRef<typeof import('@dcloudio/uni-app')['onHide']>
+    readonly onLaunch: UnwrapRef<typeof import('@dcloudio/uni-app')['onLaunch']>
+    readonly onLoad: UnwrapRef<typeof import('@dcloudio/uni-app')['onLoad']>
+    readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
+    readonly onNavigationBarButtonTap: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarButtonTap']>
+    readonly onNavigationBarSearchInputChanged: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputChanged']>
+    readonly onNavigationBarSearchInputClicked: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputClicked']>
+    readonly onNavigationBarSearchInputConfirmed: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputConfirmed']>
+    readonly onNavigationBarSearchInputFocusChanged: UnwrapRef<typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputFocusChanged']>
+    readonly onPageNotFound: UnwrapRef<typeof import('@dcloudio/uni-app')['onPageNotFound']>
+    readonly onPageScroll: UnwrapRef<typeof import('@dcloudio/uni-app')['onPageScroll']>
+    readonly onPullDownRefresh: UnwrapRef<typeof import('@dcloudio/uni-app')['onPullDownRefresh']>
+    readonly onReachBottom: UnwrapRef<typeof import('@dcloudio/uni-app')['onReachBottom']>
+    readonly onReady: UnwrapRef<typeof import('@dcloudio/uni-app')['onReady']>
+    readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
+    readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
+    readonly onResize: UnwrapRef<typeof import('@dcloudio/uni-app')['onResize']>
+    readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
+    readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
+    readonly onShareAppMessage: UnwrapRef<typeof import('@dcloudio/uni-app')['onShareAppMessage']>
+    readonly onShareTimeline: UnwrapRef<typeof import('@dcloudio/uni-app')['onShareTimeline']>
+    readonly onShow: UnwrapRef<typeof import('@dcloudio/uni-app')['onShow']>
+    readonly onTabItemTap: UnwrapRef<typeof import('@dcloudio/uni-app')['onTabItemTap']>
+    readonly onThemeChange: UnwrapRef<typeof import('@dcloudio/uni-app')['onThemeChange']>
+    readonly onUnhandledRejection: UnwrapRef<typeof import('@dcloudio/uni-app')['onUnhandledRejection']>
+    readonly onUnload: UnwrapRef<typeof import('@dcloudio/uni-app')['onUnload']>
+    readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
+    readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
+    readonly provide: UnwrapRef<typeof import('vue')['provide']>
+    readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
+    readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
+    readonly ref: UnwrapRef<typeof import('vue')['ref']>
+    readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
+    readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
+    readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
+    readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
+    readonly store: UnwrapRef<typeof import('@/utils/store')['default']>
+    readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
+    readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
+    readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
+    readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
+    readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
+    readonly unref: UnwrapRef<typeof import('vue')['unref']>
+    readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
+    readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
+    readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
+    readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
+    readonly watch: UnwrapRef<typeof import('vue')['watch']>
+    readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
+    readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
+    readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
+    readonly webapi: UnwrapRef<typeof import('@/utils/api/web')['default']>
+  }
+}

+ 104 - 0
src/types/components.ts

@@ -0,0 +1,104 @@
+interface AyPageInfo {
+  /**
+   * 页码
+   */
+  page?: number
+  /**
+   * 每页数据量
+   */
+  size?: number
+  /**
+   * 总页数
+   */
+  pages?: number
+}
+/**
+ * 通知当前数据加载完毕方法参数
+ */
+interface AyContainerMethodsLoadedArgs {
+  /**
+   * 加载完成后的提示文案 默认 '没有更多了'
+   */
+  finishedText?: string
+  /**
+   * 加载过程中的提示文案 默认 '加载中...'
+   */
+  loadingText?: string
+  /**
+   * 加载失败后的提示文案 默认 '加载失败'
+   */
+  errorText?: string
+  /**
+   * 请求状态
+   */
+  reqState: enums.ReqState
+  /**
+   * 总页数
+   */
+  pages?: number
+}
+/**
+ * 分页组件加载数据事件参数
+ */
+interface AyContainerRefreshArgs extends AyPageInfo {
+  /**
+   * true:上拉加载,false:下拉更新
+   */
+  isAdd?: boolean
+}
+interface AyContainerEntryArgs {
+  /**
+   * 生命周期类型
+   */
+  loadType?: enums.LoadType
+  /**
+   * 页面参数
+   */
+  options?: AnyObject
+  /**
+   * 分页组件加载数据事件参数
+   */
+  cras?: AyContainerRefreshArgs
+  /** 扩展参数 */
+  exts?
+}
+
+/**
+ * 分页组件方法
+ */
+interface AyContainerPullMethods {
+  onLoad?(): void
+  /**
+   * 通知分页组件当前数据加载完毕
+   */
+  loaded?(args: AyContainerMethodsLoadedArgs): void
+  /**
+   * 分页组件加载数据-内部方法
+   */
+  refresh?(args: AyContainerRefreshArgs): void
+  /** 容器通知页面加载数据 */
+  containerRefresh?(args: AyContainerRefreshArgs): void
+}
+
+/**
+  页面生命周期入口的回调函数
+ */
+type AyEntranceCallBack = (args?: AyContainerEntryArgs) => void
+
+interface AyEntranceExt {
+  /**
+   * 追加拦截的生命周期函数
+   */
+  addLoadTypes?: Array<enums.LoadType>
+  /** 分页组件加载数据事件参数默认值 */
+  defAyContainerRefreshArgs?: AyContainerRefreshArgs
+}
+/**
+  页面生命周期入口,默认拦截enums.LoadType.onLoad、enums.LoadType.refresh, 可配置enums.LoadType 枚举
+ */
+type AyEntrance = (callback?: AyEntranceCallBack, ext?: AyEntranceExt) => void
+
+/**
+    通知当前数据加载完毕方法参数
+   */
+type AyContainerLoaded = (args: AyContainerMethodsLoadedArgs) => void

+ 16 - 0
src/types/global.d.ts

@@ -0,0 +1,16 @@
+declare const __UNI_PLATFORM__:
+  | 'h5'
+  | 'app'
+  | 'mp-alipay'
+  | 'mp-baidu'
+  | 'mp-jd'
+  | 'mp-kuaishou'
+  | 'mp-lark'
+  | 'mp-qq'
+  | 'mp-toutiao'
+  | 'mp-weixin'
+  | 'quickapp-webview'
+  | 'quickapp-webview-huawei'
+  | 'quickapp-webview-union'
+
+declare const __VITE_APP_PROXY__: 'true' | 'false'

+ 52 - 0
src/types/page.d.ts

@@ -0,0 +1,52 @@
+// import { GlobalStyle } from '@uni-helper/vite-plugin-uni-pages'
+type GoPageTypeKeys = keyof typeof enums.GoPageType
+/** 页面配置信息 */
+interface ayPage {
+  /** 页面地址 _禁止修改 */
+  readonly _url: string
+  /** 页面类型 _禁止修改 */
+  readonly _type: keyof typeof enums.PageType
+  /** 页面标题 */
+  readonly title: string
+  /** 需要身份认证 默认需要 */
+  readonly identity?: boolean
+  /** 是分页页面 */
+  readonly isPager: boolean
+  /** 页面配置,对应 小程序.json */
+  style? // @uni-helper/vite-plugin-uni-pages.GlobalStyle
+  /** 分页数据 */
+  readonly pagerInfo?: PagerInfo
+  /** 当前页面参数 */
+  params?
+  /** 之前页面配置信息 */
+  prePage?: ayPage
+  // /** 通知页面加载数据 */
+  // loadData?: AyEntranceCallBack
+  /** 有值时,返回页面时执行AyEntranceCallBack-只执行一次,值为AyEntranceCallBack的参数 */
+  onceBackReloadArgs?: AyContainerEntryArgs
+  /** 当前页面的数据加载完毕接收函数 */
+  curCallBack?(args: AyContainerRefreshArgs): void
+}
+/** 分页组件数据 */
+interface PagerInfo {
+  /** loaded方法得到了通知 */
+  loaded: boolean
+  /** 增量获取 */
+  isAdd: boolean
+  /** 加载完毕 */
+  finished: boolean
+  /** 加载中 */
+  loading: boolean
+  /** 加载失败 */
+  error: boolean
+  /** 页码 */
+  page: number
+  /** 总页数 */
+  pages: number
+  /** 加载完成后的提示文案 */
+  finishedText: string
+  /** 加载过程中的提示文案 */
+  loadingText: string
+  /** 加载失败后的提示文案 */
+  errorText: string
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 1079 - 0
src/types/schemas/account.d.ts


+ 793 - 0
src/types/schemas/allinpay.d.ts

@@ -0,0 +1,793 @@
+/** 通联支付 */
+interface B2BDepositConfirmParam {
+  /** 商户订单号(支付订单),必填 */
+  bizOrderNo?: string
+  /** 商户系统用户标识,商户系统中唯一编号,必填 */
+  bizUserId?: string
+  /** 请求端IP,非必填 */
+  ip?: string
+  /** undefined */
+  orgId?: number
+}
+interface B2BDepositParam {
+  /** undefined */
+  amount?: number
+  /** undefined */
+  bizUserId?: number
+  /** undefined */
+  orgId?: number
+  /** undefined */
+  orgName?: string
+  /** undefined */
+  rechargeOrderId?: string
+  /** undefined */
+  tradeType?: number
+  /** undefined */
+  userId?: number
+  /** undefined */
+  userName?: string
+}
+interface BindCardParam {
+  /** 账户id */
+  bizUserId?: string
+  /** 银行卡号 */
+  cardNo?: string
+  /** 身份证号码 */
+  identityNo?: string
+  /** 证件类型,身份证1,默认1 */
+  identityType?: number
+  /** 如果是企业会员,请填写法人姓名 */
+  name?: string
+  /** 企业id */
+  orgId?: number
+  /** 银行预留手机 */
+  phone?: string
+}
+interface BindPhoneParam {
+  /** 账户id */
+  bizUserId?: string
+  /** 企业id,非必传 */
+  orgId?: number
+  /** 绑定的手机号 */
+  phone?: string
+  /** 验证码 */
+  verificationCode?: string
+}
+interface DateParam {
+  /** undefined */
+  createDateFrom?: string
+  /** undefined */
+  createDateTo?: string
+  /** undefined */
+  updateDateFrom?: string
+  /** undefined */
+  updateDateTo?: string
+}
+interface GasOrderVo {
+  /** undefined */
+  actualPrice?: number
+  /** undefined */
+  amount?: number
+  /** undefined */
+  benefit?: number
+  /** undefined */
+  cancelDate?: string
+  /** undefined */
+  canceler?: number
+  /** undefined */
+  cancelerName?: string
+  /** undefined */
+  carNumber?: string
+  /** undefined */
+  carrierOrgId?: number
+  /** undefined */
+  carrierOrgName?: string
+  /** undefined */
+  cashierId?: number
+  /** undefined */
+  cashierName?: string
+  /** undefined */
+  comAmount?: number
+  /** undefined */
+  createDate?: string
+  /** undefined */
+  createRole?: string
+  /** undefined */
+  creater?: number
+  /** undefined */
+  createrName?: string
+  /** undefined */
+  directGasstationFee?: number
+  /** undefined */
+  discountAmount?: number
+  /** undefined */
+  driverId?: number
+  /** undefined */
+  driverName?: string
+  /** undefined */
+  freight?: number
+  /** undefined */
+  gasQty?: number
+  /** undefined */
+  gasamount?: number
+  /** undefined */
+  gasprice?: number
+  /** undefined */
+  gasstationFee?: number
+  /** undefined */
+  gasstationId?: number
+  /** undefined */
+  gasstationName?: string
+  /** undefined */
+  gwayamount?: number
+  /** undefined */
+  gwayprice?: number
+  /** undefined */
+  harbourPrice?: number
+  /** undefined */
+  listPrice?: number
+  /** undefined */
+  nickName?: string
+  /** undefined */
+  orderId?: number
+  /** undefined */
+  orderStatus?: number
+  /** undefined */
+  payType?: number
+  /** undefined */
+  platformFee?: number
+  /** undefined */
+  platformPrice?: number
+  /** undefined */
+  preGasprice?: number
+  /** undefined */
+  rebate?: number
+  /** undefined */
+  serviceFee?: number
+  /** undefined */
+  settleStatus?: number
+  /** undefined */
+  truckId?: number
+  /** undefined */
+  updateDate?: string
+}
+interface GasOrder对象 {
+  /** 实际气价(物流公司采购价=加气站销售价)=platform_price-rebate */
+  actualPrice?: number
+  /** 实际加气金额(物流公司实付金额=加气站销售金额)=gas_qty * actual_price */
+  amount?: number
+  /** 取消日期时间 */
+  cancelDate?: string
+  /** 取消人id */
+  canceler?: string
+  /** 取消人姓名 */
+  cancelerName?: string
+  /** 车牌号 */
+  carNumber?: string
+  /** 物流公司id(user.org.org_id) */
+  carrierOrgId?: string
+  /** 物流公司名称(user.org.org_name) */
+  carrierOrgName?: string
+  /** 物流公司专享优惠总额(单价元) */
+  carrierRebate?: number
+  /** 收银员id(user.user.user_id) */
+  cashierId?: string
+  /** 收银员名称(user.user.user_name) */
+  cashierName?: string
+  /** 创建日期时间 */
+  createDate?: string
+  /** 创建订单角色  4 收银员 6 司机 */
+  createRole?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 司机id(user.user.user_id) */
+  driverId?: string
+  /** 司机名称(user.user.user_name) */
+  driverName?: string
+  /** 加气量 */
+  gasQty?: number
+  /** 加气站采购金额=长城奥扬销售金额 */
+  gasamount?: number
+  /** 加气站服务费(加气站利润价)=strategy.gasstation.profit */
+  gasstationFee?: number
+  /** 加气站id */
+  gasstationId?: string
+  /** 加气站名称 */
+  gasstationName?: string
+  /** 长城奥扬付大象平台服务费=大象加气平台服务费 */
+  gwayamount?: number
+  /** 长城奥扬付大象平台服务价=大象加气平台服务价 */
+  gwayprice?: number
+  /** undefined */
+  keyword?: string
+  /** 经营模式(0-一体化 1-新营销) */
+  marketType?: number
+  /** 加气站简称 */
+  nickName?: string
+  /** 订单编号(调用API生成) */
+  orderId?: string
+  /** 订单状态(1 待支付 2 已支付 3 取消) */
+  orderStatus?: number
+  /** 支付渠道 */
+  payChannelId?: string
+  /** 支付方式(0:所属物流/大象余额 1:所属物流/微信 2:所属物流/大象余额+微信 3:个人支付/微信 11:组合支付 ) */
+  payType?: number
+  /** 平台挂牌价 */
+  platformPrice?: number
+  /** 退款日期时间 */
+  refundDate?: string
+  /** 加气站服务费金额(元)=gas_qty * gasstation_fee */
+  serviceFee?: number
+  /** 订单结算状态(1.待支付 2.已支付 3.取消 4.支付中 5.退款中 6.退款完成) */
+  settleStatus?: number
+  /** 中石化零售价 */
+  snpPrice?: number
+  /** 站服务费清分方式(1线上实时,2 线下月度) */
+  splitType?: number
+  /** 长城标准价 */
+  standardPrice?: number
+  /** 交易结构(1 散户;2 自营车直销,3 自营车经销,4 挂靠车经销,默认1散户) */
+  tradeStruct?: number
+  /** 交易模式(1经销模式;2直销模式,默认经销模式1) */
+  tradeType?: number
+  /** 卡车id */
+  truckId?: string
+  /** 支付日期时间 */
+  updateDate?: string
+}
+interface GetBalanceParam {
+  /** undefined */
+  bizUserId?: string
+}
+interface GetBankCardBinParam {
+  /** 银行卡号,不能带空格,必填 */
+  cardNo?: string
+}
+interface GetMemberInfoParam {
+  /** 组织id */
+  orgId?: number
+}
+interface HandleConsumeParam {
+  /** undefined */
+  gasOrderId?: number
+  /** undefined */
+  orderNo?: string
+}
+interface IdcardCollectParam {
+  /** 文件路径,要求格式如M00/00/01/rB86LV-RN9OANbTuACjKHMrnk1w077.jpg */
+  filePath?: string
+  /** 组织id */
+  orgId?: number
+  /** 传图片类别 :1-营业执照(必传) 2-组织机构代码证(三证时必传) 3-税务登记证(三证时必传) 4-银行开户证明(非必传,上传《银行开户 许可证》或《基本存款账户信息》等可证明 平台银行账号和户名的文件) 5-机构信用代码(非必传) 6-ICP 备案许可(非必传) 7-行业许可证(非必传) 8-身份证正面(人像面)(必传) 9-身份证反面(国徽面)(必传) */
+  picType?: number
+  /** 用户id */
+  userId?: number
+  /** 用户姓名 */
+  userName?: string
+}
+interface OpenAccountParam {
+  /** 会员类型:2 企业 / 3 个人 */
+  memberType?: number
+  /** 组织id */
+  orgId?: number
+  /** 访问终端类型:Mobile 1 / PC 2,默认1 */
+  source?: number
+  /** 用户id,非必传 */
+  userId?: number
+  /** 用户姓名,非必传 */
+  userName?: string
+}
+interface Org对象 {
+  /** 企业对公账户,提现用 */
+  account?: string
+  /** 地址 */
+  address?: string
+  /** 通联认证时间 */
+  authDate?: string
+  /** 企业认证信息0=未认证 1=认证中 2=已认证 3=认证失败 */
+  authStatus?: number
+  /** 认证类型  1:三证  2:一证  默认1-三证 */
+  authType?: number
+  /** 开户行==通联parentBankName */
+  bank?: string
+  /** 开户行支行名称 如:“中国工商银行股份有限公司北京樱桃园支行” */
+  bankName?: string
+  /** 绑定的手机号 */
+  bindPhone?: string
+  /** 营业执照号(三证)认证类型为1 时必传 */
+  businessLicense?: string
+  /** 企业营业执照有效截止日期,长期 传99999999  */
+  businessLicenseValidEndDate?: string
+  /** 企业营业执照证件有效起始日期 */
+  businessLicenseValidStartDate?: string
+  /** 所在市 */
+  cityName?: string
+  /** 联系人 */
+  contacts?: string
+  /** 合同签订状态修改时间[签约完成时间] */
+  contractDate?: string
+  /** 合同签订状态[物流公司-象群科技、加气站->象群科技和长城奥扬]1=未签约 2=已签约 3=已取消 */
+  contractStatus?: number
+  /** 车辆租赁或挂靠协议:1=待认证 2=已认证 3=已驳回 */
+  cooperationStatus?: number
+  /** 创建日期时间 */
+  createDate?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人 */
+  createrName?: string
+  /** 所在区县 */
+  districtName?: string
+  /** 邮箱 */
+  email?: string
+  /** 环评报告:1=待认证 2=已认证 3=已驳回 */
+  envImpactStatus?: number
+  /** 消防验收报告:1=待认证 2=已认证 3=已驳回 */
+  fireControlStatus?: number
+  /** 燃气经营许可证认证状态: 1=待认证 2=已认证 3=已驳回 */
+  gasBusinessStatus?: number
+  /** 气瓶充装许可证认证状态: 1=待认证 2=已认证 3=已驳回 */
+  gasFillingStatus?: number
+  /** 加气站执照:1=待认证 2=已认证 3=已驳回,跟公司营业执照不同 */
+  gasLicenseStatus?: number
+  /** 企业法人身份证有效截止日期 yyyyMMdd,长期 传99999999 */
+  idCardValidEndDate?: string
+  /** 企业法人身份证证件有效起始日期 yyyyMMdd */
+  idCardValidStartDate?: string
+  /** 法人证件类型:1身份证 2护照 3军官证 4回乡证 5台胞证 6警官证 7士兵证 8户口簿 9港澳居民来往/内地通行证 10临时身份证 11外国人居留证 99其它证件 */
+  identityType?: number
+  /** 0=未绑定 1=已绑定 */
+  legalBankBind?: number
+  /** 法人银行卡号 */
+  legalBankno?: string
+  /** 法人证件号码, AES 加密 */
+  legalIds?: string
+  /** 法人手机号 */
+  legalPhone?: string
+  /** 法人 */
+  legalperson?: string
+  /** 手机号 */
+  mobile?: string
+  /** 组织id(调用API生成) */
+  orgId?: string
+  /** 组织名称 */
+  orgName?: string
+  /** 父id */
+  orgParentId?: string
+  /** 组织简称 */
+  orgShortName?: string
+  /** 21=物流公司  22=个人车主  */
+  orgSubType?: number
+  /** 组织类型:0=平台方企业 1=加气站  2=物流客户 3=卡车经销商 */
+  orgType?: number
+  /** 组织机构代码(三证)认证类型为1 时必传 */
+  organizationCode?: string
+  /** 所在省 */
+  provinceName?: string
+  /** 道路运输经营许可证认证状态: 1=待认证 2=已认证 3=已驳回 */
+  roadTransportStatus?: number
+  /** 状态(0:启用 1:停用) */
+  status?: number
+  /** 税务登记证(三证)认证类型为1 时必传 */
+  taxRegister?: string
+  /** 纳税人识别号 统一社会信用(一证)认证类型为2 时必传 */
+  taxpayer?: string
+  /** 交易模式(1经销模式;2直销模式,默认经销模式1) */
+  tradeType?: number
+  /** 支付行号,12位数字 */
+  unionBank?: string
+  /** 修改日期时间 */
+  updateDate?: string
+  /** 修改人id */
+  updater?: string
+  /** 修改人 */
+  updaterName?: string
+}
+interface P2PPayParam {
+  /** 支付金额,单位元 */
+  amount?: number
+  /** 转账注释 */
+  extendInfo?: string
+  /** 支付方组织bizUserId */
+  payBizUserId?: number
+  /** 支付方组织消费协议 */
+  payProtocolNo?: string
+  /** 收款方组织bizUserId */
+  receiveBizUserId?: number
+}
+interface QueryBankCardParam {
+  /** 商户系统用户标识,必填 */
+  bizUserId?: string
+  /** 银行卡号,必填 */
+  cardNo?: string
+}
+interface QueryBankInExpDetailParam {
+  /** 商户系统用户标识,商户系统中唯一编号,必填 */
+  bizUserId?: string
+  /** 结束日期,必填 */
+  dateEnd?: string
+  /** 开始日期,必填 */
+  dateStart?: string
+  /** 查询条数,必填 */
+  queryNum?: number
+  /** 起始位置,必填 */
+  startPosition?: number
+}
+interface QueryCashFlowParam {
+  /** 结束日期,必填 */
+  dateEnd?: string
+  /** 开始日期,必填 */
+  dateStart?: string
+  /** 组织id */
+  orgId?: number
+}
+interface QuerySignContractParam {
+  /** 账户id */
+  bizUserId?: string
+  /** 签订成功后,跳转返回的页面地址 */
+  jumpUrl?: string
+  /** 访问终端类型:Mobile=1 / PC=2,默认1,非必传 */
+  source?: number
+}
+interface RechargeOrder对象 {
+  /** 组织资金账户 */
+  accountId?: string
+  /** 充值金额 */
+  amount?: number
+  /** 车牌号 */
+  carNumber?: string
+  /** 创建日期时间 */
+  createDate?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 充值订单对应的加气订单 */
+  gasOrderId?: string
+  /** 关键字 */
+  keyword?: string
+  /** 从组织id(user.org.org_id) */
+  orgId?: string
+  /** 从组织名称(user.org.org_name) */
+  orgName?: string
+  /** 支付渠道 */
+  payChannelId?: string
+  /** 充值订单id(调用API生成) */
+  rechargeOrderId?: string
+  /** 订单状态(1 待支付 2 已支付 3 取消) */
+  status?: number
+  /** 交易模式(1经销模式;2直销模式,默认经销模式1) */
+  tradeType?: number
+  /** 卡车ID */
+  truckId?: string
+  /** 支付类型(0=线下支付 1=微信支付 2=支付宝支付 3=网关支付) */
+  type?: number
+  /** 支付日期时间 */
+  updateDate?: string
+}
+interface RelyConsumeParam {
+  /** 车牌号 */
+  carNumber?: string
+  /** 所属物流公司id */
+  carrierOrgId?: number
+  /** 所属物流公司名称 */
+  carrierOrgName?: string
+  /** 订单编号 */
+  orderId?: number
+  /** 卡车id */
+  truckId?: number
+}
+interface ResponseEntity {
+  /** undefined */
+  body?: AnyObject
+  /** undefined */
+  statusCode?: string
+  /** undefined */
+  statusCodeValue?: number
+}
+interface SelfConsumeParam {
+  /** 车牌号 */
+  carNumber?: string
+  /** undefined */
+  gasOrderId?: number
+  /** undefined */
+  orgId?: number
+  /** undefined */
+  orgName?: string
+  /** 卡车id */
+  truckId?: number
+  /** undefined */
+  userId?: number
+  /** undefined */
+  userName?: string
+}
+interface SendVerificationCodeParam {
+  /** 账户id */
+  bizUserId?: string
+  /** 绑定/解绑的手机号 */
+  phone?: string
+  /** 绑定手机9;解绑手机6 */
+  verificationCodeType?: number
+}
+interface SignBalanceProtocolParam {
+  /** 后台通知地址 */
+  backUrl?: string
+  /** 账户id */
+  bizUserId?: string
+  /** 签订成功后,跳转返回的页面地址 */
+  jumpUrl?: string
+  /** 组织ID */
+  orgId?: number
+  /** 访问终端类型:Mobile=1 / PC=2,默认1 */
+  source?: number
+}
+interface SignContractProtocolParam {
+  /** 后台通知地址 */
+  backUrl?: string
+  /** 账户id */
+  bizUserId?: string
+  /** 签订成功后,跳转返回的页面地址 */
+  jumpUrl?: string
+  /** 组织id */
+  orgId?: number
+  /** 访问终端类型:Mobile=1 / PC=2,默认1,非必传 */
+  source?: number
+}
+interface SplitRefundParam {
+  /** undefined */
+  gasOrderId?: number
+}
+interface TsyParam {
+  /** undefined */
+  accountNo?: string
+  /** undefined */
+  authType?: number
+  /** undefined */
+  bankCityNo?: string
+  /** undefined */
+  bankName?: string
+  /** undefined */
+  bizOrderNo?: string
+  /** undefined */
+  bizUserId?: number
+  /** undefined */
+  businessLicense?: string
+  /** undefined */
+  cashierId?: number
+  /** undefined */
+  code?: string
+  /** undefined */
+  companyAddress?: string
+  /** undefined */
+  companyName?: string
+  /** undefined */
+  contacts?: string
+  /** undefined */
+  contractNo?: string
+  /** undefined */
+  createName?: string
+  /** 创建订单角色 1 平台管理员 2 平台运营人员 3 加气站企业管理者 4 收银员 5 物流公司管理者 6 司机 */
+  createRole?: string
+  /** undefined */
+  creater?: number
+  /** undefined */
+  driveId?: number
+  /** undefined */
+  email?: string
+  /** undefined */
+  expLicense?: string
+  /** undefined */
+  extendInfo?: string
+  /** undefined */
+  gasOrderId?: number
+  /** undefined */
+  gasQty?: number
+  /** undefined */
+  gasstationAccountId?: number
+  /** undefined */
+  gasstationId?: number
+  /** undefined */
+  identityType?: number
+  /** undefined */
+  legalBankno?: string
+  /** undefined */
+  legalIds?: string
+  /** undefined */
+  legalName?: string
+  /** undefined */
+  legalPhone?: string
+  /** undefined */
+  memberType?: number
+  /** undefined */
+  oldphone?: string
+  /** undefined */
+  orgId?: number
+  /** undefined */
+  orgName?: string
+  /** undefined */
+  organizationCode?: string
+  /** undefined */
+  parentBankName?: string
+  /** undefined */
+  protocolNo?: string
+  /** undefined */
+  rechargeOrderId?: number
+  /** undefined */
+  source?: number
+  /** undefined */
+  taxRegister?: string
+  /** undefined */
+  taxpayer?: string
+  /** undefined */
+  telephone?: string
+  /** undefined */
+  tranceNum?: string
+  /** undefined */
+  truckId?: number
+  /** undefined */
+  uniCredit?: string
+  /** undefined */
+  unionBank?: string
+  /** undefined */
+  verificationCode?: string
+}
+interface UnBindCardParam {
+  /** 账户id */
+  bizUserId?: string
+  /** 银行卡号 */
+  cardNo?: string
+  /** 企业id,非必传 */
+  orgId?: number
+}
+interface UnBindPhoneParam {
+  /** 账户id */
+  bizUserId?: string
+  /** 组织id */
+  orgId?: number
+  /** 原手机号 */
+  phone?: string
+  /** 验证码 */
+  verificationCode?: string
+}
+interface WithdrawOrder对象 {
+  /** 组织资金账户 */
+  accountId?: string
+  /** 提现金额 */
+  amount?: string
+  /** 创建日期时间 */
+  createDate?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 提现备注 */
+  note?: string
+  /** 提现组织id(user.org.org_id) */
+  orgId?: string
+  /** 组织名称(user.org.org_name) */
+  orgName?: string
+  /** 支付渠道 */
+  payChannelId?: string
+  /** 提现电子回单 */
+  receiptUrl?: string
+  /** 订单状态(1 待提现 2 提现中3 提现成功 4失败 12 银行处理中,注12为前端查询条件用 */
+  status?: number
+  /** 交易模式(1经销模式;2直销模式,默认经销模式1) */
+  tradeType?: number
+  /** 支付日期时间 */
+  updateDate?: string
+  /** 提现订单id(调用API生成) */
+  withdrawOrderId?: string
+}
+interface WithdrawParam {
+  /** undefined */
+  amount?: number
+  /** undefined */
+  legalBankno?: string
+  /** undefined */
+  note?: string
+  /** undefined */
+  orgId?: number
+  /** undefined */
+  orgName?: string
+  /** undefined */
+  status?: number
+  /** undefined */
+  tradeType?: number
+  /** undefined */
+  userId?: number
+  /** undefined */
+  userName?: string
+  /** undefined */
+  verificationCode?: string
+}
+interface WxpayParam {
+  /** undefined */
+  amount?: number
+  /** undefined */
+  carNumber?: string
+  /** undefined */
+  carOwner?: number
+  /** undefined */
+  code?: string
+  /** undefined */
+  gasOrderId?: number
+  /** undefined */
+  gasstationId?: number
+  /** undefined */
+  gasstationName?: string
+  /** undefined */
+  orgId?: number
+  /** undefined */
+  orgName?: string
+  /** undefined */
+  truckId?: number
+  /** undefined */
+  userId?: number
+  /** undefined */
+  userName?: string
+  /** undefined */
+  wxPayWay?: string
+}
+interface 气瓶检测订单微信支付参数 {
+  /** 必传:公众号授权码 */
+  code?: string
+  /** 必传:气瓶检测订单id */
+  orderId?: number
+  /** undefined */
+  orgId?: number
+  /** undefined */
+  userId?: number
+  /** undefined */
+  userName?: string
+  /** undefined */
+  wxPayWay?: string
+}
+interface 订单退款参数 {
+  /** 金额 */
+  amount?: number
+  /** 操作人 */
+  operator?: string
+  /** 操作时间 */
+  operatorDate?: string
+  /** 订单id */
+  orderId?: number
+  /** 支付方式(0:余额 1:微信 2:微信+余额) */
+  payType?: number
+  /** 退款凭证,多个逗号分隔 */
+  refundUrl?: string
+  /** 操作类型 */
+  type?: string
+}
+interface 身份证二要素认证参数 {
+  /** 身份证号 */
+  idcardNo?: string
+  /** 系统内该身份证对应的组织的orgId,个人车主(组织身份)认证时必传 */
+  orgId?: number
+  /** 身份证姓名 */
+  realname?: string
+  /** 系统内该身份证对应的用户的userId, 用户(个人身份)认证时必传 */
+  userId?: number
+  /** undefined */
+  userName?: string
+}
+interface 返回值 {
+  /** 返回码 */
+  code?: number
+  /** 返回数据 */
+  data?: AnyObject
+  /** 返回信息 */
+  message?: string
+}
+interface 返现微信模板消息参数 {
+  /** 返现金额 */
+  amount?: number
+  /** 已完成支付和返现的加气订单信息 */
+  gasOrder?: GasOrderVo
+}
+interface 通用id参数 {
+  /** 通用id参数 */
+  id?: string
+}

+ 8 - 0
src/types/schemas/custom.d.ts

@@ -0,0 +1,8 @@
+type IAccountInfo = {
+  /** 显示余额 */
+  showBalance: { balance?: string; suffix?: string }
+  /** 单位 */
+  unit?: string
+  /** 显示详细 */
+  showDet: boolean
+} & 司机账户余额信息

Diferenças do arquivo suprimidas por serem muito extensas
+ 1071 - 0
src/types/schemas/gasdata.d.ts


+ 576 - 0
src/types/schemas/message.d.ts

@@ -0,0 +1,576 @@
+/** 消息中心 */
+interface FileUploadLog对象 {
+  /** 哪一端 */
+  clientId?: string
+  /** 上传源文件名 */
+  fileName?: string
+  /** 上传后存放文件路径 */
+  filePath?: string
+  /** 上传文件大小 */
+  fileSize?: string
+  /** id主键 */
+  id?: string
+  /** 组织id(user.org.org_id) */
+  orgId?: string
+  /** 0.上传一个文件或图像1.上传图像生成默认尺寸缩略图2.上传图像生成指定尺寸缩略图 */
+  type?: number
+  /** 上传日期 */
+  uploadTime?: string
+  /** 用户id(user.user.user_id) */
+  userId?: string
+}
+interface GasOrder {
+  /** 实际气价(物流公司采购价=加气站销售价)=platform_price-rebate */
+  actualPrice?: number
+  /** 实际加气金额(物流公司实付金额=加气站销售金额)=gas_qty * actual_price */
+  amount?: number
+  /** 区域优惠(单价公斤/元) */
+  benefit?: number
+  /** 取消日期时间 */
+  cancelDate?: string
+  /** 取消人id */
+  canceler?: string
+  /** 取消人姓名 */
+  cancelerName?: string
+  /** 车牌号 */
+  carNumber?: string
+  /** 物流公司id(user.org.org_id) */
+  carrierOrgId?: string
+  /** 物流公司名称(user.org.org_name) */
+  carrierOrgName?: string
+  /** 物流公司专享优惠总额(单价元) */
+  carrierRebate?: number
+  /** 总优惠金额(站、司机、收银员、物流显示的,处理了加价的) */
+  carrierRebateHand?: number
+  /** 收银员id(user.user.user_id) */
+  cashierId?: string
+  /** 收银员名称(user.user.user_name) */
+  cashierName?: string
+  /** 创建日期时间 */
+  createDate?: string
+  /** 创建订单角色  4 收银员 6 司机 */
+  createRole?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 优惠金额(物流公司返利金额=加气站优惠金额)=gas_qty * rebate */
+  discountAmount?: number
+  /** 司机id(user.user.user_id) */
+  driverId?: string
+  /** 司机名称(user.user.user_name) */
+  driverName?: string
+  /** 运费(单价公斤/元) */
+  freight?: number
+  /** 加气量 */
+  gasQty?: number
+  /** 加气站采购金额=长城奥扬销售金额 */
+  gasamount?: number
+  /** 加气站采购价=长城奥扬销售价 */
+  gasprice?: number
+  /** 加气站服务费(加气站利润价)=strategy.gasstation.profit */
+  gasstationFee?: number
+  /** 加气站id */
+  gasstationId?: string
+  /** 加气站名称 */
+  gasstationName?: string
+  /** 长城奥扬付大象平台服务费=大象加气平台服务费 */
+  gwayamount?: number
+  /** 长城奥扬付大象平台服务价=大象加气平台服务价 */
+  gwayprice?: number
+  /** 出港价(公斤/元) */
+  harbourPrice?: number
+  /** 关键字 */
+  keyword?: string
+  /** 加气站挂牌气价(来源加气站) */
+  listPrice?: number
+  /** undefined */
+  orderId?: string
+  /** 订单状态(1 待支付 2 已支付 3 取消) */
+  orderStatus?: number
+  /** 支付方式(0 余额支付 1 微信支付 2 支付宝支付 3 第三方支付) */
+  payType?: number
+  /** 平台服务费(加气站利润价限额)=strategy.gasstation.profit_quota */
+  platformFee?: number
+  /** 平台挂牌价 */
+  platformPrice?: number
+  /** 专项优惠=carrier.gas_total>15000 ? 0.35 : 0.3 */
+  rebate?: number
+  /** 服务费(加气站利润)=gas_qty * gasstation_fee */
+  serviceFee?: number
+  /** 卡车id */
+  truckId?: string
+  /** 支付日期时间 */
+  updateDate?: string
+}
+interface IdsParam {
+  /** id 数组 */
+  id?: array
+}
+interface JSONObject {}
+interface McClientRoleMessage对象 {
+  /** 端id */
+  clientId?: string
+  /** id,自增 */
+  id?: string
+  /** 消息id */
+  messageId?: string
+  /** 角色id */
+  roleId?: string
+}
+interface McMessageParam {
+  /** 消息要送达的目标群体 */
+  clientRoleList?: McClientRoleMessage对象[]
+  /** 消息信息 */
+  mcMessage?: McMessage对象
+}
+interface McMessageQueryParam {
+  /** 结束日期 */
+  endDate?: string
+  /** 查询标题关键字 */
+  keyword?: string
+  /** 消息信息 */
+  mcMessage?: McMessage对象
+  /** 查询日期类型: 0 不作为查询条件,1 创建日期 2 发布日期 */
+  queryDateType?: number
+  /** 消息的状态:-1 未选择,0 未读, 1 已读 */
+  readStatus?: number
+  /** 开始日期 */
+  startDate?: string
+}
+interface McMessageResult {
+  /** 消息要送达的目标群体 */
+  clientRoleList?: McClientRoleMessage对象[]
+  /** 消息信息 */
+  mcMessage?: McMessage对象
+}
+interface McMessage对象 {
+  /** 消息内容 */
+  content?: string
+  /** 创建时间,默认CURRENT_TIMESTAMP(当前时间) */
+  createTime?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** id,自增 */
+  id?: string
+  /** 发布状态:1 编辑中,2 发布中,3 已发布 */
+  publishStatus?: number
+  /** 发布时间 */
+  publishTime?: string
+  /** 发布方式:1 实时发布,2 定时发布  */
+  publishType?: number
+  /** 标题 */
+  title?: string
+  /** 修改时间 */
+  updateTime?: string
+  /** 修改人id */
+  updater?: string
+  /** 修改人姓名 */
+  updaterName?: string
+}
+interface McUserMessageNoticeResult {
+  /** 前10条未读消息 */
+  mcMessages?: McMessage对象[]
+  /** 未读消息总条数 */
+  total?: number
+}
+interface McUserMessageResult {
+  /** 消息实体对象 */
+  mcMessage?: McMessage对象
+  /** 消息的状态:0 未读, 1 已读 */
+  readStatus?: number
+}
+interface MobileParam {
+  /** 手机号 */
+  mobile?: string
+}
+interface MsgGroup对象 {
+  /** 创建日期 */
+  createDate?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 组id */
+  groupId?: number
+  /** 组名 */
+  groupName?: string
+}
+interface MsgIdGen对象 {
+  /** 添加时间 */
+  addTime?: string
+  /** 组id,默认1(系统消息),非必填 */
+  groupId?: number
+  /** 组名,默认系统消息,非必填 */
+  groupName?: string
+  /** 消息id */
+  msgId?: number
+  /** 接收人id */
+  userId?: string
+}
+interface Msg对象 {
+  /** 发送时间 */
+  fromDate?: string
+  /** 发送人id */
+  fromUserId?: string
+  /** 发送人姓名 */
+  fromUserName?: string
+  /** 组id */
+  groupId?: number
+  /** 组名 */
+  groupName?: string
+  /** id */
+  id?: number
+  /** 消息体 */
+  message?: string
+  /** 消息id */
+  msgId?: number
+  /** 0未读,1已读,2删除 */
+  status?: number
+  /** 接收人id */
+  toUserId?: string
+}
+interface Printer对象 {
+  /** 创建时间 */
+  createTime?: string
+  /** 创建人 */
+  creater?: string
+  /** 加气站id */
+  gasstationId?: string
+  /** 加气站名称 */
+  gasstationName?: string
+  /** 主键id,自增长 */
+  id?: number
+  /** 终端号 */
+  machineCode?: string
+  /** 密钥 */
+  msign?: string
+  /** 手机卡号码 */
+  phone?: string
+  /** 小票打印:0-不打印;1-打印 */
+  print?: number
+  /** 打印机名称 */
+  printName?: string
+  /** 打印机状态(0离线 1在线 2缺纸) */
+  status?: number
+  /** 修改时间 */
+  updateTime?: string
+  /** 修改人 */
+  updater?: string
+  /** 音量大小(0:关;1:低;2:中;3:高) */
+  voice?: number
+}
+interface QaCatalogs对象 {
+  /** 创建时间 */
+  createDate?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 栏目图标 */
+  iconUrl?: string
+  /** 编号id */
+  id?: number
+  /** 栏目名称 */
+  name?: string
+  /** 上级目录id,第一级父ID为0 */
+  parentId?: number
+  /** 排序值,越小越靠前 */
+  sortOrder?: number
+  /** 分类状态1.启用 2.停用 */
+  status?: number
+}
+interface QaClient对象 {
+  /** 客户端id */
+  clientId?: number
+  /** 客户端名 */
+  clientName?: string
+  /** 创建时间 */
+  createDate?: string
+  /** 创建人id */
+  createrId?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 主键 */
+  id?: number
+}
+interface QaContentClientParam {
+  /** 客户端id列表1.物流公司pc端 2.物流公司移动端 3.司机端 4.加气站pc端 5.加气站移动端 6.收银员端 */
+  clientIds?: array
+  /** 问答id */
+  contentId?: number
+  /** 用户id */
+  userId?: number
+  /** 用户名 */
+  userName?: string
+}
+interface QaContentParam {
+  /** 问答id */
+  clientId?: number
+  /** 问答 */
+  qaContent?: QaContent对象
+}
+interface QaContentSaveParam {
+  /** 附件路径 */
+  filePaths?: array
+  /** 问答 */
+  qaContent?: QaContent对象
+}
+interface QaContent对象 {
+  /** 目录id */
+  catalogsId?: number
+  /** 客户端名称 */
+  clientNames?: string
+  /** QA回答 */
+  content?: string
+  /** 创建时间 */
+  createDate?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人姓名 */
+  createrName?: string
+  /** 编号id */
+  id?: number
+  /** 无用次数 */
+  noUseCount?: number
+  /** 排序值 */
+  sortOrder?: number
+  /** 状态,1显示,2不显示;默认值1 */
+  status?: number
+  /** QA标题 */
+  title?: string
+  /** 修改时间 */
+  updateDate?: string
+  /** 修改人id */
+  updater?: string
+  /** 修改人姓名 */
+  updaterName?: string
+  /** 有用次数 */
+  useCount?: number
+  /** 点击次数 */
+  viewCount?: number
+}
+interface SmsSendLog对象 {
+  /** 哪一端 */
+  clientId?: string
+  /** 发送内容 */
+  content?: string
+  /** 验证码位数,默认6位(例:四位验证码则传参4) */
+  digit?: number
+  /** id主键 */
+  id?: string
+  /** 图片验证码 */
+  imageText?: string
+  /** 图片验证码对应的key */
+  key?: string
+  /** 手机号 */
+  mobile?: string
+  /** 组织id(user.org.org_id) */
+  orgId?: string
+  /** 发送日期 */
+  sendTime?: string
+  /** 对应 message.sms_template.type */
+  type?: number
+  /** 用户id(user.user.user_id) */
+  userId?: string
+}
+interface SmsTemplate对象 {
+  /** 内容 */
+  content?: string
+  /** 创建时间 */
+  createDate?: string
+  /** 创建人id */
+  creater?: string
+  /** 创建人 */
+  createrName?: string
+  /** 阿里云短信模板编号 */
+  smsCode?: string
+  /** 模板名称 */
+  templateName?: string
+  /** 模板编号 */
+  type?: number
+}
+interface UseParam {
+  /** 问答id */
+  contentId?: number
+  /** 有帮助,无帮助类型,1有帮助,2无帮助 */
+  useType?: number
+}
+interface WxUserinfo {
+  /** undefined */
+  city?: string
+  /** undefined */
+  country?: string
+  /** undefined */
+  headimgurl?: string
+  /** undefined */
+  language?: string
+  /** undefined */
+  nickname?: string
+  /** undefined */
+  openid?: string
+  /** undefined */
+  province?: string
+  /** undefined */
+  sex?: number
+  /** undefined */
+  subscribe?: number
+  /** undefined */
+  subscribe_time?: number
+}
+interface WxWebPageUserinfo {
+  /** undefined */
+  city?: string
+  /** undefined */
+  country?: string
+  /** undefined */
+  headimgurl?: string
+  /** undefined */
+  nickname?: string
+  /** undefined */
+  openid?: string
+  /** undefined */
+  province?: string
+  /** undefined */
+  sex?: number
+}
+interface ocr文字识别参数 {
+  /** 反面url(副页url), 格式为:group/path,如:image/M00/00/00/xxxxxxx.png */
+  backUrl?: string
+  /** 正面url(首页url), 格式为:group/path,如:image/M00/00/00/xxxxxxx.png */
+  faceUrl?: string
+}
+interface ocr识别参数 {
+  /** 文件地址url */
+  fileUrl?: string
+}
+interface 发送短信_图形验证码辅助验证 {
+  /** 验证码位数,默认6位(例:四位验证码则传参4) */
+  digit?: number
+  /** 图形验证码文本值 */
+  imageText?: string
+  /** 验证时需要返回的key */
+  key?: string
+  /** 要发送短信的手机号 */
+  mobile?: string
+}
+interface 图片验证码返回值 {
+  /** 图片base64码 */
+  image?: string
+  /** 验证时需要返回的key */
+  key?: string
+}
+interface 增值税发票信息 {
+  /** 销售方地址、电话 */
+  address?: string
+  /** 文件地址 */
+  fileUrl?: string
+  /** 发票代码 */
+  invoiceCode?: string
+  /** 销售方名称 */
+  payeeName?: string
+  /** 销售方税号 */
+  payerRegisterNo?: string
+  /** 是否成功 */
+  success?: boolean
+  /** 发票金额 */
+  taxAmount?: string
+  /** 不含税金额 */
+  withoutTaxAmount?: string
+}
+interface 微信openid {
+  /** 微信openid */
+  openid?: string
+}
+interface 微信网页授权获取用户信息参数_授权后重定向参数 {
+  /** 网页授权后的重定向参数code */
+  code?: string
+  /** 网页授权后的重定向额外参数state */
+  state?: string
+}
+interface 营业执照信息 {
+  /** 公司地址,没有识别出来时返回"FailInRecognition" */
+  address?: string
+  /** 公司法人、个体户经营者:没有识别出来时返回"FailInRecognition" */
+  legalperson?: string
+  /** 组织名称:公司名称,没有识别出来时返回"FailInRecognition" */
+  orgName?: string
+  /** 识别是否成功 */
+  success?: boolean
+  /** 纳税人识别号,统一社会信用代码、注册号:没有识别出来时返回"FailInRecognition" */
+  taxpayer?: string
+}
+interface 行驶证识别信息 {
+  /** 住址 */
+  address?: string
+  /** 车牌号 */
+  carNumber?: string
+  /** 能源类型 */
+  energyType?: string
+  /** 发动机编号 */
+  engineNumber?: string
+  /** 档案编号 */
+  fileNo?: string
+  /** 发证日期 */
+  issueDate?: string
+  /** 所有人 */
+  owner?: string
+  /** 注册日期 */
+  registerDate?: string
+  /** 识别是否成功 */
+  success?: boolean
+  /** 车辆名称,默认开车品牌名 */
+  truckName?: string
+  /** 车辆类型(行驶证上的车辆类型) */
+  typeName?: string
+  /** 使用性质 */
+  useNature?: string
+  /** 车辆识别码 */
+  vehicleIdCode?: string
+}
+interface 身份证信息 {
+  /** 身份证号 */
+  cardNo?: string
+  /** 身份证姓名 */
+  realname?: string
+  /** 识别是否成功 */
+  success?: boolean
+  /** 身份证有效期 */
+  validity?: string
+}
+interface 返回值 {
+  /** 返回码 */
+  code?: number
+  /** 返回数据 */
+  data?: AnyObject
+  /** 返回信息 */
+  message?: string
+}
+interface 返现微信模板消息参数 {
+  /** 返现金额 */
+  amount?: number
+  /** 已完成支付和返现的加气订单信息 */
+  gasOrder?: GasOrder
+}
+interface 驾驶证信息 {
+  /** 住址 */
+  address?: string
+  /** 出生日期 */
+  birthDate?: string
+  /** 准驾车型 */
+  drivingType?: string
+  /** 初次领证日期 */
+  issueDate?: string
+  /** 驾驶证号,识别错误时,为"NoResult"/"InvalidInput" */
+  licenseNo?: string
+  /** 姓名字符串,识别不出来时,可能为"NoResult"/"InvalidInput" */
+  realname?: string
+  /** 性别 */
+  sex?: string
+  /** 识别是否成功 */
+  success?: boolean
+  /** 有效日期 */
+  validityDate?: string
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 1110 - 0
src/types/schemas/pay.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 1451 - 0
src/types/schemas/settle.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 5194 - 0
src/types/schemas/strategy.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 1124 - 0
src/types/schemas/tms.d.ts


Diferenças do arquivo suprimidas por serem muito extensas
+ 2369 - 0
src/types/schemas/user.d.ts


+ 46 - 0
src/types/schemas/websocket.d.ts

@@ -0,0 +1,46 @@
+/** websocket打印中心 */
+interface JSONObject {}
+interface Printer对象 {
+  /** 创建时间 */
+  createTime?: string
+  /** 创建人 */
+  creater?: string
+  /** 加气站id */
+  gasstationId?: string
+  /** 加气站名称 */
+  gasstationName?: string
+  /** 主键id,自增长 */
+  id?: number
+  /** 终端号 */
+  machineCode?: string
+  /** 密钥 */
+  msign?: string
+  /** 手机卡号码 */
+  phone?: string
+  /** 小票打印:0-不打印;1-打印 */
+  print?: number
+  /** 打印机名称 */
+  printName?: string
+  /** 打印机状态(0离线 1在线 2缺纸) */
+  status?: number
+  /** 修改时间 */
+  updateTime?: string
+  /** 修改人 */
+  updater?: string
+  /** 音量大小(0:关;1:低;2:中;3:高) */
+  voice?: number
+}
+interface WsSendLog对象 {
+  /** json串 */
+  content?: string
+  /** 创建日期时间 */
+  createDate?: string
+  /** 发送方(0-来自系统) */
+  fromUser?: string
+  /** id主键消息流水号 */
+  id?: number
+  /** 接收方 */
+  toUser?: string
+  /** 类型(0-通知类消息 1-加气确认 2-发往小票打印机) */
+  type?: number
+}

+ 8 - 0
src/types/shims-uni.d.ts

@@ -0,0 +1,8 @@
+/// <reference types='@dcloudio/types' />
+import 'vue'
+
+declare module '@vue/runtime-core' {
+  type Hooks = App.AppInstance & Page.PageInstance
+
+  interface ComponentCustomOptions extends Hooks {}
+}

+ 77 - 0
src/uni.scss

@@ -0,0 +1,77 @@
+/* stylelint-disable comment-empty-line-before */
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color: #333; // 基本色
+$uni-text-color-inverse: #fff; // 反色
+$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable: #c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color: #fff;
+$uni-bg-color-grey: #f8f8f8;
+$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
+$uni-bg-color-mask: rgb(0 0 0 / 40%); // 遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color: #c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm: 12px;
+$uni-font-size-base: 14px;
+$uni-font-size-lg: 16;
+
+/* 图片尺寸 */
+$uni-img-size-sm: 20px;
+$uni-img-size-base: 26px;
+$uni-img-size-lg: 40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2c405a; // 文章标题颜色
+$uni-font-size-title: 20px;
+$uni-color-subtitle: #555; // 二级标题颜色
+$uni-font-size-subtitle: 18px;
+$uni-color-paragraph: #3f536e; // 文章段落颜色
+$uni-font-size-paragraph: 15px;

+ 49 - 0
src/utils/aop/index.ts

@@ -0,0 +1,49 @@
+export default {
+  /** 请求 */
+  request: {
+    /** 前置通知 */
+    BA: {},
+    /** 后置通知 */
+    AR: {
+      getAccountInfo(res: 司机账户余额信息): IAccountInfo {
+        const accountInfo: IAccountInfo = {
+          showBalance: { balance: '', suffix: '' },
+          unit: '暂无余额',
+          showDet: false,
+        }
+        if (!res.orgName) {
+          accountInfo.orgName = '--'
+        }
+        if (!res.carNumber) {
+          accountInfo.carNumber = '--'
+        }
+
+        if (res.orgId) {
+          accountInfo.unit = '元'
+          if (res.autoAccount === 1 && res.flag === 1) {
+            accountInfo.showBalance.balance = `> ${res.limitAmount}`
+          } else {
+            accountInfo.showDet = true
+            accountInfo.showBalance.balance = res.totalBalance.toString()
+          }
+          if (accountInfo.showBalance.balance.includes('.')) {
+            const balanceArr = accountInfo.showBalance.balance.split('.')
+            accountInfo.showBalance.balance = balanceArr[0]
+            accountInfo.showBalance.suffix = '.' + balanceArr[1]
+          }
+        }
+        return accountInfo
+      },
+    },
+    /** 异常通知 */
+    AT: {
+      common({ args, res }) {
+        // console.log(args,res)
+      },
+    },
+    /** 最终通知 */
+    AF: {},
+    /** 环绕通知 */
+    AA: {},
+  },
+}

+ 89 - 0
src/utils/api/socket/stomp.ts

@@ -0,0 +1,89 @@
+import Stomp from 'stompjs'
+
+let socketOpen = false
+let socketMsgQueue = []
+
+export default {
+  client: null,
+  init(url, header, connectWS) {
+    if (this.client) {
+      return Promise.resolve(this.client)
+    }
+
+    return new Promise((resolve, reject) => {
+      const ws = {
+        send: this.sendMessage,
+        onopen: null,
+        onmessage: null,
+        close() {},
+      }
+
+      uni.connectSocket({ url, header })
+
+      uni.onSocketOpen(function (res) {
+        console.log('WebSocket连接已打开!', res)
+
+        socketOpen = true
+        for (let i = 0; i < socketMsgQueue.length; i++) {
+          ws.send(socketMsgQueue[i])
+        }
+        socketMsgQueue = []
+
+        ws.onopen && ws.onopen()
+      })
+
+      uni.onSocketMessage(function (res) {
+        // ios 缺少 0x00 导致解析失败
+        if (res && res.data) {
+          let value = res.data
+          const code = value.charCodeAt(value.length - 1)
+          if (code !== 0x00) {
+            value += String.fromCharCode(0x00)
+            res.data = value
+          }
+        }
+        ws.onmessage && ws.onmessage(res)
+      })
+
+      uni.onSocketError(function (res) {
+        // console.log('WebSocket 错误!', res)
+      })
+
+      uni.onSocketClose((res) => {
+        this.client = null
+        socketOpen = false
+        // console.log('WebSocket 已关闭!', res)
+        if (res.code !== 1000) {
+          setTimeout(() => {
+            connectWS()
+          }, 3000)
+        }
+      })
+
+      Stomp.setInterval = function (interval, f) {
+        return setInterval(f, interval)
+      }
+      Stomp.clearInterval = function (id) {
+        return clearInterval(id)
+      }
+
+      const client = (this.client = Stomp.over(ws))
+      // 关闭连接
+      client.close = () => {
+        uni.closeSocket()
+      }
+      client.connect(header, function () {
+        resolve(client)
+      })
+    })
+  },
+  sendMessage(message) {
+    if (socketOpen) {
+      uni.sendSocketMessage({
+        data: message,
+      })
+    } else {
+      socketMsgQueue.push(message)
+    }
+  },
+}

+ 86 - 0
src/utils/api/web/index.ts

@@ -0,0 +1,86 @@
+import request from './request'
+import webapi from '@/utils/config/webapi'
+
+type post = 'post'
+type get = 'get'
+type IIAPI<T> = {
+  [P in keyof T]: {
+    [C in keyof T[P]]: getIServiceApiUnionReq<T[P][C], post>
+  }
+}
+// 接口请求参数类型定义
+type QK = 'reqType'
+// 接口返回值类型定义
+type SK = 'resType'
+/** 取出具体接口 KT 设置的类型 */
+type GetKT<T, KT extends QK | SK> = T extends Record<KT, infer VT> ? VT : any
+
+/**
+ * 获取请求类型
+ * @generic T:具体接口的服务类型
+ * @generic RT:post 或 get
+ */
+type getReq<T, RT extends post | get> = T extends Record<RT, infer VT> ? VT : any
+/**
+ * 具体接口的服务类型
+ * @generic T:具体接口配置信息
+ */
+declare type getIServiceApi<T> = IServiceApi<GetKT<T, QK>, GetKT<T, SK>>
+
+/**
+ * 交集 getIServiceApi、getIServiceApi.[post|get]
+ * @generic T:具体接口配置信息
+ * @generic RT:post 或 get
+ */
+type getIServiceApiUnionReq<T, RT extends post | get> = getIServiceApi<T> &
+  getReq<getIServiceApi<T>, RT>
+
+const common = {} as IIAPI<typeof webapi>
+for (const [gk, gv] of Object.entries(webapi)) {
+  for (const [ik, iv] of Object.entries(gv)) {
+    if (!common[gk]) {
+      common[gk] = {}
+    }
+    const curws = {
+      get(args, ext) {
+        return request.get({
+          ext: {
+            ...config.common.RequestExtDef,
+            ...ext,
+          },
+          urlObj: iv,
+          uur: {
+            data: {
+              ...args,
+            },
+          },
+        })
+      },
+      post(args, ext) {
+        return request.post({
+          ext: {
+            ...config.common.RequestExtDef,
+            ...ext,
+          },
+          urlObj: iv,
+          uur: {
+            data: {
+              ...args,
+            },
+          },
+        })
+      },
+    }
+    common[gk][ik] = new Proxy(() => {}, {
+      // 拦截作为函数调用的操作,直接返回post方法
+      apply(target, thisArg, argArray) {
+        return curws.post(argArray[0], argArray[1])
+      },
+      // 拦截作为对象形式访问
+      get(target, p) {
+        return curws[p]
+      },
+    })
+  }
+}
+export default common

+ 31 - 0
src/utils/api/web/request/afterReturning.ts

@@ -0,0 +1,31 @@
+import common from '@/utils/store/common'
+import com from './com'
+export default {
+  /**
+   *
+   * 返回通知 成功拿到返回结果
+   */
+  async main(args: { options: IRequestOption; res: IResData<any> }) {
+    await com.complete.main(args)
+    // 设置接口请求状态
+    store.webapi[args.options.urlObj.group][args.options.urlObj.name].set(enums.ReqState.success)
+    if (args.options.urlObj.isUpload && typeof args.res.data === 'string') {
+      args.res.data = ay.getResourceUrl(args.res.data)
+    }
+    // 分页接口自动通知容器,数据加载完毕
+    if (store.curPage.pageConfig.isPager) {
+      let pages = config.common.defAyContainerRefreshArgs.pages
+      if (func.hasProps(args.res.data, config.common.IPageProps)) {
+        pages = args.res.data.pages
+      }
+      if (func.hasProps(args.res.data?.page, config.common.IPageProps)) {
+        pages = args.res.data.page.pages
+      }
+      ay.containerLoaded({
+        reqState: enums.ReqState.success,
+        pages,
+      })
+    }
+    return args.res.data
+  },
+}

+ 49 - 0
src/utils/api/web/request/afterThrowing.ts

@@ -0,0 +1,49 @@
+import com from './com'
+export default {
+  /**
+   *  异常通知 未成功拿到返回结果
+   */
+  async main(args: { options: IRequestOption } & TPromiseCatchReason) {
+    await com.complete.main(args)
+    // console.log('貌似网络不太稳定,请稍后重试', args.err)
+    // 设置接口请求状态
+    store.webapi[args.options.urlObj.group][args.options.urlObj.name].set(enums.ReqState.fail)
+    if (args.errType === enums.ErrorType.business) {
+      switch (args.res.code) {
+        case 2800: // 请求头中参数不存在或错误
+        case 2810: // 您提供的TOKEN解析错误
+        case 2811: // 您提供的Identifier解析错误
+        case 2812: // 您的Identifier与TOKEN不匹配
+        case 2813: // 您提供角色不在授权范围内
+        case 2814: // 登录已超时,请重新登录
+          store.user.clearUserInfo()
+          ay.goLogin()
+          break
+        default:
+          // 公共错误提示
+          func.native.showToast(args.res.message)
+      }
+    }
+    if (args.errType === enums.ErrorType.net) {
+      // 公共错误提示
+      func.native.showToast({
+        title: '网络错误',
+        icon: 'error',
+      })
+    }
+    const pcr: TPromiseCatchReason = {
+      errType: args.errType,
+      errInfo: args.errInfo,
+      options: args.options,
+      res: args.res,
+    }
+    // 分页页面- 接口异常自动通知容器
+    if (store.curPage.pageConfig.isPager) {
+      ay.containerLoaded({
+        reqState: enums.ReqState.fail,
+      })
+    }
+
+    return Promise.reject(pcr)
+  },
+}

+ 67 - 0
src/utils/api/web/request/before.ts

@@ -0,0 +1,67 @@
+import com from './com'
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+import { Base64 } from 'js-base64'
+
+export default {
+  /**
+   * 前置通知 发送请求之前
+   */
+  main(options: IRequestOption) {
+    if (options.ext.showLoading) {
+      com.loading.show(options)
+    }
+    // 设置接口请求状态
+    store.webapi[options.urlObj.group][options.urlObj.name].set(enums.ReqState.ing)
+    this.setReuqestArgs(options)
+  },
+  /** 设置请求参数 */
+  setReuqestArgs(options: IRequestOption) {
+    const rv: UUR = {
+      // 1. 请求超时
+      timeout: 10000,
+      url: options.urlObj.getUrl(),
+      header: this.getHeader(options),
+    }
+    if (options.ext.appendUrl) {
+      rv.url += options.ext.appendUrl
+    }
+    if (options.urlObj.isUpload) {
+      rv.name = 'file'
+      rv.formData = options.uur.data
+      if (options.ext.choosFiles.length === 1) {
+        rv.filePath = options.ext.choosFiles[0]
+      } else {
+        rv.files = options.ext.choosFiles.map((m) => {
+          return {
+            uri: m,
+          }
+        }) // as UniApp.UploadFileOptionFiles[]
+      }
+    } else {
+      rv.method = options.uur.method
+      rv.data = options.uur.data
+      rv.dataType = 'json'
+      // #ifndef MP-WEIXIN
+      rv.responseType = 'json'
+      // #endif
+    }
+    options.uur = rv
+  },
+  getHeader(options: IRequestOption) {
+    const header = {
+      'Content-Type': 'application/json;charset=UTF-8',
+      Authorization: store.user.Authorization,
+      Identifier: store.user.userInfo.Identifier,
+    }
+
+    if (options.urlObj.isUpload) {
+      delete header['Content-Type']
+    }
+    if (
+      [config.webapi.user.token.name, config.webapi.user.logout.name].includes(options.urlObj.name)
+    ) {
+      header['Content-Type'] = 'application/x-www-form-urlencoded'
+    }
+    return header
+  },
+}

+ 31 - 0
src/utils/api/web/request/com.ts

@@ -0,0 +1,31 @@
+const com = {
+  complete: {
+    async main(args: { options: IRequestOption }) {
+      if (store.common.data.debug) {
+        await func.awaiter()
+      }
+      if (args.options.ext.showLoading) {
+        if (--com.loading.count === 0) {
+          com.loading.hide()
+          //   if (utils.store.curPage) {
+          //     utils.store.curPage.common.show = true;
+          //   }
+        }
+      }
+    },
+  },
+  loading: {
+    cur: null,
+    count: 0,
+    show(options: IRequestOption) {
+      com.loading.count++
+      uni.showLoading({
+        title: options.ext.loadingText,
+      })
+    },
+    hide() {
+      uni.hideLoading()
+    },
+  },
+}
+export default com

+ 74 - 0
src/utils/api/web/request/index.ts

@@ -0,0 +1,74 @@
+import before from '@/utils/api/web/request/before'
+import afterReturning from './afterReturning'
+import afterThrowing from './afterThrowing'
+const setRequestResult = ({ options, resolve, reject }) => {
+  const rv = {
+    // 响应成功
+    success(res) {
+      if (options.urlObj.isUpload) {
+        res.data = JSON.parse(res.data)
+      }
+      resolve(res)
+    },
+    // 响应失败
+    fail(err) {
+      const rejectInfo = afterThrowing.main({
+        options,
+        errInfo: err as UniApp.RequestSuccessCallbackResult,
+        errType: enums.ErrorType.net,
+      })
+      reject(rejectInfo)
+    },
+  }
+  options.uur.success = rv.success
+  options.uur.fail = rv.fail
+}
+
+const http = async <T>(options: IRequestOption) => {
+  if (options.urlObj.isUpload) {
+    options.ext.choosFiles = await func.native.choose({ count: options.ext.fileCount })
+  }
+  // 1. 返回 Promise 对象
+  return new Promise<any>((resolve, reject) => {
+    before.main(options)
+    setRequestResult({ options, resolve, reject })
+    if (options.urlObj.isUpload) {
+      uni.uploadFile(options.uur as UniApp.UploadFileOption)
+    } else {
+      uni.request(options.uur as UniApp.RequestOptions)
+    }
+  }).then((res) => {
+    // 接口请求正常
+    if (res.statusCode === 200) {
+      // 业务逻辑正确
+      if (res.data.code === 0) {
+        return afterReturning.main({ options, res: res.data })
+      } else {
+        return afterThrowing.main({ options, res: res.data, errType: enums.ErrorType.business })
+      }
+    } else {
+      return afterThrowing.main({ options, errInfo: res, errType: enums.ErrorType.net })
+    }
+  })
+}
+
+/**
+ * GET 请求
+ * @param url 后台地址
+ * @param query 请求query参数
+ * @returns
+ */
+const httpGet = <T>(options: IRequestOption) => {
+  options.uur.method = 'GET'
+  return http<T>(options)
+}
+
+const httpPost = <T>(options: IRequestOption) => {
+  options.uur.method = 'POST'
+  return http<T>(options)
+}
+
+export default {
+  get: httpGet,
+  post: httpPost,
+}

+ 11 - 0
src/utils/api/web/request/preSetRAS.ts

@@ -0,0 +1,11 @@
+// 入参预处理
+import qs from 'qs'
+export default {
+  main(options: IRequestOption) {
+    // if (option.method === 'get') {
+    //   option.params = option.data
+    // }
+    // options.data = JSON.stringify(options.data)
+    return options
+  },
+}

+ 99 - 0
src/utils/config/index.ts

@@ -0,0 +1,99 @@
+import pages from './pages'
+import subPages from './subPages'
+import webapi from './webapi'
+const common = {
+  /** 订单状态 */
+  get orderStatus() {
+    return {
+      1: '待支付',
+      7: '支付异常',
+      4: '支付中',
+      2: '已支付',
+      3: '已取消',
+      6: '已退款',
+      5: '退款中',
+      // 待定
+      10: '其他',
+    }
+  },
+  /** 支付方式 */ get payType() {
+    return {
+      // 所属物流
+      0: '大象余额',
+      1: '微信',
+      2: '大象余额+微信',
+      // 个人支付
+      3: '微信',
+      // 待定
+      10: '其他',
+    }
+  },
+  /** 交易模式 */
+  get tradeType() {
+    return {
+      1: '大象经销',
+      2: '大象直销',
+      // 待定
+      10: '其他',
+    }
+  },
+  _SystemInfo: null as UniNamespace.GetSystemInfoResult,
+  get SystemInfo() {
+    if (!this._SystemInfo) {
+      this._SystemInfo = uni.getSystemInfoSync()
+    }
+    return this._SystemInfo
+  },
+  IPageProps: ['current', 'pages', 'total', 'records'],
+  /** 分页组件加载数据事件参数默认值 */
+  get defAyContainerRefreshArgs() {
+    return {
+      page: 1,
+      size: 10,
+      isAdd: false,
+    } as AyContainerRefreshArgs
+  },
+  /** 页面数据默认值 */
+  get defPageConfig() {
+    return {
+      _url: '',
+      title: '',
+      identity: true,
+      isPager: false,
+      pagerInfo: {
+        // #ifdef H5
+        /** loaded方法得到了通知 */
+        loaded: false,
+        // #endif
+        isAdd: false,
+        finished: false,
+        loading: false,
+        error: false,
+        // 页码
+        page: 1,
+        // 总页数
+        pages: 0,
+        // 加载完成后的提示文案
+        finishedText: '没有更多了',
+        // 加载过程中的提示文案
+        loadingText: '加载中...',
+        // 加载失败后的提示文案
+        errorText: '加载失败',
+      },
+    } as ayPage
+  },
+  get RequestExtDef() {
+    return {
+      isUpload: false,
+      showLoading: false,
+      loadingText: '加载中...',
+      fileCount: 1,
+    } as IRequestExt
+  },
+}
+export default {
+  pages,
+  subPages,
+  common,
+  webapi,
+}

+ 0 - 0
src/utils/config/interFaces/account.ts


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff