Compare commits
3 Commits
408527375f
...
02a96682f6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02a96682f6 | ||
|
|
21f8040994 | ||
|
|
29543ef0e7 |
3
apps/miniprogram/.env.production
Normal file
3
apps/miniprogram/.env.production
Normal file
@@ -0,0 +1,3 @@
|
||||
TARO_APP_API_URL=https://api.hms.example.com/api/v1
|
||||
TARO_APP_DEFAULT_TENANT_ID=
|
||||
TARO_APP_ENCRYPTION_KEY=
|
||||
8
apps/miniprogram/.prettierrc
Normal file
8
apps/miniprogram/.prettierrc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"arrowParens": "always"
|
||||
}
|
||||
@@ -20,8 +20,12 @@ export default defineConfig(async (merge) => {
|
||||
'process.env.TARO_APP_WX_TEMPLATE_CRITICAL_ALERT': JSON.stringify(process.env.TARO_APP_WX_TEMPLATE_CRITICAL_ALERT || ''),
|
||||
'process.env.TARO_APP_WX_TEMPLATE_HEALTH_ABNORMAL': JSON.stringify(process.env.TARO_APP_WX_TEMPLATE_HEALTH_ABNORMAL || ''),
|
||||
'process.env.TARO_APP_DEFAULT_TENANT_ID': JSON.stringify(process.env.TARO_APP_DEFAULT_TENANT_ID || ''),
|
||||
'process.env.TARO_APP_DEV_USER': JSON.stringify(process.env.TARO_APP_DEV_USER || ''),
|
||||
'process.env.TARO_APP_DEV_PASS': JSON.stringify(process.env.TARO_APP_DEV_PASS || ''),
|
||||
'process.env.TARO_APP_DEV_USER': JSON.stringify(
|
||||
process.env.NODE_ENV === 'production' ? '' : (process.env.TARO_APP_DEV_USER || '')
|
||||
),
|
||||
'process.env.TARO_APP_DEV_PASS': JSON.stringify(
|
||||
process.env.NODE_ENV === 'production' ? '' : (process.env.TARO_APP_DEV_PASS || '')
|
||||
),
|
||||
},
|
||||
copy: { patterns: [], options: {} },
|
||||
framework: 'react',
|
||||
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
compress: {
|
||||
drop_console: true,
|
||||
drop_debugger: true,
|
||||
pure_funcs: ['console.log', 'console.info', 'console.debug'],
|
||||
pure_funcs: ['console.log', 'console.info', 'console.debug', 'console.warn'],
|
||||
},
|
||||
format: {
|
||||
comments: false,
|
||||
|
||||
35
apps/miniprogram/eslint.config.mjs
Normal file
35
apps/miniprogram/eslint.config.mjs
Normal file
@@ -0,0 +1,35 @@
|
||||
import js from '@eslint/js';
|
||||
import ts from '@typescript-eslint/eslint-plugin';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
import reactHooks from 'eslint-plugin-react-hooks';
|
||||
import reactRefresh from 'eslint-plugin-react-refresh';
|
||||
|
||||
export default [
|
||||
{ ignores: ['dist/', 'dist-h5/', 'lib/', 'node_modules/', 'config/'] },
|
||||
{
|
||||
files: ['src/**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: { jsx: true },
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': ts,
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
},
|
||||
rules: {
|
||||
...js.configs.recommended.rules,
|
||||
...ts.configs.recommended.rules,
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -6,6 +6,11 @@
|
||||
"scripts": {
|
||||
"build:weapp": "taro build --type weapp",
|
||||
"dev:weapp": "taro build --type weapp --watch",
|
||||
"lint": "eslint src/",
|
||||
"lint:fix": "eslint src/ --fix",
|
||||
"format": "prettier --write 'src/**/*.{ts,tsx}'",
|
||||
"format:check": "prettier --check 'src/**/*.{ts,tsx}'",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test:e2e": "vitest run --config e2e/vitest.config.ts",
|
||||
"dev:h5": "dotenv -e .env.h5 -- taro build --type h5 --watch",
|
||||
"build:h5": "dotenv -e .env.h5 -- taro build --type h5"
|
||||
@@ -26,7 +31,8 @@
|
||||
"@tarojs/taro": "4.2.0",
|
||||
"react": "^18.3.0",
|
||||
"react-dom": "18.3.1",
|
||||
"zustand": "^5.0.0"
|
||||
"zustand": "^5.0.0",
|
||||
"@noble/ciphers": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.29.2",
|
||||
@@ -44,6 +50,15 @@
|
||||
"react-refresh": "^0.14.0",
|
||||
"sass": "^1.87.0",
|
||||
"typescript": "^5.8.0",
|
||||
"@types/node": "^22.0.0",
|
||||
"eslint": "^9.0.0",
|
||||
"@eslint/js": "^9.0.0",
|
||||
"@typescript-eslint/parser": "^8.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.0",
|
||||
"prettier": "^3.0.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"vite": "^8.0.10",
|
||||
"vitest": "^4.1.5",
|
||||
"webpack": "~5.95.0"
|
||||
|
||||
539
apps/miniprogram/pnpm-lock.yaml
generated
539
apps/miniprogram/pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@noble/ciphers':
|
||||
specifier: ^1.0.0
|
||||
version: 1.3.0
|
||||
'@tarojs/components':
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0(@tarojs/helper@4.2.0)(@types/react@18.3.28)(html-webpack-plugin@5.6.7(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(postcss@8.5.12)(rollup@3.30.0)(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))
|
||||
@@ -16,7 +19,7 @@ importers:
|
||||
version: 4.2.0
|
||||
'@tarojs/plugin-framework-react':
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0(@pmmmwh/react-refresh-webpack-plugin@0.6.2(react-refresh@0.14.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@tarojs/helper@4.2.0)(@tarojs/runtime@4.2.0)(@tarojs/shared@4.2.0)(react@18.3.1)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))
|
||||
version: 4.2.0(@pmmmwh/react-refresh-webpack-plugin@0.6.2(react-refresh@0.14.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@tarojs/helper@4.2.0)(@tarojs/runtime@4.2.0)(@tarojs/shared@4.2.0)(react@18.3.1)(vite@8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))
|
||||
'@tarojs/plugin-platform-weapp':
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0(@tarojs/service@4.2.0)(@tarojs/shared@4.2.0)
|
||||
@@ -54,30 +57,57 @@ importers:
|
||||
'@babel/runtime':
|
||||
specifier: ^7.27.0
|
||||
version: 7.29.2
|
||||
'@eslint/js':
|
||||
specifier: ^9.0.0
|
||||
version: 9.39.4
|
||||
'@pmmmwh/react-refresh-webpack-plugin':
|
||||
specifier: ^0.6.2
|
||||
version: 0.6.2(react-refresh@0.14.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))
|
||||
'@tarojs/cli':
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0(@types/node@25.6.0)
|
||||
version: 4.2.0(@types/node@22.19.19)
|
||||
'@tarojs/plugin-platform-h5':
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0(@tarojs/taro@4.2.0(@tarojs/components@4.2.0(@tarojs/helper@4.2.0)(@types/react@18.3.28)(html-webpack-plugin@5.6.7(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(postcss@8.5.12)(rollup@3.30.0)(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@tarojs/helper@4.2.0)(@tarojs/shared@4.2.0)(@types/react@18.3.28)(html-webpack-plugin@5.6.7(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(postcss@8.5.12)(rollup@3.30.0)(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@types/react@18.3.28)(html-webpack-plugin@5.6.7(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(postcss@8.5.12)(react@18.3.1)(rollup@3.30.0)(solid-js@1.9.13)(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))
|
||||
'@tarojs/webpack5-runner':
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0(@babel/core@7.29.0)(@swc/core@1.3.96)(@tarojs/runtime@4.2.0)(less@3.13.1)(postcss@8.5.12)(sass@1.99.0)(stylus@0.64.0)(typescript@5.9.3)(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))
|
||||
'@types/node':
|
||||
specifier: ^22.0.0
|
||||
version: 22.19.19
|
||||
'@types/react':
|
||||
specifier: ^18.3.0
|
||||
version: 18.3.28
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^8.0.0
|
||||
version: 8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^8.0.0
|
||||
version: 8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
|
||||
babel-preset-taro:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0(@babel/core@7.29.0)(@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0))(@babel/preset-react@7.28.5(@babel/core@7.29.0))(react-refresh@0.14.0)
|
||||
dotenv-cli:
|
||||
specifier: ^11.0.0
|
||||
version: 11.0.0
|
||||
eslint:
|
||||
specifier: ^9.0.0
|
||||
version: 9.39.4(jiti@2.6.1)
|
||||
eslint-config-prettier:
|
||||
specifier: ^10.0.0
|
||||
version: 10.1.8(eslint@9.39.4(jiti@2.6.1))
|
||||
eslint-plugin-react-hooks:
|
||||
specifier: ^5.0.0
|
||||
version: 5.2.0(eslint@9.39.4(jiti@2.6.1))
|
||||
eslint-plugin-react-refresh:
|
||||
specifier: ^0.4.0
|
||||
version: 0.4.26(eslint@9.39.4(jiti@2.6.1))
|
||||
miniprogram-automator:
|
||||
specifier: ^0.12.1
|
||||
version: 0.12.1
|
||||
prettier:
|
||||
specifier: ^3.0.0
|
||||
version: 3.8.3
|
||||
react-refresh:
|
||||
specifier: ^0.14.0
|
||||
version: 0.14.0
|
||||
@@ -89,10 +119,10 @@ importers:
|
||||
version: 5.9.3
|
||||
vite:
|
||||
specifier: ^8.0.10
|
||||
version: 8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
version: 8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
vitest:
|
||||
specifier: ^4.1.5
|
||||
version: 4.1.5(@types/node@25.6.0)(jsdom@24.1.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))
|
||||
version: 4.1.5(@types/node@22.19.19)(jsdom@24.1.3)(vite@8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))
|
||||
webpack:
|
||||
specifier: ~5.95.0
|
||||
version: 5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)
|
||||
@@ -1021,20 +1051,60 @@ packages:
|
||||
resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
|
||||
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
||||
|
||||
'@eslint/config-array@0.21.2':
|
||||
resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/config-helpers@0.4.2':
|
||||
resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/core@0.17.0':
|
||||
resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/eslintrc@2.1.4':
|
||||
resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
||||
'@eslint/eslintrc@3.3.5':
|
||||
resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/js@8.41.0':
|
||||
resolution: {integrity: sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
||||
'@eslint/js@9.39.4':
|
||||
resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/object-schema@2.1.7':
|
||||
resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/plugin-kit@0.4.1':
|
||||
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@hapi/hoek@9.3.0':
|
||||
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
|
||||
|
||||
'@hapi/topo@5.1.0':
|
||||
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
|
||||
|
||||
'@humanfs/core@0.19.2':
|
||||
resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
||||
'@humanfs/node@0.16.8':
|
||||
resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
||||
'@humanfs/types@0.15.0':
|
||||
resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
||||
'@humanwhocodes/config-array@0.11.14':
|
||||
resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
|
||||
engines: {node: '>=10.10.0'}
|
||||
@@ -1048,6 +1118,10 @@ packages:
|
||||
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
|
||||
deprecated: Use @eslint/object-schema instead
|
||||
|
||||
'@humanwhocodes/retry@0.4.3':
|
||||
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
||||
engines: {node: '>=18.18'}
|
||||
|
||||
'@inquirer/external-editor@1.0.3':
|
||||
resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -1245,6 +1319,10 @@ packages:
|
||||
'@emnapi/core': ^1.7.1
|
||||
'@emnapi/runtime': ^1.7.1
|
||||
|
||||
'@noble/ciphers@1.3.0':
|
||||
resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
|
||||
engines: {node: ^14.21.3 || >=16}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -1981,8 +2059,8 @@ packages:
|
||||
'@types/node-forge@1.3.14':
|
||||
resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==}
|
||||
|
||||
'@types/node@25.6.0':
|
||||
resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==}
|
||||
'@types/node@22.19.19':
|
||||
resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==}
|
||||
|
||||
'@types/postcss-url@10.0.4':
|
||||
resolution: {integrity: sha512-5QIO9NgbWmAkle65haRqkdgYPCOXheNsaFdbTJJQjT302yK3H49ql4t9a4y0NfpuPtU/UBo15VcV64WCSIMJKg==}
|
||||
@@ -2036,6 +2114,65 @@ packages:
|
||||
'@types/yargs@17.0.35':
|
||||
resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.59.4':
|
||||
resolution: {integrity: sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^8.59.4
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/parser@8.59.4':
|
||||
resolution: {integrity: sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/project-service@8.59.4':
|
||||
resolution: {integrity: sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/scope-manager@8.59.4':
|
||||
resolution: {integrity: sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.59.4':
|
||||
resolution: {integrity: sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/type-utils@8.59.4':
|
||||
resolution: {integrity: sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/types@8.59.4':
|
||||
resolution: {integrity: sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.59.4':
|
||||
resolution: {integrity: sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/utils@8.59.4':
|
||||
resolution: {integrity: sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.59.4':
|
||||
resolution: {integrity: sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@vitest/expect@4.1.5':
|
||||
resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==}
|
||||
|
||||
@@ -3081,6 +3218,23 @@ packages:
|
||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
eslint-config-prettier@10.1.8:
|
||||
resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
eslint: '>=7.0.0'
|
||||
|
||||
eslint-plugin-react-hooks@5.2.0:
|
||||
resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
|
||||
|
||||
eslint-plugin-react-refresh@0.4.26:
|
||||
resolution: {integrity: sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==}
|
||||
peerDependencies:
|
||||
eslint: '>=8.40'
|
||||
|
||||
eslint-scope@5.1.1:
|
||||
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
@@ -3089,16 +3243,42 @@ packages:
|
||||
resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
||||
eslint-scope@8.4.0:
|
||||
resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
eslint-visitor-keys@3.4.3:
|
||||
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
||||
eslint-visitor-keys@4.2.1:
|
||||
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
eslint-visitor-keys@5.0.1:
|
||||
resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==}
|
||||
engines: {node: ^20.19.0 || ^22.13.0 || >=24}
|
||||
|
||||
eslint@8.41.0:
|
||||
resolution: {integrity: sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
|
||||
hasBin: true
|
||||
|
||||
eslint@9.39.4:
|
||||
resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
jiti: '*'
|
||||
peerDependenciesMeta:
|
||||
jiti:
|
||||
optional: true
|
||||
|
||||
espree@10.4.0:
|
||||
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
espree@9.6.1:
|
||||
resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -3206,6 +3386,10 @@ packages:
|
||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
|
||||
file-entry-cache@8.0.0:
|
||||
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
|
||||
file-type@3.9.0:
|
||||
resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -3269,6 +3453,10 @@ packages:
|
||||
resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
|
||||
flat-cache@4.0.1:
|
||||
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
flat@5.0.2:
|
||||
resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
|
||||
hasBin: true
|
||||
@@ -3415,6 +3603,10 @@ packages:
|
||||
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
globals@14.0.0:
|
||||
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
globby@14.1.0:
|
||||
resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -4835,6 +5027,11 @@ packages:
|
||||
resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
prettier@3.8.3:
|
||||
resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
||||
pretty-bytes@5.6.0:
|
||||
resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -5547,6 +5744,12 @@ packages:
|
||||
resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
ts-api-utils@2.5.0:
|
||||
resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==}
|
||||
engines: {node: '>=18.12'}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4'
|
||||
|
||||
tslib@1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
|
||||
@@ -5593,8 +5796,8 @@ packages:
|
||||
unbzip2-stream@1.4.3:
|
||||
resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==}
|
||||
|
||||
undici-types@7.19.2:
|
||||
resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==}
|
||||
undici-types@6.21.0:
|
||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||
|
||||
unescape-js@1.1.4:
|
||||
resolution: {integrity: sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g==}
|
||||
@@ -6972,8 +7175,29 @@ snapshots:
|
||||
eslint: 8.41.0
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))':
|
||||
dependencies:
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/regexpp@4.12.2': {}
|
||||
|
||||
'@eslint/config-array@0.21.2':
|
||||
dependencies:
|
||||
'@eslint/object-schema': 2.1.7
|
||||
debug: 4.4.3
|
||||
minimatch: 3.1.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@eslint/config-helpers@0.4.2':
|
||||
dependencies:
|
||||
'@eslint/core': 0.17.0
|
||||
|
||||
'@eslint/core@0.17.0':
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
'@eslint/eslintrc@2.1.4':
|
||||
dependencies:
|
||||
ajv: 6.15.0
|
||||
@@ -6988,14 +7212,49 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@eslint/eslintrc@3.3.5':
|
||||
dependencies:
|
||||
ajv: 6.15.0
|
||||
debug: 4.4.3
|
||||
espree: 10.4.0
|
||||
globals: 14.0.0
|
||||
ignore: 5.3.2
|
||||
import-fresh: 3.3.1
|
||||
js-yaml: 4.1.1
|
||||
minimatch: 3.1.5
|
||||
strip-json-comments: 3.1.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@eslint/js@8.41.0': {}
|
||||
|
||||
'@eslint/js@9.39.4': {}
|
||||
|
||||
'@eslint/object-schema@2.1.7': {}
|
||||
|
||||
'@eslint/plugin-kit@0.4.1':
|
||||
dependencies:
|
||||
'@eslint/core': 0.17.0
|
||||
levn: 0.4.1
|
||||
|
||||
'@hapi/hoek@9.3.0': {}
|
||||
|
||||
'@hapi/topo@5.1.0':
|
||||
dependencies:
|
||||
'@hapi/hoek': 9.3.0
|
||||
|
||||
'@humanfs/core@0.19.2':
|
||||
dependencies:
|
||||
'@humanfs/types': 0.15.0
|
||||
|
||||
'@humanfs/node@0.16.8':
|
||||
dependencies:
|
||||
'@humanfs/core': 0.19.2
|
||||
'@humanfs/types': 0.15.0
|
||||
'@humanwhocodes/retry': 0.4.3
|
||||
|
||||
'@humanfs/types@0.15.0': {}
|
||||
|
||||
'@humanwhocodes/config-array@0.11.14':
|
||||
dependencies:
|
||||
'@humanwhocodes/object-schema': 2.0.3
|
||||
@@ -7008,12 +7267,14 @@ snapshots:
|
||||
|
||||
'@humanwhocodes/object-schema@2.0.3': {}
|
||||
|
||||
'@inquirer/external-editor@1.0.3(@types/node@25.6.0)':
|
||||
'@humanwhocodes/retry@0.4.3': {}
|
||||
|
||||
'@inquirer/external-editor@1.0.3(@types/node@22.19.19)':
|
||||
dependencies:
|
||||
chardet: 2.1.1
|
||||
iconv-lite: 0.7.2
|
||||
optionalDependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
dependencies:
|
||||
@@ -7032,7 +7293,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/istanbul-lib-coverage': 2.0.6
|
||||
'@types/istanbul-reports': 3.0.4
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
'@types/yargs': 15.0.20
|
||||
chalk: 4.1.2
|
||||
|
||||
@@ -7041,7 +7302,7 @@ snapshots:
|
||||
'@jest/schemas': 29.6.3
|
||||
'@types/istanbul-lib-coverage': 2.0.6
|
||||
'@types/istanbul-reports': 3.0.4
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
'@types/yargs': 17.0.35
|
||||
chalk: 4.1.2
|
||||
|
||||
@@ -7295,6 +7556,8 @@ snapshots:
|
||||
'@tybys/wasm-util': 0.10.1
|
||||
optional: true
|
||||
|
||||
'@noble/ciphers@1.3.0': {}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
dependencies:
|
||||
'@nodelib/fs.stat': 2.0.5
|
||||
@@ -7564,7 +7827,7 @@ snapshots:
|
||||
'@tarojs/binding-linux-x64-gnu': 4.2.0
|
||||
'@tarojs/binding-win32-x64-msvc': 4.2.0
|
||||
|
||||
'@tarojs/cli@4.2.0(@types/node@25.6.0)':
|
||||
'@tarojs/cli@4.2.0(@types/node@22.19.19)':
|
||||
dependencies:
|
||||
'@tarojs/binding': 4.2.0
|
||||
'@tarojs/helper': 4.2.0
|
||||
@@ -7576,7 +7839,7 @@ snapshots:
|
||||
cli-highlight: 2.1.11
|
||||
download-git-repo: 3.0.2
|
||||
envinfo: 7.21.0
|
||||
inquirer: 8.2.7(@types/node@25.6.0)
|
||||
inquirer: 8.2.7(@types/node@22.19.19)
|
||||
latest-version: 5.1.0
|
||||
minimist: 1.2.8
|
||||
ora: 5.4.1
|
||||
@@ -7709,7 +7972,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@tarojs/plugin-framework-react@4.2.0(@pmmmwh/react-refresh-webpack-plugin@0.6.2(react-refresh@0.14.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@tarojs/helper@4.2.0)(@tarojs/runtime@4.2.0)(@tarojs/shared@4.2.0)(react@18.3.1)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))':
|
||||
'@tarojs/plugin-framework-react@4.2.0(@pmmmwh/react-refresh-webpack-plugin@0.6.2(react-refresh@0.14.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@tarojs/helper@4.2.0)(@tarojs/runtime@4.2.0)(@tarojs/shared@4.2.0)(react@18.3.1)(vite@8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))':
|
||||
dependencies:
|
||||
'@tarojs/helper': 4.2.0
|
||||
'@tarojs/runtime': 4.2.0
|
||||
@@ -7721,7 +7984,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@pmmmwh/react-refresh-webpack-plugin': 0.6.2(react-refresh@0.14.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))
|
||||
react: 18.3.1
|
||||
vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
vite: 8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
webpack: 5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)
|
||||
|
||||
'@tarojs/plugin-platform-h5@4.2.0(@tarojs/taro@4.2.0(@tarojs/components@4.2.0(@tarojs/helper@4.2.0)(@types/react@18.3.28)(html-webpack-plugin@5.6.7(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(postcss@8.5.12)(rollup@3.30.0)(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@tarojs/helper@4.2.0)(@tarojs/shared@4.2.0)(@types/react@18.3.28)(html-webpack-plugin@5.6.7(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(postcss@8.5.12)(rollup@3.30.0)(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(@types/react@18.3.28)(html-webpack-plugin@5.6.7(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(postcss@8.5.12)(react@18.3.1)(rollup@3.30.0)(solid-js@1.9.13)(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7)))(webpack@5.95.0(@swc/core@1.3.96)(esbuild@0.27.7))':
|
||||
@@ -7952,11 +8215,11 @@ snapshots:
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/bonjour@3.5.13':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/chai@5.2.3':
|
||||
dependencies:
|
||||
@@ -7966,11 +8229,11 @@ snapshots:
|
||||
'@types/connect-history-api-fallback@1.5.4':
|
||||
dependencies:
|
||||
'@types/express-serve-static-core': 5.1.1
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/debug@4.1.13':
|
||||
dependencies:
|
||||
@@ -7982,14 +8245,14 @@ snapshots:
|
||||
|
||||
'@types/express-serve-static-core@4.19.8':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
'@types/qs': 6.15.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 1.2.1
|
||||
|
||||
'@types/express-serve-static-core@5.1.1':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
'@types/qs': 6.15.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 1.2.1
|
||||
@@ -8003,12 +8266,12 @@ snapshots:
|
||||
|
||||
'@types/fs-extra@8.1.5':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/glob@7.2.0':
|
||||
dependencies:
|
||||
'@types/minimatch': 6.0.0
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/html-minifier-terser@6.1.0': {}
|
||||
|
||||
@@ -8016,7 +8279,7 @@ snapshots:
|
||||
|
||||
'@types/http-proxy@1.17.17':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/istanbul-lib-coverage@2.0.6': {}
|
||||
|
||||
@@ -8032,7 +8295,7 @@ snapshots:
|
||||
|
||||
'@types/keyv@3.1.4':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/lodash.debounce@4.0.9':
|
||||
dependencies:
|
||||
@@ -8050,15 +8313,15 @@ snapshots:
|
||||
|
||||
'@types/node-forge@1.3.14':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/node@25.6.0':
|
||||
'@types/node@22.19.19':
|
||||
dependencies:
|
||||
undici-types: 7.19.2
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/postcss-url@10.0.4':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
postcss: 8.5.12
|
||||
|
||||
'@types/prop-types@15.7.15': {}
|
||||
@@ -8074,7 +8337,7 @@ snapshots:
|
||||
|
||||
'@types/responselike@1.0.3':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/retry@0.12.0': {}
|
||||
|
||||
@@ -8085,11 +8348,11 @@ snapshots:
|
||||
'@types/send@0.17.6':
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/send@1.2.1':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/serve-index@1.9.4':
|
||||
dependencies:
|
||||
@@ -8098,16 +8361,16 @@ snapshots:
|
||||
'@types/serve-static@1.15.10':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.5
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
'@types/send': 0.17.6
|
||||
|
||||
'@types/sockjs@0.3.36':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
|
||||
'@types/yargs-parser@21.0.3': {}
|
||||
|
||||
@@ -8119,6 +8382,97 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/yargs-parser': 21.0.3
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@typescript-eslint/parser': 8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
|
||||
'@typescript-eslint/scope-manager': 8.59.4
|
||||
'@typescript-eslint/type-utils': 8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
ignore: 7.0.5
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.59.4
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/typescript-estree': 8.59.4(typescript@5.9.3)
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
debug: 4.4.3
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/project-service@8.59.4(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.59.4(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
debug: 4.4.3
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/scope-manager@8.59.4':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.59.4(typescript@5.9.3)':
|
||||
dependencies:
|
||||
typescript: 5.9.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/typescript-estree': 8.59.4(typescript@5.9.3)
|
||||
'@typescript-eslint/utils': 8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)
|
||||
debug: 4.4.3
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/types@8.59.4': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.59.4(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/project-service': 8.59.4(typescript@5.9.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.59.4(typescript@5.9.3)
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/visitor-keys': 8.59.4
|
||||
debug: 4.4.3
|
||||
minimatch: 10.2.5
|
||||
semver: 7.7.4
|
||||
tinyglobby: 0.2.16
|
||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.59.4(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
|
||||
'@typescript-eslint/scope-manager': 8.59.4
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
'@typescript-eslint/typescript-estree': 8.59.4(typescript@5.9.3)
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
typescript: 5.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.59.4':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.59.4
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
'@vitest/expect@4.1.5':
|
||||
dependencies:
|
||||
'@standard-schema/spec': 1.1.0
|
||||
@@ -8128,13 +8482,13 @@ snapshots:
|
||||
chai: 6.2.2
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@vitest/mocker@4.1.5(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))':
|
||||
'@vitest/mocker@4.1.5(vite@8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))':
|
||||
dependencies:
|
||||
'@vitest/spy': 4.1.5
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
vite: 8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
|
||||
'@vitest/pretty-format@4.1.5':
|
||||
dependencies:
|
||||
@@ -9331,6 +9685,18 @@ snapshots:
|
||||
|
||||
escape-string-regexp@4.0.0: {}
|
||||
|
||||
eslint-config-prettier@10.1.8(eslint@9.39.4(jiti@2.6.1)):
|
||||
dependencies:
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
|
||||
eslint-plugin-react-hooks@5.2.0(eslint@9.39.4(jiti@2.6.1)):
|
||||
dependencies:
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
|
||||
eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@2.6.1)):
|
||||
dependencies:
|
||||
eslint: 9.39.4(jiti@2.6.1)
|
||||
|
||||
eslint-scope@5.1.1:
|
||||
dependencies:
|
||||
esrecurse: 4.3.0
|
||||
@@ -9341,8 +9707,17 @@ snapshots:
|
||||
esrecurse: 4.3.0
|
||||
estraverse: 5.3.0
|
||||
|
||||
eslint-scope@8.4.0:
|
||||
dependencies:
|
||||
esrecurse: 4.3.0
|
||||
estraverse: 5.3.0
|
||||
|
||||
eslint-visitor-keys@3.4.3: {}
|
||||
|
||||
eslint-visitor-keys@4.2.1: {}
|
||||
|
||||
eslint-visitor-keys@5.0.1: {}
|
||||
|
||||
eslint@8.41.0:
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@8.41.0)
|
||||
@@ -9387,6 +9762,53 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint@9.39.4(jiti@2.6.1):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1))
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@eslint/config-array': 0.21.2
|
||||
'@eslint/config-helpers': 0.4.2
|
||||
'@eslint/core': 0.17.0
|
||||
'@eslint/eslintrc': 3.3.5
|
||||
'@eslint/js': 9.39.4
|
||||
'@eslint/plugin-kit': 0.4.1
|
||||
'@humanfs/node': 0.16.8
|
||||
'@humanwhocodes/module-importer': 1.0.1
|
||||
'@humanwhocodes/retry': 0.4.3
|
||||
'@types/estree': 1.0.8
|
||||
ajv: 6.15.0
|
||||
chalk: 4.1.2
|
||||
cross-spawn: 7.0.6
|
||||
debug: 4.4.3
|
||||
escape-string-regexp: 4.0.0
|
||||
eslint-scope: 8.4.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
espree: 10.4.0
|
||||
esquery: 1.7.0
|
||||
esutils: 2.0.3
|
||||
fast-deep-equal: 3.1.3
|
||||
file-entry-cache: 8.0.0
|
||||
find-up: 5.0.0
|
||||
glob-parent: 6.0.2
|
||||
ignore: 5.3.2
|
||||
imurmurhash: 0.1.4
|
||||
is-glob: 4.0.3
|
||||
json-stable-stringify-without-jsonify: 1.0.1
|
||||
lodash.merge: 4.6.2
|
||||
minimatch: 3.1.5
|
||||
natural-compare: 1.4.0
|
||||
optionator: 0.9.4
|
||||
optionalDependencies:
|
||||
jiti: 2.6.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
espree@10.4.0:
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
acorn-jsx: 5.3.2(acorn@8.16.0)
|
||||
eslint-visitor-keys: 4.2.1
|
||||
|
||||
espree@9.6.1:
|
||||
dependencies:
|
||||
acorn: 8.16.0
|
||||
@@ -9520,6 +9942,10 @@ snapshots:
|
||||
dependencies:
|
||||
flat-cache: 3.2.0
|
||||
|
||||
file-entry-cache@8.0.0:
|
||||
dependencies:
|
||||
flat-cache: 4.0.1
|
||||
|
||||
file-type@3.9.0: {}
|
||||
|
||||
file-type@4.4.0: {}
|
||||
@@ -9583,6 +10009,11 @@ snapshots:
|
||||
keyv: 4.5.4
|
||||
rimraf: 3.0.2
|
||||
|
||||
flat-cache@4.0.1:
|
||||
dependencies:
|
||||
flatted: 3.4.2
|
||||
keyv: 4.5.4
|
||||
|
||||
flat@5.0.2: {}
|
||||
|
||||
flatted@3.4.2: {}
|
||||
@@ -9736,6 +10167,8 @@ snapshots:
|
||||
dependencies:
|
||||
type-fest: 0.20.2
|
||||
|
||||
globals@14.0.0: {}
|
||||
|
||||
globby@14.1.0:
|
||||
dependencies:
|
||||
'@sindresorhus/merge-streams': 2.3.0
|
||||
@@ -10001,9 +10434,9 @@ snapshots:
|
||||
|
||||
ini@1.3.8: {}
|
||||
|
||||
inquirer@8.2.7(@types/node@25.6.0):
|
||||
inquirer@8.2.7(@types/node@22.19.19):
|
||||
dependencies:
|
||||
'@inquirer/external-editor': 1.0.3(@types/node@25.6.0)
|
||||
'@inquirer/external-editor': 1.0.3(@types/node@22.19.19)
|
||||
ansi-escapes: 4.3.2
|
||||
chalk: 4.1.2
|
||||
cli-cursor: 3.1.0
|
||||
@@ -10134,7 +10567,7 @@ snapshots:
|
||||
jest-util@29.7.0:
|
||||
dependencies:
|
||||
'@jest/types': 29.6.3
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.9.0
|
||||
graceful-fs: 4.2.11
|
||||
@@ -10142,13 +10575,13 @@ snapshots:
|
||||
|
||||
jest-worker@27.5.1:
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 8.1.1
|
||||
|
||||
jest-worker@29.7.0:
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
jest-util: 29.7.0
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 8.1.1
|
||||
@@ -11109,6 +11542,8 @@ snapshots:
|
||||
|
||||
prepend-http@2.0.0: {}
|
||||
|
||||
prettier@3.8.3: {}
|
||||
|
||||
pretty-bytes@5.6.0: {}
|
||||
|
||||
pretty-error@4.0.0:
|
||||
@@ -11871,6 +12306,10 @@ snapshots:
|
||||
dependencies:
|
||||
escape-string-regexp: 1.0.5
|
||||
|
||||
ts-api-utils@2.5.0(typescript@5.9.3):
|
||||
dependencies:
|
||||
typescript: 5.9.3
|
||||
|
||||
tslib@1.14.1: {}
|
||||
|
||||
tslib@2.8.1: {}
|
||||
@@ -11909,7 +12348,7 @@ snapshots:
|
||||
buffer: 5.7.1
|
||||
through: 2.3.8
|
||||
|
||||
undici-types@7.19.2: {}
|
||||
undici-types@6.21.0: {}
|
||||
|
||||
unescape-js@1.1.4:
|
||||
dependencies:
|
||||
@@ -11989,7 +12428,7 @@ snapshots:
|
||||
|
||||
vary@1.1.2: {}
|
||||
|
||||
vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2):
|
||||
vite@8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2):
|
||||
dependencies:
|
||||
lightningcss: 1.32.0
|
||||
picomatch: 4.0.4
|
||||
@@ -11997,7 +12436,7 @@ snapshots:
|
||||
rolldown: 1.0.0-rc.17
|
||||
tinyglobby: 0.2.16
|
||||
optionalDependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
esbuild: 0.27.7
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.6.1
|
||||
@@ -12006,10 +12445,10 @@ snapshots:
|
||||
stylus: 0.64.0
|
||||
terser: 5.46.2
|
||||
|
||||
vitest@4.1.5(@types/node@25.6.0)(jsdom@24.1.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)):
|
||||
vitest@4.1.5(@types/node@22.19.19)(jsdom@24.1.3)(vite@8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)):
|
||||
dependencies:
|
||||
'@vitest/expect': 4.1.5
|
||||
'@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))
|
||||
'@vitest/mocker': 4.1.5(vite@8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2))
|
||||
'@vitest/pretty-format': 4.1.5
|
||||
'@vitest/runner': 4.1.5
|
||||
'@vitest/snapshot': 4.1.5
|
||||
@@ -12026,10 +12465,10 @@ snapshots:
|
||||
tinyexec: 1.1.1
|
||||
tinyglobby: 0.2.16
|
||||
tinyrainbow: 3.1.0
|
||||
vite: 8.0.10(@types/node@25.6.0)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
vite: 8.0.10(@types/node@22.19.19)(esbuild@0.27.7)(jiti@2.6.1)(less@3.13.1)(sass@1.99.0)(stylus@0.64.0)(terser@5.46.2)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 22.19.19
|
||||
jsdom: 24.1.3
|
||||
transitivePeerDependencies:
|
||||
- msw
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import './utils/crypto-polyfill';
|
||||
import { useEffect, useRef, PropsWithChildren } from 'react';
|
||||
import Taro, { useDidShow, useDidHide } from '@tarojs/taro';
|
||||
import { useDidShow, useDidHide } from '@tarojs/taro';
|
||||
import ErrorBoundary from './components/ErrorBoundary';
|
||||
import { flushEvents } from './services/analytics';
|
||||
import { useAuthStore } from './stores/auth';
|
||||
|
||||
@@ -1,31 +1,77 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Component } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import './index.scss';
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
fallback?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
retryCount: number;
|
||||
errorCategory: ErrorCategory;
|
||||
}
|
||||
|
||||
type ErrorCategory = 'network' | 'render' | 'unknown';
|
||||
|
||||
const MAX_RETRIES = 3;
|
||||
|
||||
function classifyError(error: Error): ErrorCategory {
|
||||
const msg = error.message?.toLowerCase() || '';
|
||||
if (
|
||||
msg.includes('network') ||
|
||||
msg.includes('fetch') ||
|
||||
msg.includes('timeout') ||
|
||||
msg.includes('request:fail')
|
||||
) {
|
||||
return 'network';
|
||||
}
|
||||
if (
|
||||
msg.includes('cannot read properties') ||
|
||||
msg.includes('is not defined') ||
|
||||
msg.includes('is not a function') ||
|
||||
msg.includes('render')
|
||||
) {
|
||||
return 'render';
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
function logError(error: Error, info: React.ErrorInfo, category: ErrorCategory): void {
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
const entry = {
|
||||
ts: new Date().toISOString(),
|
||||
category,
|
||||
message: error.message,
|
||||
stack: isDev ? error.stack : undefined,
|
||||
componentStack: isDev ? info.componentStack : undefined,
|
||||
};
|
||||
|
||||
if (isDev) {
|
||||
console.error('[ErrorBoundary]', JSON.stringify(entry, null, 2));
|
||||
} else {
|
||||
console.error('[ErrorBoundary]', entry.ts, entry.category, entry.message);
|
||||
}
|
||||
}
|
||||
|
||||
export default class ErrorBoundary extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { hasError: false, retryCount: 0 };
|
||||
this.state = { hasError: false, retryCount: 0, errorCategory: 'unknown' };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(): Partial<State> {
|
||||
return { hasError: true };
|
||||
static getDerivedStateFromError(error: Error): Partial<State> {
|
||||
return { hasError: true, errorCategory: classifyError(error) };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, info: React.ErrorInfo) {
|
||||
console.error('[ErrorBoundary]', error, info.componentStack);
|
||||
this.setState((prev) => ({ retryCount: prev.retryCount + 1 }));
|
||||
const category = classifyError(error);
|
||||
logError(error, info, category);
|
||||
this.setState((prev) => ({
|
||||
retryCount: prev.retryCount + 1,
|
||||
errorCategory: category,
|
||||
}));
|
||||
}
|
||||
|
||||
handleRetry = () => {
|
||||
@@ -34,21 +80,28 @@ export default class ErrorBoundary extends Component<Props, State> {
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
if (this.props.fallback) {
|
||||
return this.props.fallback;
|
||||
}
|
||||
|
||||
const exceeded = this.state.retryCount >= MAX_RETRIES;
|
||||
const isNetwork = this.state.errorCategory === 'network';
|
||||
const title = isNetwork ? '网络连接失败' : '页面出了点问题';
|
||||
const desc = exceeded
|
||||
? '请重启小程序后重试'
|
||||
: isNetwork
|
||||
? '请检查网络后重试'
|
||||
: '请返回重试';
|
||||
|
||||
return (
|
||||
<View className='error-boundary'>
|
||||
<View className='error-icon-wrap'>
|
||||
<Text className='error-icon-text'>!</Text>
|
||||
</View>
|
||||
<Text className='error-title'>页面出了点问题</Text>
|
||||
<Text className='error-desc'>
|
||||
{exceeded ? '请重启小程序' : '请返回重试'}
|
||||
</Text>
|
||||
<Text className='error-title'>{title}</Text>
|
||||
<Text className='error-desc'>{desc}</Text>
|
||||
{!exceeded && (
|
||||
<View
|
||||
className='error-retry-btn'
|
||||
onClick={this.handleRetry}
|
||||
>
|
||||
<View className='error-retry-btn' onClick={this.handleRetry}>
|
||||
<Text className='error-retry-text'>重新加载</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -3,6 +3,10 @@ import { Canvas, View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import './index.scss';
|
||||
|
||||
/** Canvas 2D 上下文类型 — 微信小程序 Canvas 2d 接口 */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type CanvasRenderingContext2D = any;
|
||||
|
||||
interface TrendChartProps {
|
||||
data: { date: string; value: number }[];
|
||||
referenceMin?: number;
|
||||
@@ -181,7 +185,6 @@ export default React.memo(function TrendChart({
|
||||
if (!node) return;
|
||||
canvasRef.current = node;
|
||||
const sysInfo = Taro.getSystemInfoSync();
|
||||
const canvasW = (sysInfo.windowWidth * 750) / sysInfo.windowWidth;
|
||||
node.width = sysInfo.windowWidth * getDPR();
|
||||
node.height = ((height / 750) * sysInfo.windowWidth) * getDPR();
|
||||
draw();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import './index.scss';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, RichText } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, ScrollView } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback, useMemo } from 'react';
|
||||
import { useState, useCallback, useMemo } from 'react';
|
||||
import { View, Text, Input } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { listDoctors, createAppointment, calendarView } from '../../../services/appointment';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { getAppointment, cancelAppointment } from '../../../services/appointment';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
@@ -38,7 +38,7 @@ export default function AppointmentList() {
|
||||
const fetchData = useCallback(async (pageNum: number, isRefresh = false) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await listAppointments(pageNum);
|
||||
const res = await listAppointments(undefined, pageNum);
|
||||
const list = res.data || [];
|
||||
if (isRefresh) {
|
||||
setAppointments(list);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, RichText } from '@tarojs/components';
|
||||
import Taro, { useRouter, useShareAppMessage } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -34,8 +34,8 @@ interface ArticleCategory {
|
||||
export default function ArticleList() {
|
||||
const modeClass = useElderClass();
|
||||
const [articles, setArticles] = useState<ArticleItem[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [, setPage] = useState(1);
|
||||
const [, setTotal] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(false);
|
||||
const [categories, setCategories] = useState<ArticleCategory[]>([]);
|
||||
|
||||
@@ -84,7 +84,7 @@ export default function ConsultationCreate() {
|
||||
const typeLabels = CONSULTATION_TYPES.map((t) => TYPE_LABELS[t] || t);
|
||||
|
||||
return (
|
||||
<PageShell title='发起咨询' scroll={false}>
|
||||
<PageShell scroll={false}>
|
||||
<View className={`consult-create ${modeClass}`}>
|
||||
<View className='consult-create__section'>
|
||||
<Text className='consult-create__label'>咨询类型</Text>
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function Health() {
|
||||
const currentPatient = useAuthStore((s) => s.currentPatient);
|
||||
const modeClass = useElderClass();
|
||||
const {
|
||||
user, todaySummary, loading, error, activeTab, trendData, trendLoading,
|
||||
user, todaySummary: _todaySummary, loading: _loading, error, activeTab, trendData, trendLoading,
|
||||
aiSuggestions, thresholds, handleTabChange, loadTrend, refreshToday, fetchData,
|
||||
} = useHealthData();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useState, useRef } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useHealthStore } from '@/stores/health';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import { getTrend, getHealthThresholds, DEFAULT_THRESHOLDS, type HealthThreshold } from '@/services/health';
|
||||
import { getHealthThresholds, DEFAULT_THRESHOLDS, type HealthThreshold } from '@/services/health';
|
||||
import { listPendingSuggestions, type AiSuggestionItem } from '@/services/ai-analysis';
|
||||
|
||||
export type VitalType = 'blood_pressure' | 'heart_rate' | 'blood_sugar' | 'weight';
|
||||
|
||||
@@ -6,14 +6,14 @@ import { useAuthStore } from '../../stores/auth';
|
||||
import { useUIStore } from '../../stores/ui';
|
||||
import { navigateToLogin } from '../../utils/navigate';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
import { useThrottledDidShow } from '@/hooks/useThrottledDidShow';
|
||||
// useThrottledDidShow removed — unused import
|
||||
import { api } from '@/services/request';
|
||||
import type { Article } from '@/services/article';
|
||||
import ProgressRing from '@/components/ui/ProgressRing';
|
||||
import Loading from '../../components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useHomeData, type ReminderItem } from './useHomeData';
|
||||
import { useHomeData } from './useHomeData';
|
||||
import './index.scss';
|
||||
|
||||
interface PublicBanner {
|
||||
@@ -27,9 +27,9 @@ interface PublicBanner {
|
||||
}
|
||||
|
||||
const FALLBACK_SLIDES = [
|
||||
{ id: 'slide-1', title: '专业血透中心', desc: '三甲级医护团队全程守护', image_url: '' },
|
||||
{ id: 'slide-2', title: '智慧健康管理', desc: 'AI 驱动个性化健康方案', image_url: '' },
|
||||
{ id: 'slide-3', title: '温馨就医环境', desc: '舒适安全的治疗体验', image_url: '' },
|
||||
{ id: 'slide-1', title: '专业血透中心', subtitle: '', desc: '三甲级医护团队全程守护', image_url: '' },
|
||||
{ id: 'slide-2', title: '智慧健康管理', subtitle: '', desc: 'AI 驱动个性化健康方案', image_url: '' },
|
||||
{ id: 'slide-3', title: '温馨就医环境', subtitle: '', desc: '舒适安全的治疗体验', image_url: '' },
|
||||
];
|
||||
|
||||
// ─── 访客首页 ───
|
||||
|
||||
@@ -83,7 +83,7 @@ export function useHomeData() {
|
||||
]);
|
||||
|
||||
if (suggestRes.status === 'fulfilled') {
|
||||
for (const s of suggestRes.value.data.slice(0, 1)) {
|
||||
for (const s of suggestRes.value.slice(0, 1)) {
|
||||
items.push({ id: s.id, text: buildSuggestionText(s), type: 'ai', tag: 'AI 建议' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ import { safeNavigateTo } from '@/utils/navigate';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import './index.scss';
|
||||
|
||||
declare const __wxConfig: Record<string, unknown> | undefined;
|
||||
|
||||
const IS_DEV = process.env.NODE_ENV !== 'production';
|
||||
const IS_SIMULATOR = typeof __wxConfig !== 'undefined' && (__wxConfig as any).envVersion === 'develop';
|
||||
const IS_SIMULATOR = typeof __wxConfig !== 'undefined' && (__wxConfig as Record<string, unknown>)?.envVersion === 'develop';
|
||||
|
||||
export default function Login() {
|
||||
const [username, setUsername] = useState('');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { useState, useRef } from 'react';
|
||||
import { View, Text, Input, ScrollView } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import {
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getDialysisRecord, reviewDialysisRecord,
|
||||
updateDialysisRecord, deleteDialysisRecord,
|
||||
type DialysisRecord,
|
||||
type UpdateDialysisRecordReq,
|
||||
} from '@/services/doctor/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
@@ -59,7 +60,8 @@ export default function DialysisDetail() {
|
||||
if (!record) return;
|
||||
setSubmitting(true);
|
||||
try {
|
||||
const updated = await updateDialysisRecord(id, { status: 'completed' }, record.version);
|
||||
const req = { status: 'completed' } as UpdateDialysisRecordReq;
|
||||
const updated = await updateDialysisRecord(id, req, record.version);
|
||||
setRecord(updated);
|
||||
Taro.showToast({ title: '已标记完成', icon: 'success' });
|
||||
} catch (err) {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useState } from 'react';
|
||||
import { View, Text, Input, Textarea, Picker } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { createDialysisPrescription } from '@/services/doctor/dialysis';
|
||||
import Loading from '@/components/Loading';
|
||||
import PageShell from '@/components/ui/PageShell';
|
||||
import ContentCard from '@/components/ui/ContentCard';
|
||||
import { useDoctorClass } from '@/hooks/useDoctorClass';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback, useRef } from 'react';
|
||||
import { useState, useCallback, useRef } from 'react';
|
||||
import { View, Text, ScrollView } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
@@ -33,7 +33,7 @@ export default function PatientAlerts() {
|
||||
const currentPatient = useAuthStore((s) => s.currentPatient);
|
||||
const [alerts, setAlerts] = useState<Alert[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [page, setPage] = useState(1);
|
||||
const [_page, setPage] = useState(1);
|
||||
const [status, setStatus] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(false);
|
||||
@@ -76,7 +76,7 @@ export default function PatientAlerts() {
|
||||
try {
|
||||
const tmplId = process.env.TARO_APP_WX_TEMPLATE_CRITICAL_ALERT || '';
|
||||
if (tmplId) {
|
||||
await Taro.requestSubscribeMessage({ tmplIds: [tmplId] });
|
||||
await (Taro.requestSubscribeMessage as (option: { tmplIds: string[] }) => Promise<unknown>)({ tmplIds: [tmplId] });
|
||||
}
|
||||
} catch {
|
||||
// 用户拒绝或已订阅,不阻塞页面
|
||||
|
||||
@@ -15,7 +15,7 @@ import ContentCard from '@/components/ui/ContentCard';
|
||||
import {
|
||||
BP_RANGE, WEIGHT_RANGE, SUGAR_RANGE, VOLUME_RANGE,
|
||||
checkAbnormal, formatDate, FIELD_LABELS,
|
||||
type SectionKey, type AbnormalResult,
|
||||
type SectionKey,
|
||||
} from './constants';
|
||||
import './index.scss';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, ScrollView } from '@tarojs/components';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import * as pointsApi from '@/services/points';
|
||||
import Loading from '@/components/Loading';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { View, Text, Input, Picker } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { createPatient, updatePatient, Patient } from '../../../services/patient';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, Textarea } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text, Input, Picker } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { usePageData } from '@/hooks/usePageData';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { View, Text } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { safeNavigateTo } from '@/utils/navigate';
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface LoginResp {
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
expires_in: number;
|
||||
user: { id: string; username: string; display_name?: string; phone?: string; avatar_url?: string };
|
||||
user: { id: string; username: string; display_name?: string; phone?: string; avatar_url?: string; tenant_id?: string };
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export interface SyncResult {
|
||||
export class DataSyncScheduler {
|
||||
private config: Required<SyncSchedulerConfig>;
|
||||
private timerId: ReturnType<typeof setInterval> | null = null;
|
||||
private isSyncing = false;
|
||||
|
||||
constructor(config?: SyncSchedulerConfig) {
|
||||
this.config = { ...DEFAULT_CONFIG, ...config };
|
||||
@@ -40,14 +41,21 @@ export class DataSyncScheduler {
|
||||
|
||||
/** 执行同步并记录时间戳 */
|
||||
async recordSync(syncFn: () => Promise<SyncResult>): Promise<SyncResult> {
|
||||
if (this.isSyncing) {
|
||||
return { success: false, uploadedCount: 0, error: '同步进行中' };
|
||||
}
|
||||
this.isSyncing = true;
|
||||
try {
|
||||
const result = await syncFn();
|
||||
if (result.success) {
|
||||
this.saveRecord({ lastSyncAt: Date.now() });
|
||||
}
|
||||
return result;
|
||||
} catch (e: any) {
|
||||
return { success: false, uploadedCount: 0, error: e.message || '同步失败' };
|
||||
} catch (e: unknown) {
|
||||
const message = e instanceof Error ? e.message : '同步失败';
|
||||
return { success: false, uploadedCount: 0, error: message };
|
||||
} finally {
|
||||
this.isSyncing = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +104,6 @@ export class DataSyncScheduler {
|
||||
Taro.setStorageSync(this.config.storageKey, JSON.stringify(record));
|
||||
} catch (err) {
|
||||
console.warn('[ble-sync] Storage 操作失败:', err);
|
||||
// Storage 写入失败不影响主流程
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,19 +19,12 @@ const RACP_CHARACTERISTIC = '00002A52-0000-1000-8000-00805F9B34FB';
|
||||
|
||||
// RACP 操作码
|
||||
const RACP_OPCODE_REPORT_STORED_RECORDS = 0x01;
|
||||
const RACP_OPCODE_DELETE_STORED_RECORDS = 0x02;
|
||||
const RACP_OPCODE_ABORT_OPERATION = 0x03;
|
||||
const RACP_OPCODE_REPORT_NUMBER_OF_RECORDS = 0x04;
|
||||
const RACP_OPCODE_NUMBER_OF_STORED_RECORDS_RESPONSE = 0x05;
|
||||
const RACP_OPCODE_RESPONSE_CODE = 0x06;
|
||||
|
||||
// RACP 操作符
|
||||
const RACP_OPERATOR_ALL = 0x01;
|
||||
const RACP_OPERATOR_LESS_THAN = 0x04;
|
||||
const RACP_OPERATOR_GREATER_THAN = 0x05;
|
||||
|
||||
// RACP 过滤器类型
|
||||
const RACP_FILTER_TYPE_TIME = 0x01;
|
||||
|
||||
/** 解析心率测量值(Heart Rate Measurement 格式) */
|
||||
function parseHeartRate(data: ArrayBuffer): number | null {
|
||||
@@ -118,14 +111,11 @@ export const XiaomiBandAdapter: DeviceAdapter = {
|
||||
const opcode = view.getUint8(0);
|
||||
|
||||
if (opcode === RACP_OPCODE_NUMBER_OF_STORED_RECORDS_RESPONSE) {
|
||||
const count = view.getUint16(2, true);
|
||||
// 不返回 reading,仅用于日志/调试
|
||||
return [];
|
||||
}
|
||||
|
||||
if (opcode === RACP_OPCODE_RESPONSE_CODE) {
|
||||
const reqOpcode = view.getUint8(1);
|
||||
const status = view.getUint8(2);
|
||||
// status: 0x01=成功, 0x02=不支持的操作码, 等
|
||||
// 不返回 reading,仅用于日志
|
||||
return [];
|
||||
@@ -162,7 +152,7 @@ export function buildRACPReportAll(): ArrayBuffer {
|
||||
export function buildRACPReportCount(): ArrayBuffer {
|
||||
const buffer = new ArrayBuffer(2);
|
||||
const view = new DataView(buffer);
|
||||
view.setUint8(0, RACP_OPCODE_REPORT_NUMBER_OF_STORED_RECORDS);
|
||||
view.setUint8(0, RACP_OPCODE_REPORT_NUMBER_OF_RECORDS);
|
||||
view.setUint8(1, RACP_OPERATOR_ALL);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ interface BatchReadingRequest {
|
||||
device_model?: string;
|
||||
readings: {
|
||||
device_type: string;
|
||||
values: Record<string, number>;
|
||||
values: Record<string, number | string>;
|
||||
measured_at: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
@@ -40,10 +40,13 @@ export async function listActionItems(params?: {
|
||||
assigned_to_me?: boolean;
|
||||
patient_id?: string;
|
||||
}) {
|
||||
return api.get<PaginatedData>(
|
||||
'/health/action-inbox',
|
||||
params as Record<string, string | number | boolean | undefined>,
|
||||
);
|
||||
const query: Record<string, string | number | undefined> = {};
|
||||
if (params) {
|
||||
for (const [k, v] of Object.entries(params)) {
|
||||
if (v !== undefined) query[k] = typeof v === 'boolean' ? String(v) : v;
|
||||
}
|
||||
}
|
||||
return api.get<PaginatedData>('/health/action-inbox', query);
|
||||
}
|
||||
|
||||
export async function getActionThread(sourceRef: string) {
|
||||
@@ -55,7 +58,7 @@ export async function getActionThread(sourceRef: string) {
|
||||
export async function getWorkbenchStats(assignedToMe?: boolean) {
|
||||
return api.get<WorkbenchStats>(
|
||||
'/health/action-inbox/stats',
|
||||
assignedToMe !== undefined ? { assigned_to_me: assignedToMe } : undefined,
|
||||
assignedToMe !== undefined ? { assigned_to_me: String(assignedToMe) } as Record<string, string | number | undefined> : undefined,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ export interface CreateDialysisRecordReq {
|
||||
complication_notes?: string;
|
||||
}
|
||||
|
||||
export type UpdateDialysisRecordReq = Omit<CreateDialysisRecordReq, 'patient_id'>;
|
||||
export type UpdateDialysisRecordReq = Omit<CreateDialysisRecordReq, 'patient_id'> & {
|
||||
status?: string;
|
||||
};
|
||||
|
||||
export interface CreateDialysisPrescriptionReq {
|
||||
patient_id: string;
|
||||
@@ -52,7 +54,9 @@ export interface CreateDialysisPrescriptionReq {
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export type UpdateDialysisPrescriptionReq = Omit<CreateDialysisPrescriptionReq, 'patient_id'>;
|
||||
export type UpdateDialysisPrescriptionReq = Omit<CreateDialysisPrescriptionReq, 'patient_id'> & {
|
||||
status?: string;
|
||||
};
|
||||
|
||||
export interface DialysisStatistics {
|
||||
total_records: number;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { api } from './request';
|
||||
|
||||
export const notificationService = {
|
||||
list: (params?: { page?: number; page_size?: number }) =>
|
||||
api.get('/messages', params as Record<string, string | number | undefined>),
|
||||
list: <T = unknown>(params?: { page?: number; page_size?: number }) =>
|
||||
api.get<T>('/messages', params as Record<string, string | number | undefined>),
|
||||
markRead: (id: string) =>
|
||||
api.put(`/messages/${id}/read`),
|
||||
markAllRead: () =>
|
||||
|
||||
@@ -18,13 +18,6 @@ let cachedRolesObj: string[] = [];
|
||||
let cachedPatientJson = '';
|
||||
let cachedPatientObj: authApi.PatientInfo | null = null;
|
||||
|
||||
interface BindPhoneResp {
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
expires_in?: number;
|
||||
user: { id: string; username: string; display_name?: string; phone?: string; tenant_id?: string };
|
||||
}
|
||||
|
||||
interface AuthState {
|
||||
user: { id: string; username: string; display_name?: string; phone?: string; tenant_id?: string } | null;
|
||||
roles: string[];
|
||||
@@ -221,7 +214,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
|
||||
clearLoggingOut();
|
||||
get().loadPatients();
|
||||
return true;
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
secureRemove('wechat_openid');
|
||||
set({ loading: false });
|
||||
throw err;
|
||||
|
||||
34
apps/miniprogram/src/utils/crypto-polyfill.ts
Normal file
34
apps/miniprogram/src/utils/crypto-polyfill.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 微信小程序 crypto.getRandomValues polyfill
|
||||
* 使用 wx.getRandomValuesSync,不可用时回退到 Math.random
|
||||
* 必须在 app.tsx 首行导入
|
||||
*/
|
||||
|
||||
declare const wx: {
|
||||
getRandomValuesSync?: (params: { length: number }) => ArrayBuffer;
|
||||
} | undefined;
|
||||
|
||||
if (typeof globalThis.crypto === 'undefined' || !globalThis.crypto.getRandomValues) {
|
||||
const wxCrypto = {
|
||||
getRandomValues<T extends ArrayBufferView>(arr: T): T {
|
||||
if (typeof wx !== 'undefined' && typeof wx.getRandomValuesSync === 'function') {
|
||||
const buf = wx.getRandomValuesSync({ length: arr.byteLength });
|
||||
const view = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
const src = new Uint8Array(buf as ArrayBuffer);
|
||||
for (let i = 0; i < view.length; i++) {
|
||||
view[i] = src[i] ?? (Math.random() * 256) | 0;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
// fallback: Math.random
|
||||
const view = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
||||
for (let i = 0; i < view.length; i++) {
|
||||
view[i] = (Math.random() * 256) | 0;
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
};
|
||||
|
||||
// @ts-expect-error — polyfill
|
||||
globalThis.crypto = wxCrypto;
|
||||
}
|
||||
44
apps/miniprogram/src/utils/logger.ts
Normal file
44
apps/miniprogram/src/utils/logger.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
type LogLevel = 'info' | 'warn' | 'error';
|
||||
|
||||
const IS_DEV = process.env.NODE_ENV === 'development';
|
||||
|
||||
function formatMessage(level: LogLevel, module: string, message: string): string {
|
||||
return `[${level.toUpperCase()}][${module}] ${message}`;
|
||||
}
|
||||
|
||||
function safeDetail(detail: unknown): string {
|
||||
if (IS_DEV) {
|
||||
return typeof detail === 'object' ? JSON.stringify(detail) : String(detail);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export const logger = {
|
||||
info(module: string, message: string, detail?: unknown): void {
|
||||
if (IS_DEV) {
|
||||
console.log(formatMessage('info', module, message), detail ?? '');
|
||||
}
|
||||
},
|
||||
|
||||
warn(module: string, message: string, detail?: unknown): void {
|
||||
console.warn(formatMessage('warn', module, message), safeDetail(detail));
|
||||
},
|
||||
|
||||
error(module: string, message: string, detail?: unknown): void {
|
||||
console.error(formatMessage('error', module, message), safeDetail(detail));
|
||||
},
|
||||
};
|
||||
|
||||
export function safeWarn(module: string, message: string): void {
|
||||
if (IS_DEV) {
|
||||
console.warn(`[${module}] ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function safeError(module: string, message: string, detail?: unknown): void {
|
||||
if (IS_DEV) {
|
||||
console.error(`[${module}] ${message}`, detail ?? '');
|
||||
} else {
|
||||
console.error(`[${module}] ${message}`);
|
||||
}
|
||||
}
|
||||
167
apps/miniprogram/src/utils/secure-storage-aes.ts
Normal file
167
apps/miniprogram/src/utils/secure-storage-aes.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* AES-256-GCM 加密存储 — 替代 XOR 加密
|
||||
* 依赖 @noble/ciphers + crypto-polyfill(wx.getRandomValuesSync)
|
||||
*/
|
||||
import Taro from '@tarojs/taro';
|
||||
import { gcm } from '@noble/ciphers/aes.js';
|
||||
|
||||
const STORAGE_PREFIX = '_es_';
|
||||
const AES_MARKER = 'aes:';
|
||||
const NONCE_LENGTH = 12; // GCM 标准 nonce 长度
|
||||
|
||||
declare const wx: {
|
||||
getRandomValuesSync?: (params: { length: number }) => ArrayBuffer;
|
||||
} | undefined;
|
||||
|
||||
function getEncryptionKey(): Uint8Array {
|
||||
const hex = process.env.TARO_APP_ENCRYPTION_KEY || '';
|
||||
if (hex && /^[0-9a-fA-F]{64}$/.test(hex)) {
|
||||
return new Uint8Array(hex.match(/.{2}/g)!.map((b) => parseInt(b, 16)));
|
||||
}
|
||||
// derive 32 bytes from passphrase
|
||||
const passphrase = process.env.TARO_APP_ENCRYPTION_KEY || 'hms-default-key';
|
||||
const bytes = new Uint8Array(32);
|
||||
for (let i = 0; i < 32; i++) {
|
||||
bytes[i] = passphrase.charCodeAt(i % passphrase.length) ^ ((i * 37) & 0xff);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function generateNonce(): Uint8Array {
|
||||
const nonce = new Uint8Array(NONCE_LENGTH);
|
||||
if (typeof globalThis.crypto?.getRandomValues === 'function') {
|
||||
globalThis.crypto.getRandomValues(nonce);
|
||||
} else if (typeof wx !== 'undefined' && typeof wx.getRandomValuesSync === 'function') {
|
||||
const buf = wx.getRandomValuesSync({ length: NONCE_LENGTH });
|
||||
const src = new Uint8Array(buf as ArrayBuffer);
|
||||
nonce.set(src);
|
||||
} else {
|
||||
for (let i = 0; i < NONCE_LENGTH; i++) {
|
||||
nonce[i] = (Math.random() * 256) | 0;
|
||||
}
|
||||
}
|
||||
return nonce;
|
||||
}
|
||||
|
||||
function aesEncrypt(plaintext: string): string {
|
||||
const key = getEncryptionKey();
|
||||
const nonce = generateNonce();
|
||||
const cipher = gcm(key, nonce);
|
||||
const data = new TextEncoder().encode(plaintext);
|
||||
const ciphertext = cipher.encrypt(data);
|
||||
// nonce(12) + ciphertext 打包
|
||||
const combined = new Uint8Array(nonce.length + ciphertext.length);
|
||||
combined.set(nonce, 0);
|
||||
combined.set(ciphertext, nonce.length);
|
||||
return AES_MARKER + Taro.arrayBufferToBase64(combined.buffer as ArrayBuffer);
|
||||
}
|
||||
|
||||
function aesDecrypt(encoded: string): string | null {
|
||||
try {
|
||||
const b64 = encoded.slice(AES_MARKER.length);
|
||||
const buf = Taro.base64ToArrayBuffer(b64);
|
||||
const combined = new Uint8Array(buf);
|
||||
if (combined.length < NONCE_LENGTH) return null;
|
||||
|
||||
const nonce = combined.slice(0, NONCE_LENGTH);
|
||||
const ciphertext = combined.slice(NONCE_LENGTH);
|
||||
const key = getEncryptionKey();
|
||||
const cipher = gcm(key, nonce);
|
||||
const plaintext = cipher.decrypt(ciphertext);
|
||||
return new TextDecoder().decode(plaintext);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// XOR decryption for reading legacy data
|
||||
function xorDecrypt(data: string, key: string): string {
|
||||
let result = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
result += String.fromCharCode(data.charCodeAt(i) ^ key.charCodeAt(i % key.length));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function fromBase64(b64: string): string {
|
||||
try {
|
||||
const buffer = Taro.base64ToArrayBuffer(b64);
|
||||
return new TextDecoder().decode(new Uint8Array(buffer));
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
const LEGACY_KEY = process.env.TARO_APP_ENCRYPTION_KEY || 'hms-default-key';
|
||||
|
||||
export function secureSet(key: string, value: string): void {
|
||||
if (!value) {
|
||||
Taro.removeStorageSync(STORAGE_PREFIX + key);
|
||||
return;
|
||||
}
|
||||
const encrypted = aesEncrypt(value);
|
||||
Taro.setStorageSync(STORAGE_PREFIX + key, encrypted);
|
||||
}
|
||||
|
||||
export function secureGet(key: string): string {
|
||||
const prefixedKey = STORAGE_PREFIX + key;
|
||||
const raw = Taro.getStorageSync(prefixedKey);
|
||||
if (!raw || typeof raw !== 'string') {
|
||||
// fallback: 明文键(兼容 MCP 注入)
|
||||
const plain = Taro.getStorageSync(key);
|
||||
return plain && typeof plain === 'string' ? plain : '';
|
||||
}
|
||||
|
||||
// AES 格式
|
||||
if (raw.startsWith(AES_MARKER)) {
|
||||
const decrypted = aesDecrypt(raw);
|
||||
if (decrypted !== null) return decrypted;
|
||||
}
|
||||
|
||||
// XOR 格式(legacy)
|
||||
try {
|
||||
const decoded = fromBase64(raw);
|
||||
if (decoded) {
|
||||
return xorDecrypt(decoded, LEGACY_KEY);
|
||||
}
|
||||
} catch {
|
||||
// fallthrough
|
||||
}
|
||||
|
||||
// 明文 fallback
|
||||
return raw;
|
||||
}
|
||||
|
||||
export function secureRemove(key: string): void {
|
||||
Taro.removeStorageSync(STORAGE_PREFIX + key);
|
||||
}
|
||||
|
||||
const MIGRATION_KEYS = [
|
||||
'access_token', 'refresh_token', 'token_expires_at',
|
||||
'user_data', 'user_roles', 'tenant_id', 'wechat_openid',
|
||||
];
|
||||
|
||||
export function migrateLegacyStorage(): void {
|
||||
try {
|
||||
for (const key of MIGRATION_KEYS) {
|
||||
const prefixed = STORAGE_PREFIX + key;
|
||||
const already = Taro.getStorageSync(prefixed);
|
||||
if (already) {
|
||||
// re-encrypt with AES if not already
|
||||
if (typeof already === 'string' && !already.startsWith(AES_MARKER)) {
|
||||
const value = secureGet(key);
|
||||
if (value) secureSet(key, value);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const legacy = Taro.getStorageSync(key);
|
||||
if (!legacy || typeof legacy !== 'string') continue;
|
||||
|
||||
secureSet(key, legacy);
|
||||
Taro.removeStorageSync(key);
|
||||
}
|
||||
} catch {
|
||||
// migration best-effort
|
||||
}
|
||||
}
|
||||
@@ -1,97 +1,5 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
const ENCRYPTION_KEY = process.env.TARO_APP_ENCRYPTION_KEY || 'hms-default-key';
|
||||
|
||||
function xorEncrypt(data: string, key: string): string {
|
||||
let result = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
result += String.fromCharCode(data.charCodeAt(i) ^ key.charCodeAt(i % key.length));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function toBase64(str: string): string {
|
||||
try {
|
||||
const encoder = new TextEncoder();
|
||||
const uint8 = encoder.encode(str);
|
||||
return Taro.arrayBufferToBase64(uint8.buffer as ArrayBuffer);
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function fromBase64(b64: string): string {
|
||||
try {
|
||||
const buffer = Taro.base64ToArrayBuffer(b64);
|
||||
const decoder = new TextDecoder();
|
||||
return decoder.decode(new Uint8Array(buffer));
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
const STORAGE_PREFIX = '_es_';
|
||||
|
||||
export function secureSet(key: string, value: string): void {
|
||||
if (!value) {
|
||||
Taro.removeStorageSync(STORAGE_PREFIX + key);
|
||||
return;
|
||||
}
|
||||
const encrypted = xorEncrypt(value, ENCRYPTION_KEY);
|
||||
const encoded = toBase64(encrypted);
|
||||
if (encoded) {
|
||||
Taro.setStorageSync(STORAGE_PREFIX + key, encoded);
|
||||
} else {
|
||||
Taro.setStorageSync(STORAGE_PREFIX + key, value);
|
||||
}
|
||||
}
|
||||
|
||||
export function secureGet(key: string): string {
|
||||
const prefixedKey = STORAGE_PREFIX + key;
|
||||
const raw = Taro.getStorageSync(prefixedKey);
|
||||
if (!raw || typeof raw !== 'string') {
|
||||
// fallback: 尝试读取明文键(兼容 MCP 注入等场景)
|
||||
const plain = Taro.getStorageSync(key);
|
||||
return (plain && typeof plain === 'string') ? plain : '';
|
||||
}
|
||||
|
||||
// 始终尝试 base64 解码 + XOR 解密(secureSet 的写入格式)
|
||||
try {
|
||||
const decoded = fromBase64(raw);
|
||||
if (decoded) {
|
||||
return xorEncrypt(decoded, ENCRYPTION_KEY);
|
||||
}
|
||||
} catch {
|
||||
// fallthrough — 可能是未加密的旧数据
|
||||
}
|
||||
|
||||
// fallback: 兼容未加密的旧数据(明文 JSON/JWT 或其他值)
|
||||
return raw;
|
||||
}
|
||||
|
||||
export function secureRemove(key: string): void {
|
||||
Taro.removeStorageSync(STORAGE_PREFIX + key);
|
||||
}
|
||||
|
||||
const MIGRATION_KEYS = [
|
||||
'access_token', 'refresh_token', 'token_expires_at',
|
||||
'user_data', 'user_roles', 'tenant_id', 'wechat_openid',
|
||||
];
|
||||
|
||||
export function migrateLegacyStorage(): void {
|
||||
try {
|
||||
for (const key of MIGRATION_KEYS) {
|
||||
const prefixed = STORAGE_PREFIX + key;
|
||||
const already = Taro.getStorageSync(prefixed);
|
||||
if (already) continue;
|
||||
|
||||
const legacy = Taro.getStorageSync(key);
|
||||
if (!legacy || typeof legacy !== 'string') continue;
|
||||
|
||||
secureSet(key, legacy);
|
||||
Taro.removeStorageSync(key);
|
||||
}
|
||||
} catch {
|
||||
// migration best-effort
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 安全存储 — AES-256-GCM 加密
|
||||
* 重导出 secure-storage-aes,保留旧导入路径兼容
|
||||
*/
|
||||
export { secureSet, secureGet, secureRemove, migrateLegacyStorage } from './secure-storage-aes';
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"target": "ES2018",
|
||||
"module": "commonjs",
|
||||
"lib": ["ES2018"],
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": true,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": false,
|
||||
"noImplicitAny": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"outDir": "lib",
|
||||
"noUnusedLocals": true,
|
||||
@@ -14,10 +15,12 @@
|
||||
"strictNullChecks": true,
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"jsx": "react",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"types": ["node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user