提交
This commit is contained in:
1 parent
683f14828f
commit
fdf7d391a6
40 files changed
+6242
-19470
No files matched your search
@@ -54,6 +54,7 @@ backend/.ocr-venv/
|
||||
*.key
|
||||
*.p12
|
||||
secrets/
|
||||
生产机器账号密码
|
||||
|
||||
# 日志与临时文件
|
||||
*.log
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
49544
|
||||
19962
|
||||
+10
-12
@@ -209,19 +209,17 @@ def refresh_token(body: dict, db: Session = Depends(get_db)):
|
||||
|
||||
@router.post("/web/auth/logout", response_model=dict)
|
||||
def logout(request: Request):
|
||||
"""登出:吊销 Redis 会话(若已配置 REDIS_HOST)。"""
|
||||
"""登出:吊销 Redis 会话(若已配置 REDIS_HOST)。无 Token 或已失效时仍返回成功(幂等)。"""
|
||||
authorization = request.headers.get("Authorization", "")
|
||||
if not authorization.startswith("Bearer "):
|
||||
return error_response(401, "未授权")
|
||||
|
||||
token = authorization.replace("Bearer ", "")
|
||||
try:
|
||||
payload = decode_token(token)
|
||||
session_id = payload.get("sid")
|
||||
if session_id:
|
||||
revoke_session(session_id=session_id)
|
||||
except HTTPException:
|
||||
return error_response(401, "Token无效或已过期")
|
||||
if authorization.startswith("Bearer "):
|
||||
token = authorization.replace("Bearer ", "")
|
||||
try:
|
||||
payload = decode_token(token)
|
||||
session_id = payload.get("sid")
|
||||
if session_id:
|
||||
revoke_session(session_id=session_id)
|
||||
except HTTPException:
|
||||
pass
|
||||
|
||||
return success_response({"message": "登出成功"})
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 生产一键发版脚本设计
|
||||
|
||||
日期:2026-08-08
|
||||
脚本:`生产环境部署/deploy-release.sh`
|
||||
|
||||
## 目标
|
||||
|
||||
在 macOS 本机一键完成生产环境前后端更新:先前端后后端,发版前备份,保留远程 `web/dist/src`。
|
||||
|
||||
## 流程
|
||||
|
||||
1. 解析仓库根目录 `生产机器账号密码`(IP + root 密码)
|
||||
2. 本地 `web-admin` 执行 `pnpm build`(可用 `--skip-build` 跳过)
|
||||
3. 备份远程 `/iflytek/shanxia2.0/web` → `bak/web-YYYYMMDD-HHMMSS`
|
||||
4. `rsync --delete --exclude 'src/'` 同步到 `web/dist`
|
||||
5. 备份远程 `backend` → `bak/backend-YYYYMMDD-HHMMSS`
|
||||
6. 删除远程 `backend/app`,同步本地 `backend/app`
|
||||
7. `PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart`
|
||||
8. `curl http://127.0.0.1:9111/health`
|
||||
|
||||
## 约束
|
||||
|
||||
- 凭据不写进脚本;`生产机器账号密码` 已加入 `.gitignore`
|
||||
- 仅替换 `app/`,不覆盖远程 `venv` / `.env.production` / `logs` / `uploads`
|
||||
- 依赖本机:`ssh`、`rsync`、`sshpass`、`pnpm`
|
||||
+42
-42
@@ -20,8 +20,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"package.json": {
|
||||
"mtime": 1785657009.9324844,
|
||||
"ast_hash": "f84943886ed35640c67e7d9d11ad9857",
|
||||
"mtime": 1786194935.77331,
|
||||
"ast_hash": "c9645afa983ec0773f38202f0417fd4d",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"public/tinymce/icons/default/icons.js": {
|
||||
@@ -900,8 +900,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/api/auth.ts": {
|
||||
"mtime": 1783859000.0,
|
||||
"ast_hash": "e613f5fd485fb55d09f96c609722655e",
|
||||
"mtime": 1786197470.7104685,
|
||||
"ast_hash": "00f91a528856880868cb7298323f5c4b",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/api/bx/index.ts": {
|
||||
@@ -1500,8 +1500,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/business/product-form-dialog/index.vue": {
|
||||
"mtime": 1786095022.967315,
|
||||
"ast_hash": "2e3740ddea4872e7011ddced83ac9aba",
|
||||
"mtime": 1786196563.5496323,
|
||||
"ast_hash": "1a9f47895063a29d94d0083c220db835",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/business/product-selector/index.vue": {
|
||||
@@ -1685,8 +1685,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/core/base/art-svg-icon/index.vue": {
|
||||
"mtime": 1782858534.0,
|
||||
"ast_hash": "2ff45e19c9d506f4120a786d4f38efb1",
|
||||
"mtime": 1786194949.5663605,
|
||||
"ast_hash": "272235c611dc0d356237d216cf7fd74b",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/core/base/list-index-column/index.vue": {
|
||||
@@ -1935,8 +1935,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/core/layouts/art-settings-panel/composables/useSettingsConfig.ts": {
|
||||
"mtime": 1783256189.0,
|
||||
"ast_hash": "ee54130b67d8f6b68f43b41ca8dd9537",
|
||||
"mtime": 1786194954.6344905,
|
||||
"ast_hash": "4912965c8644b354f58a653e990ed6d0",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/core/layouts/art-settings-panel/composables/useSettingsHandlers.ts": {
|
||||
@@ -2025,8 +2025,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/core/list-toolbar-date-shortcuts/index.vue": {
|
||||
"mtime": 1786181835.4696286,
|
||||
"ast_hash": "26c69c9f5ab284a3f8cd73f824f0d22d",
|
||||
"mtime": 1786197038.1514368,
|
||||
"ast_hash": "746febcf60690e8e3178832b65bbe8f7",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/components/core/media/art-cutter-img/index.vue": {
|
||||
@@ -2365,8 +2365,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/main.ts": {
|
||||
"mtime": 1785690210.1346507,
|
||||
"ast_hash": "3316a9eb4b350993c9ca3f1ed2b71ed5",
|
||||
"mtime": 1786194951.3744397,
|
||||
"ast_hash": "8307c8801d4f5f907496f2b876a71a10",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/mock/json/chinaMap.json": {
|
||||
@@ -2400,8 +2400,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/router/core/MenuProcessor.ts": {
|
||||
"mtime": 1786161771.6129146,
|
||||
"ast_hash": "68bcc06072dbf23a066ac4c296160925",
|
||||
"mtime": 1786195456.961378,
|
||||
"ast_hash": "06ad320f46422b2664f9ddf0c01e9dd2",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/router/core/RoutePermissionValidator.ts": {
|
||||
@@ -2465,8 +2465,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/router/modules/sqxp.ts": {
|
||||
"mtime": 1786166018.5711956,
|
||||
"ast_hash": "19c098bc6627247d0d22eb3f2277f194",
|
||||
"mtime": 1786195447.3096144,
|
||||
"ast_hash": "e97b601c3d1da7ff31f42613e5e05103",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/router/routes/asyncRoutes.ts": {
|
||||
@@ -2525,8 +2525,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/store/modules/user.ts": {
|
||||
"mtime": 1786164213.99407,
|
||||
"ast_hash": "b4994b9206c5460048d403b6003e45ef",
|
||||
"mtime": 1786197472.6410632,
|
||||
"ast_hash": "f5743d88eca390d4eb987aaece9858fd",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/store/modules/worktab.ts": {
|
||||
@@ -2760,8 +2760,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/utils/http/index.ts": {
|
||||
"mtime": 1782858530.0,
|
||||
"ast_hash": "f772026ad1b690269b612b38a8dfc2d8",
|
||||
"mtime": 1786197473.6926188,
|
||||
"ast_hash": "2ba44539229220f84e5ce589e60c8de0",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/utils/http/portal-auth.ts": {
|
||||
@@ -3055,8 +3055,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/utils/ui/iconify-loader.ts": {
|
||||
"mtime": 1782858528.0,
|
||||
"ast_hash": "6742ca3f093bc765a1e8b4523daa96d6",
|
||||
"mtime": 1786194970.003212,
|
||||
"ast_hash": "b3ebab6f113784b8c5a9b585573f7866",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/utils/ui/index.ts": {
|
||||
@@ -3250,8 +3250,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/crm/contract/components/ContractDetailDialog.vue": {
|
||||
"mtime": 1786188825.3967483,
|
||||
"ast_hash": "75282c90bb8e615a09df89beebf63b15",
|
||||
"mtime": 1786196745.0045779,
|
||||
"ast_hash": "ca3ce20832c2c30984038b9447d7dde9",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/crm/contract/components/ContractFormDialog.vue": {
|
||||
@@ -3265,8 +3265,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/crm/contract/components/InvalidDialog.vue": {
|
||||
"mtime": 1783167841.0,
|
||||
"ast_hash": "b89c8be12419753a8467606ee771543e",
|
||||
"mtime": 1786196151.567379,
|
||||
"ast_hash": "f9cef0e753fa01ebc59cea7a47ac131e",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/crm/contract/components/RenewDialog.vue": {
|
||||
@@ -3570,18 +3570,18 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/db/inventory/index.vue": {
|
||||
"mtime": 1786186548.239029,
|
||||
"ast_hash": "1b3249c7ddfda59e59470640ff079869",
|
||||
"mtime": 1786197034.6730628,
|
||||
"ast_hash": "8f43e8f844a0ad71aea848271e282c07",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/db/plans/index.vue": {
|
||||
"mtime": 1786180978.8021648,
|
||||
"ast_hash": "3398d4465cc663dad313d3d7e789c226",
|
||||
"mtime": 1786197034.6860974,
|
||||
"ast_hash": "708627416dd8db8deb20afb37f49e681",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/db/weighing/index.vue": {
|
||||
"mtime": 1786186548.2393966,
|
||||
"ast_hash": "b3518d3c8836ba9f70504677abfe720b",
|
||||
"mtime": 1786197034.6689532,
|
||||
"ast_hash": "3443fb83b0ded1c711fea82793e76ad8",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/demo/category/index.vue": {
|
||||
@@ -3635,8 +3635,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/pl/_shared/IoOrderListPage.vue": {
|
||||
"mtime": 1786180978.7263196,
|
||||
"ast_hash": "1f7a434f5f01bbd8ac8a71b8465632cc",
|
||||
"mtime": 1786197035.291659,
|
||||
"ast_hash": "d6ba66f36fa4e2fec738d8233c6f3814",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/pl/carrier/index.vue": {
|
||||
@@ -3725,13 +3725,13 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/pl/plan-archive/index.vue": {
|
||||
"mtime": 1786180978.724036,
|
||||
"ast_hash": "6a6d95b3b02297d54ec71269ee204e4a",
|
||||
"mtime": 1786197035.7200282,
|
||||
"ast_hash": "e753264e0e5f4cd0d2ac7ad4b306afb9",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/pl/plan-cert/index.vue": {
|
||||
"mtime": 1786180978.7093124,
|
||||
"ast_hash": "69829b160d1890dce3bd8dfef5d492f8",
|
||||
"mtime": 1786197037.217237,
|
||||
"ast_hash": "8fef9e3eda810d83d6d37d086398e437",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/pl/plan/arrange.vue": {
|
||||
@@ -3750,8 +3750,8 @@
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/pl/plan/index.vue": {
|
||||
"mtime": 1786180978.7139883,
|
||||
"ast_hash": "06d7f9efec9c69889b5f9dd6d8effa67",
|
||||
"mtime": 1786197036.7124588,
|
||||
"ast_hash": "b21a0b880d17f4d39606e2e10e5568b0",
|
||||
"semantic_hash": ""
|
||||
},
|
||||
"src/views/pl/self-vehicle/index.vue": {
|
||||
|
||||
@@ -162,9 +162,9 @@
|
||||
"160": "zh_CN.js",
|
||||
"161": "Community 161",
|
||||
"162": "Community 162",
|
||||
"163": "pl-batch-print.ts",
|
||||
"163": "saveNodes",
|
||||
"164": "Community 164",
|
||||
"165": "colors.ts",
|
||||
"165": "handleDisburse",
|
||||
"166": "Community 166",
|
||||
"167": "Community 167",
|
||||
"168": "loadDefaultCustomerOptions",
|
||||
@@ -185,16 +185,22 @@
|
||||
"183": "index.vue",
|
||||
"184": "v2.4.2.1 - 2025-06-16",
|
||||
"185": "zh_CN.js",
|
||||
"186": "fetchData",
|
||||
"186": "highlight.ts",
|
||||
"187": "Community 187",
|
||||
"188": "Community 188",
|
||||
"189": "Community 189",
|
||||
"190": "index.vue",
|
||||
"191": "index.vue",
|
||||
"191": "canDeleteByCreator",
|
||||
"192": "loadUserOptions",
|
||||
"193": "loadUserOptions",
|
||||
"194": "detail.vue",
|
||||
"195": "Community 195",
|
||||
"196": "Community 196",
|
||||
"197": "handleSearch",
|
||||
"198": "loadUserOptions",
|
||||
"199": "v2.4.2.3 - 2025-06-18",
|
||||
"200": "index.js",
|
||||
"201": "loading.ts",
|
||||
"202": "Community 202",
|
||||
"207": "Community 207",
|
||||
"208": "Community 208",
|
||||
@@ -504,7 +510,6 @@
|
||||
"1224": "emojis.js",
|
||||
"1225": "emojis.min.js",
|
||||
"1226": "index.js",
|
||||
"1227": "index.js",
|
||||
"1228": "ar.js",
|
||||
"1229": "bg_BG.js",
|
||||
"1230": "ca.js",
|
||||
@@ -594,7 +599,6 @@
|
||||
"1318": "content.js",
|
||||
"1319": "skin.js",
|
||||
"1320": "skin.shadowdom.js",
|
||||
"1322": "iconify-loader.ts",
|
||||
"1323": "index.vue",
|
||||
"1324": "index.vue",
|
||||
"1325": "index.vue",
|
||||
|
||||
@@ -162,9 +162,9 @@
|
||||
"160": "zh_CN.js",
|
||||
"161": "Community 161",
|
||||
"162": "Community 162",
|
||||
"163": "pl-batch-print.ts",
|
||||
"163": "saveNodes",
|
||||
"164": "Community 164",
|
||||
"165": "colors.ts",
|
||||
"165": "handleDisburse",
|
||||
"166": "Community 166",
|
||||
"167": "Community 167",
|
||||
"168": "loadDefaultCustomerOptions",
|
||||
@@ -185,12 +185,24 @@
|
||||
"183": "index.vue",
|
||||
"184": "v2.4.2.1 - 2025-06-16",
|
||||
"185": "zh_CN.js",
|
||||
"186": "highlight.ts",
|
||||
"187": "Community 187",
|
||||
"188": "Community 188",
|
||||
"189": "Community 189",
|
||||
"190": "index.vue",
|
||||
"191": "canDeleteByCreator",
|
||||
"192": "loadUserOptions",
|
||||
"193": "loadUserOptions",
|
||||
"194": "detail.vue",
|
||||
"195": "Community 195",
|
||||
"196": "Community 196",
|
||||
"197": "handleSearch",
|
||||
"198": "loadUserOptions",
|
||||
"199": "v2.4.2.3 - 2025-06-18",
|
||||
"200": "index.js",
|
||||
"201": "loading.ts",
|
||||
"202": "Community 202",
|
||||
"203": "tabs.ts",
|
||||
"207": "Community 207",
|
||||
"208": "Community 208",
|
||||
"209": "Community 209",
|
||||
@@ -436,7 +448,6 @@
|
||||
"732": "Community 732",
|
||||
"733": "Community 733",
|
||||
"734": "修复",
|
||||
"764": "新增",
|
||||
"766": "新增",
|
||||
"770": "移除",
|
||||
"772": "重构",
|
||||
@@ -500,7 +511,6 @@
|
||||
"1224": "emojis.js",
|
||||
"1225": "emojis.min.js",
|
||||
"1226": "index.js",
|
||||
"1227": "index.js",
|
||||
"1228": "ar.js",
|
||||
"1229": "bg_BG.js",
|
||||
"1230": "ca.js",
|
||||
@@ -590,7 +600,6 @@
|
||||
"1318": "content.js",
|
||||
"1319": "skin.js",
|
||||
"1320": "skin.shadowdom.js",
|
||||
"1322": "iconify-loader.ts",
|
||||
"1323": "index.vue",
|
||||
"1324": "index.vue",
|
||||
"1325": "index.vue",
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_json", "label": "package.json", "file_type": "code", "source_file": "package.json", "source_location": "L1"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_name", "label": "name", "file_type": "code", "source_file": "package.json", "source_location": "L2"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_version", "label": "version", "file_type": "code", "source_file": "package.json", "source_location": "L3"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_description", "label": "description", "file_type": "code", "source_file": "package.json", "source_location": "L4"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_type", "label": "type", "file_type": "code", "source_file": "package.json", "source_location": "L5"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_engines", "label": "engines", "file_type": "code", "source_file": "package.json", "source_location": "L6"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_engines_node", "label": "node", "file_type": "code", "source_file": "package.json", "source_location": "L7"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_engines_pnpm", "label": "pnpm", "file_type": "code", "source_file": "package.json", "source_location": "L8"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts", "label": "scripts", "file_type": "code", "source_file": "package.json", "source_location": "L10"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_dev", "label": "dev", "file_type": "code", "source_file": "package.json", "source_location": "L11"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_build", "label": "build", "file_type": "code", "source_file": "package.json", "source_location": "L12"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_build_typecheck", "label": "build:typecheck", "file_type": "code", "source_file": "package.json", "source_location": "L13"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_serve", "label": "serve", "file_type": "code", "source_file": "package.json", "source_location": "L14"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_lint", "label": "lint", "file_type": "code", "source_file": "package.json", "source_location": "L15"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_fix", "label": "fix", "file_type": "code", "source_file": "package.json", "source_location": "L16"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_lint_prettier", "label": "lint:prettier", "file_type": "code", "source_file": "package.json", "source_location": "L17"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_lint_stylelint", "label": "lint:stylelint", "file_type": "code", "source_file": "package.json", "source_location": "L18"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_lint_lint_staged", "label": "lint:lint-staged", "file_type": "code", "source_file": "package.json", "source_location": "L19"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_prepare", "label": "prepare", "file_type": "code", "source_file": "package.json", "source_location": "L20"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_commit", "label": "commit", "file_type": "code", "source_file": "package.json", "source_location": "L21"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_scripts_clean_dev", "label": "clean:dev", "file_type": "code", "source_file": "package.json", "source_location": "L22"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_config", "label": "config", "file_type": "code", "source_file": "package.json", "source_location": "L24"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_config_commitizen", "label": "commitizen", "file_type": "code", "source_file": "package.json", "source_location": "L25"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_commitizen_path", "label": "path", "file_type": "code", "source_file": "package.json", "source_location": "L26"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_lint_staged", "label": "lint-staged", "file_type": "code", "source_file": "package.json", "source_location": "L29"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_lint_staged_js_ts_mjs_mts_tsx", "label": "*.{js,ts,mjs,mts,tsx}", "file_type": "code", "source_file": "package.json", "source_location": "L30"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_lint_staged_cjs_json_jsonc", "label": "*.{cjs,json,jsonc}", "file_type": "code", "source_file": "package.json", "source_location": "L34"}, {"id": "users_wuzilong_work_00code_shanxia2_0_web_admin_package_lint_staged_vue", "label": "*.vue", "fileLine truncated
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"/Users/zlwu/work/00code/shanxia2.0/web-admin/package.json":{"size":3957,"mtime_ns":1781960299953649209,"hash":"ca01a16c94014e791391dfd8896f93c1ba7c451db1afa2f49f8a2a68b87dcc56"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/tsconfig.json":{"size":921,"mtime_ns":1780108931391506392,"hash":"8cec43256bc87216f729ae2c9588979558b20f33831419aa58502b54f5127c98"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/settings.json":{"size":425,"mtime_ns":1780108931156918274,"hash":"0f2b6369eaf54ccac995e091d7ef5e292fa1396eadd32b64cbddd5bba0018d14"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/extensions.json":{"size":200,"mtime_ns":1780108931156854566,"hash":"520c42e097d801a599814f12fe6a97bf5d7100e5395fd33217a365baa2cfe3c8"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/zh.json":{"size":10170,"mtime_ns":1783851637746348929,"hash":"015bc477ca647b32f2ef55c87db91ead797ec9db036de6dbf3578cd1be78de89"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/en.json":{"size":10312,"mtime_ns":1783851637976877140,"hash":"c46cb6e3ab9d55364fa79ce2ee42e46fb307f54350ee9abff7a71a74387c5982"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/mock/json/chinaMap.json":{"size":956443,"mtime_ns":1780108931366831877,"hash":"2ce3f532aed5b51fa9b64bf134bf1d77c7886e695fd55a3368333584cbef4113"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-flat.json":{"size":341606,"mtime_ns":1780108931184708348,"hash":"120c09f381ee3ac8fc6282e0be885a72ff256093c5aebf7a0861e38185d5f8ae"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-cascader.json":{"size":217969,"mtime_ns":1780108931184402180,"hash":"63789a66f6bd55e8adeda487f6e4f361f1a916c4fdb3e2d8961ee412de57d307"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.md":{"size":19526,"mtime_ns":1780108931156993275,"hash":"3e1cf79e220067ef1e99102d5cee89646591a03e292f7ca957e209ee264d416a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.md":{"size":4196,"mtime_ns":1780108931157199359,"hash":"114c94f9bf11e2083f1c985b2a5f58c5fbc50334dfbd25438415f21f8f577150"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.zh-CN.md":{"size":17172,"mtime_ns":1780108931157071900,"hash":"f4ec5751d75c6d3ec0767fd9c1f5787cc96c0a1ab059ed199ae4de1f1959f9fc"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.zh-CN.md":{"size":3775,"mtime_ns":1780108931157266568,"hash":"75a5522b08799b17dfe4416d20153a9cd247f5cbf280fe04ed0858a8337dc2d7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/views/crm/clue/README.md":{"size":7884,"mtime_ns":1780211534938564937,"hash":"43ee077b77166be37ebf44e0f13c8f01801f08a8274ebfa976ae21cbe8c27ca7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-quote-vue.py":{"size":4450,"mtime_ns":1780242127112333277,"hash":"97378f52743089231fbc83430106cad7701aa59b045126af45a238d7d2878bac"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-index-shell.py":{"size":11102,"mtime_ns":1780228518737746875,"hash":"0557768a404e2a0d9f2d3b233599bd741bdeb61a8e2d3cadf8d8dc4f1d6be25d"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-vue.py":{"size":4673,"mtime_ns":1780228615418009691,"hash":"790b4297df996f03b45d2efda686e219d60cd8e0f796fd860c070ed2e13939d6"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-attachments.py":{"size":1708,"mtime_ns":1780229286334758010,"hash":"eb364a061d7f7a6659311604353cd64a53edc81c1f1413b626ddf0388d709c46"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-panel.py":{"size":5523,"mtime_ns":1780229250658746500,"hash":"c873cdb8f5e8d8339aec3f47dc840106e1a176e3c9ac210ddd6d0abe547d928a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-attachments.py":{"size":14077,"mtime_ns":1780229316215427400,"hash":"470af77a8b9508291fab61aeee4c64bd495f78c77d09574e6b49962ce165eeaf"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-layout.py":{"size":5157,"mtime_ns":1780229581646441465,"hash":"d5d97158dd892bd942f61721bcae770de518de368f487c2a30129502b3125787"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-detail-fresh-mint.py":{"size":24615,"mtime_ns":1780229887010846627,"hash":"daf372506c69aa3a92a4ddf3d508252ae63b68718d00bb49fb03914cc8bcfee3"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/apply-list-toolbar-refresh.py":{"size":5777,"mtime_ns":1782834192989973152,"hash":"a2329df76d2aca29b6a7c751e43e61ec47b569718de910f3f10a2391d7b3bedb"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/add-list-index-columns.py":{"size":4644,"mtime_ns":1782865925817727372,"hash":"7e769c9dcb928cb8c4a5ce3eecebd488b94c4a2467959c99d8ec4cbed76bdb44"},"/Users/wuzilong/work/00code/shanxia2.0/web-admin/.vscode/extensions.json":{"size":200,"mtime_ns":1780108931000000000,"hash":"520c42e097d801a599814f12fe6a97bf5d7100e5395fd33217a365baa2cfe3c8"},"/Users/wuzilong/work/00code/shanxia2.0/web-admin/.vscode/settings.json":{"size":425,"mtime_ns":1780108931Line truncated
|
||||
{"/Users/zlwu/work/00code/shanxia2.0/web-admin/package.json":{"size":3957,"mtime_ns":1781960299953649209,"hash":"ca01a16c94014e791391dfd8896f93c1ba7c451db1afa2f49f8a2a68b87dcc56"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/tsconfig.json":{"size":921,"mtime_ns":1780108931391506392,"hash":"8cec43256bc87216f729ae2c9588979558b20f33831419aa58502b54f5127c98"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/settings.json":{"size":425,"mtime_ns":1780108931156918274,"hash":"0f2b6369eaf54ccac995e091d7ef5e292fa1396eadd32b64cbddd5bba0018d14"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/extensions.json":{"size":200,"mtime_ns":1780108931156854566,"hash":"520c42e097d801a599814f12fe6a97bf5d7100e5395fd33217a365baa2cfe3c8"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/zh.json":{"size":10170,"mtime_ns":1783851637746348929,"hash":"015bc477ca647b32f2ef55c87db91ead797ec9db036de6dbf3578cd1be78de89"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/en.json":{"size":10312,"mtime_ns":1783851637976877140,"hash":"c46cb6e3ab9d55364fa79ce2ee42e46fb307f54350ee9abff7a71a74387c5982"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/mock/json/chinaMap.json":{"size":956443,"mtime_ns":1780108931366831877,"hash":"2ce3f532aed5b51fa9b64bf134bf1d77c7886e695fd55a3368333584cbef4113"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-flat.json":{"size":341606,"mtime_ns":1780108931184708348,"hash":"120c09f381ee3ac8fc6282e0be885a72ff256093c5aebf7a0861e38185d5f8ae"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-cascader.json":{"size":217969,"mtime_ns":1780108931184402180,"hash":"63789a66f6bd55e8adeda487f6e4f361f1a916c4fdb3e2d8961ee412de57d307"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.md":{"size":19526,"mtime_ns":1780108931156993275,"hash":"3e1cf79e220067ef1e99102d5cee89646591a03e292f7ca957e209ee264d416a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.md":{"size":4196,"mtime_ns":1780108931157199359,"hash":"114c94f9bf11e2083f1c985b2a5f58c5fbc50334dfbd25438415f21f8f577150"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.zh-CN.md":{"size":17172,"mtime_ns":1780108931157071900,"hash":"f4ec5751d75c6d3ec0767fd9c1f5787cc96c0a1ab059ed199ae4de1f1959f9fc"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.zh-CN.md":{"size":3775,"mtime_ns":1780108931157266568,"hash":"75a5522b08799b17dfe4416d20153a9cd247f5cbf280fe04ed0858a8337dc2d7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/views/crm/clue/README.md":{"size":7884,"mtime_ns":1780211534938564937,"hash":"43ee077b77166be37ebf44e0f13c8f01801f08a8274ebfa976ae21cbe8c27ca7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-quote-vue.py":{"size":4450,"mtime_ns":1780242127112333277,"hash":"97378f52743089231fbc83430106cad7701aa59b045126af45a238d7d2878bac"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-index-shell.py":{"size":11102,"mtime_ns":1780228518737746875,"hash":"0557768a404e2a0d9f2d3b233599bd741bdeb61a8e2d3cadf8d8dc4f1d6be25d"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-vue.py":{"size":4673,"mtime_ns":1780228615418009691,"hash":"790b4297df996f03b45d2efda686e219d60cd8e0f796fd860c070ed2e13939d6"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-attachments.py":{"size":1708,"mtime_ns":1780229286334758010,"hash":"eb364a061d7f7a6659311604353cd64a53edc81c1f1413b626ddf0388d709c46"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-panel.py":{"size":5523,"mtime_ns":1780229250658746500,"hash":"c873cdb8f5e8d8339aec3f47dc840106e1a176e3c9ac210ddd6d0abe547d928a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-attachments.py":{"size":14077,"mtime_ns":1780229316215427400,"hash":"470af77a8b9508291fab61aeee4c64bd495f78c77d09574e6b49962ce165eeaf"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-layout.py":{"size":5157,"mtime_ns":1780229581646441465,"hash":"d5d97158dd892bd942f61721bcae770de518de368f487c2a30129502b3125787"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-detail-fresh-mint.py":{"size":24615,"mtime_ns":1780229887010846627,"hash":"daf372506c69aa3a92a4ddf3d508252ae63b68718d00bb49fb03914cc8bcfee3"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/apply-list-toolbar-refresh.py":{"size":5777,"mtime_ns":1782834192989973152,"hash":"a2329df76d2aca29b6a7c751e43e61ec47b569718de910f3f10a2391d7b3bedb"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/add-list-index-columns.py":{"size":4644,"mtime_ns":1782865925817727372,"hash":"7e769c9dcb928cb8c4a5ce3eecebd488b94c4a2467959c99d8ec4cbed76bdb44"},"/Users/wuzilong/work/00code/shanxia2.0/web-admin/.vscode/extensions.json":{"size":200,"mtime_ns":1780108931000000000,"hash":"520c42e097d801a599814f12fe6a97bf5d7100e5395fd33217a365baa2cfe3c8"},"/Users/wuzilong/work/00code/shanxia2.0/web-admin/.vscode/settings.json":{"size":425,"mtime_ns":1780108931Line truncated
|
||||
+2417
-2386
File diff suppressed because it is too large.
Load diff
Generated
-13732
File diff suppressed because it is too large.
Load diff
@@ -56,6 +56,7 @@
|
||||
"dependencies": {
|
||||
"@antv/x6": "^3.1.7",
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@iconify-json/ri": "^1.2.10",
|
||||
"@iconify/vue": "^5.0.0",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
"@tinymce/tinymce-vue": "^6.3.0",
|
||||
|
||||
Generated
+16
-26
@@ -14,6 +14,9 @@ importers:
|
||||
'@element-plus/icons-vue':
|
||||
specifier: ^2.3.2
|
||||
version: 2.3.2(vue@3.5.22(typescript@5.6.3))
|
||||
'@iconify-json/ri':
|
||||
specifier: ^1.2.10
|
||||
version: 1.2.10
|
||||
'@iconify/vue':
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0(vue@3.5.22(typescript@5.6.3))
|
||||
@@ -761,6 +764,9 @@ packages:
|
||||
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
||||
engines: {node: '>=18.18'}
|
||||
|
||||
'@iconify-json/ri@1.2.10':
|
||||
resolution: {integrity: sha512-WWMhoncVVM+Xmu9T5fgu2lhYRrKTEWhKk3Com0KiM111EeEsRLiASjpsFKnC/SrB6covhUp95r2mH8tGxhgd5Q==}
|
||||
|
||||
'@iconify/types@2.0.0':
|
||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||
|
||||
@@ -852,42 +858,36 @@ packages:
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||
@@ -964,67 +964,56 @@ packages:
|
||||
resolution: {integrity: sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.52.3':
|
||||
resolution: {integrity: sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.52.3':
|
||||
resolution: {integrity: sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.52.3':
|
||||
resolution: {integrity: sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.52.3':
|
||||
resolution: {integrity: sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.52.3':
|
||||
resolution: {integrity: sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.52.3':
|
||||
resolution: {integrity: sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.52.3':
|
||||
resolution: {integrity: sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.52.3':
|
||||
resolution: {integrity: sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.52.3':
|
||||
resolution: {integrity: sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.52.3':
|
||||
resolution: {integrity: sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.52.3':
|
||||
resolution: {integrity: sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==}
|
||||
@@ -1099,28 +1088,24 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.1.14':
|
||||
resolution: {integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.1.14':
|
||||
resolution: {integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.1.14':
|
||||
resolution: {integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.1.14':
|
||||
resolution: {integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==}
|
||||
@@ -1900,6 +1885,7 @@ packages:
|
||||
|
||||
crypto-js@4.2.0:
|
||||
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
|
||||
deprecated: Active development of CryptoJS has been discontinued. This library is no longer maintained.
|
||||
|
||||
css-functions-list@3.2.3:
|
||||
resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==}
|
||||
@@ -2492,6 +2478,7 @@ packages:
|
||||
git-raw-commits@4.0.0:
|
||||
resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==}
|
||||
engines: {node: '>=16'}
|
||||
deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.
|
||||
hasBin: true
|
||||
|
||||
glob-parent@5.1.2:
|
||||
@@ -2504,7 +2491,7 @@ packages:
|
||||
|
||||
glob@7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
|
||||
global-directory@4.0.1:
|
||||
resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==}
|
||||
@@ -2909,28 +2896,24 @@ packages:
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.30.1:
|
||||
resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-linux-x64-gnu@1.30.1:
|
||||
resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-x64-musl@1.30.1:
|
||||
resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.30.1:
|
||||
resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
|
||||
@@ -3889,6 +3872,7 @@ packages:
|
||||
tar@7.5.1:
|
||||
resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==}
|
||||
engines: {node: '>=18'}
|
||||
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
|
||||
terser@5.44.0:
|
||||
resolution: {integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==}
|
||||
@@ -4068,6 +4052,7 @@ packages:
|
||||
|
||||
uuid@8.3.2:
|
||||
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
|
||||
deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
|
||||
hasBin: true
|
||||
|
||||
vant@4.9.24:
|
||||
@@ -4178,6 +4163,7 @@ packages:
|
||||
vue-i18n@9.14.5:
|
||||
resolution: {integrity: sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g==}
|
||||
engines: {node: '>= 16'}
|
||||
deprecated: v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
@@ -4873,6 +4859,10 @@ snapshots:
|
||||
|
||||
'@humanwhocodes/retry@0.4.3': {}
|
||||
|
||||
'@iconify-json/ri@1.2.10':
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
|
||||
'@iconify/types@2.0.0': {}
|
||||
|
||||
'@iconify/vue@5.0.0(vue@3.5.22(typescript@5.6.3))':
|
||||
|
||||
@@ -83,10 +83,13 @@ export function fetchRefreshToken(refreshToken: string) {
|
||||
|
||||
/**
|
||||
* 登出
|
||||
* @param accessToken 可选:主动退出时传入当前 token,避免清空 store 后拦截器拿不到 Authorization
|
||||
*/
|
||||
export function fetchLogout() {
|
||||
export function fetchLogout(accessToken?: string) {
|
||||
return request.post({
|
||||
url: '/web/auth/logout'
|
||||
url: '/web/auth/logout',
|
||||
headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : undefined,
|
||||
showErrorMessage: false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<el-form-item label="产品名称" prop="productName">
|
||||
<el-input v-model="formData.productName" placeholder="请输入产品名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="拼音首字母" class="form-col-span-2">
|
||||
<el-form-item label="拼音首字母">
|
||||
<div class="pinyin-abbr-row">
|
||||
<el-input
|
||||
v-model="formData.namePinyinAbbr"
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue'
|
||||
// 使用 offline 构建,避免缺失图标时回退请求 api.unisvg.com
|
||||
import { Icon } from '@iconify/vue/offline'
|
||||
import { resolveEpIcon } from '@/utils/ui/ep-icon-map'
|
||||
|
||||
defineOptions({ name: 'ArtSvgIcon', inheritAttrs: false })
|
||||
|
||||
+2
-2
@@ -66,12 +66,12 @@ export function useSettingsConfig() {
|
||||
{
|
||||
value: ContainerWidthEnum.FULL,
|
||||
label: t('setting.container.list[0]'),
|
||||
icon: 'icon-park-outline:auto-width'
|
||||
icon: 'ri:fullscreen-line'
|
||||
},
|
||||
{
|
||||
value: ContainerWidthEnum.BOXED,
|
||||
label: t('setting.container.list[1]'),
|
||||
icon: 'ix:width'
|
||||
icon: 'ri:aspect-ratio-line'
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
@@ -468,7 +468,10 @@
|
||||
const wrap = scrollRef.value
|
||||
const ul = tabsRef.value
|
||||
if (!wrap || !ul) return false
|
||||
return ul.scrollWidth > wrap.clientWidth + 1
|
||||
// 布局未完成时 clientWidth 可能为 0,勿当作溢出(否则会误淘汰全部可关闭标签)
|
||||
const wrapWidth = wrap.clientWidth
|
||||
if (wrapWidth <= 0) return false
|
||||
return ul.scrollWidth > wrapWidth + 1
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
}>(),
|
||||
{
|
||||
ariaLabel: '日期快捷筛选',
|
||||
variant: 'select'
|
||||
variant: 'pills'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import './utils/patch-el-select-filterable'
|
||||
import './utils/ui/iconify-loader' // 离线注册 Remix Icon,避免请求 Iconify CDN
|
||||
import App from './App.vue'
|
||||
import { createApp } from 'vue'
|
||||
import { ElTable } from 'element-plus'
|
||||
|
||||
@@ -60,39 +60,23 @@ export class MenuProcessor {
|
||||
/** 确保 /home 启动器路由存在于菜单树(供动态注册) */
|
||||
private ensurePortalHomeRoute(menuList: AppRouteRecord[]): AppRouteRecord[] {
|
||||
const hasHome = menuList.some(
|
||||
(m) =>
|
||||
m.path === '/home-root' ||
|
||||
m.name === 'PortalHomeRoot' ||
|
||||
m.children?.some((c) => c.path === '/home' || c.name === 'PortalHome')
|
||||
(m) => m.path === '/home' || m.name === 'PortalHome'
|
||||
)
|
||||
if (hasHome) {
|
||||
return menuList
|
||||
}
|
||||
|
||||
const homeRoute: AppRouteRecord = {
|
||||
id: 'HOME00000000000000000000000000001',
|
||||
name: 'PortalHomeRoot',
|
||||
path: '/home-root',
|
||||
component: '/index/index',
|
||||
id: 'HOME00000000000000000000000000002',
|
||||
name: 'PortalHome',
|
||||
path: '/home',
|
||||
component: '/portal/home/index',
|
||||
meta: {
|
||||
title: '首页',
|
||||
keepAlive: false,
|
||||
keepAlive: true,
|
||||
fixedTab: true,
|
||||
isHide: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'HOME00000000000000000000000000002',
|
||||
name: 'PortalHome',
|
||||
path: '/home',
|
||||
component: '/portal/home/index',
|
||||
meta: {
|
||||
title: '首页',
|
||||
keepAlive: true,
|
||||
fixedTab: true,
|
||||
isHide: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return [homeRoute, ...menuList]
|
||||
}
|
||||
@@ -217,12 +201,7 @@ export class MenuProcessor {
|
||||
): AppRouteRecord[] {
|
||||
return menu.reduce((acc: AppRouteRecord[], item) => {
|
||||
// 门户启动器首页不参与 menuCodes 过滤
|
||||
if (
|
||||
item.path === '/home-root' ||
|
||||
item.path === '/home' ||
|
||||
item.name === 'PortalHomeRoot' ||
|
||||
item.name === 'PortalHome'
|
||||
) {
|
||||
if (item.path === '/home' || item.name === 'PortalHome') {
|
||||
acc.push({ ...item })
|
||||
return acc
|
||||
}
|
||||
|
||||
@@ -6,34 +6,20 @@ import type { AppRouteRecord } from '@/types/router'
|
||||
*/
|
||||
export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
// ──────────────────────────────────────────────
|
||||
// 门户菜单启动器首页(不在业务菜单树中展示)
|
||||
// 门户菜单启动器首页(一级叶子路由,由 Layout 包裹;不在业务菜单树中展示)
|
||||
// ──────────────────────────────────────────────
|
||||
{
|
||||
id: 'HOME00000000000000000000000000001',
|
||||
name: 'PortalHomeRoot',
|
||||
path: '/home-root',
|
||||
component: '/index/index',
|
||||
id: 'HOME00000000000000000000000000002',
|
||||
name: 'PortalHome',
|
||||
path: '/home',
|
||||
component: '/portal/home/index',
|
||||
meta: {
|
||||
title: '首页',
|
||||
keepAlive: false,
|
||||
keepAlive: true,
|
||||
fixedTab: true,
|
||||
isHide: true,
|
||||
roles: ['admin', 'super_admin']
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'HOME00000000000000000000000000002',
|
||||
name: 'PortalHome',
|
||||
path: '/home',
|
||||
component: '/portal/home/index',
|
||||
meta: {
|
||||
title: '首页',
|
||||
keepAlive: true,
|
||||
fixedTab: true,
|
||||
isHide: true,
|
||||
roles: ['admin', 'super_admin']
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@@ -123,9 +123,11 @@ export const useUserStore = defineStore(
|
||||
* 通知后端撤销 Redis 会话,然后清空所有用户相关状态并跳转到登录页
|
||||
*/
|
||||
const logOut = async () => {
|
||||
// 先通知后端撤销 Redis 会话(不等待结果,失败也不阻塞退出)
|
||||
if (accessToken.value) {
|
||||
fetchLogout().catch(() => {})
|
||||
// 先记下 token,再通知后端撤销会话(fire-and-forget);须显式带 Authorization,
|
||||
// 否则清空 store 后请求拦截器可能发无 Token 请求,后端返回 401 并触发未授权提示
|
||||
const tokenSnapshot = accessToken.value
|
||||
if (tokenSnapshot) {
|
||||
fetchLogout(tokenSnapshot).catch(() => {})
|
||||
}
|
||||
|
||||
// 保存当前用户 ID,用于下次登录时判断是否为同一用户
|
||||
|
||||
@@ -153,14 +153,18 @@ export const useWorktabStore = defineStore(
|
||||
overflowCheckHandler.value = fn
|
||||
}
|
||||
|
||||
/**
|
||||
* 门户多标签:若 DOM 判定溢出,仅淘汰 1 个最早的可关闭标签。
|
||||
*
|
||||
* 不能在同步 while 中反复 checker():关闭后 Vue 尚未重绘,scrollWidth 仍是旧值,
|
||||
* 会误判「持续溢出」并把所有可关闭标签一次清光(只剩固定首页)。
|
||||
* ArtWorkTab 在 opened.length 变更后 nextTick 再调用,逐步收到刚好不溢出为止。
|
||||
*/
|
||||
const evictUntilNoOverflow = (): void => {
|
||||
if (!isPortalMultiTabMode()) return
|
||||
const checker = overflowCheckHandler.value
|
||||
if (!checker) return
|
||||
let guard = 0
|
||||
while (checker() && guard++ < 50) {
|
||||
if (!evictOldestClosableTab()) break
|
||||
}
|
||||
if (!checker || !checker()) return
|
||||
if (!evictOldestClosableTab()) return
|
||||
if (current.value.path && findTabIndex(String(current.value.path)) === -1) {
|
||||
const fallback = opened.value[opened.value.length - 1]
|
||||
if (fallback?.path) {
|
||||
|
||||
@@ -163,10 +163,10 @@ axiosInstance.interceptors.request.use(
|
||||
}
|
||||
)
|
||||
|
||||
/** 登录/公钥等未持 Token 的认证接口:业务 401 不得走 refresh/登出 */
|
||||
/** 登录/公钥/登出等认证接口:业务 401 不得走 refresh/再登出(主动退出时尤其勿弹「未授权」) */
|
||||
function isPublicAuthApiUrl(url?: string): boolean {
|
||||
if (!url) return false
|
||||
return /\/web\/auth\/(login|login-rsa-public-key)(?:\?|$)/.test(url)
|
||||
return /\/web\/auth\/(login|login-rsa-public-key|logout)(?:\?|$)/.test(url)
|
||||
}
|
||||
|
||||
function isBlobResponseType(config?: AxiosRequestConfig): boolean {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* 离线图标加载器
|
||||
*
|
||||
* 用于在内网环境下支持 Iconify 图标的离线加载。
|
||||
* 通过预加载图标集数据,避免运行时从 CDN 获取图标。
|
||||
* 用于在内网/无法访问 Iconify CDN 的环境下支持 Iconify 图标。
|
||||
* 通过预加载图标集数据,避免运行时请求 api.unisvg.com / api.iconify.design。
|
||||
*
|
||||
* 使用方式:
|
||||
* 1. 安装所需图标集:pnpm add -D @iconify-json/[icon-set-name]
|
||||
* 1. 安装所需图标集:pnpm add @iconify-json/[icon-set-name]
|
||||
* 2. 在此文件中导入并注册图标集
|
||||
* 3. 在组件中使用:<ArtSvgIcon icon="ri:home-line" />
|
||||
*
|
||||
@@ -13,19 +13,7 @@
|
||||
* @author Art Design Pro Team
|
||||
*/
|
||||
|
||||
// import { addCollection } from '@iconify/vue'
|
||||
import { addCollection } from '@iconify/vue/offline'
|
||||
import { icons as riIcons } from '@iconify-json/ri'
|
||||
|
||||
// // 导入离线图标数据
|
||||
|
||||
// // 系统必要图标库
|
||||
// import riIcons from '@iconify-json/ri/icons.json'
|
||||
|
||||
// // 演示图标库(可选,生产环境可移除)
|
||||
// import svgSpinners from '@iconify-json/svg-spinners/icons.json'
|
||||
// import lineMd from '@iconify-json/line-md/icons.json'
|
||||
|
||||
// // 注册离线图标集
|
||||
|
||||
// addCollection(riIcons)
|
||||
// addCollection(svgSpinners)
|
||||
// addCollection(lineMd)
|
||||
addCollection(riIcons)
|
||||
@@ -22,12 +22,6 @@
|
||||
size="large"
|
||||
class="ml-2"
|
||||
>{{ dictStore.getLabel('crm_contract_status', detailContract?.status) }}</el-tag>
|
||||
<el-tag
|
||||
v-if="detailContract?.approvalStatus"
|
||||
:type="dictStore.getTagType('crm_approval_status', detailContract?.approvalStatus)"
|
||||
size="large"
|
||||
class="ml-2"
|
||||
>{{ dictStore.getLabel('crm_approval_status', detailContract?.approvalStatus) }}</el-tag>
|
||||
</div>
|
||||
<div class="detail-actions">
|
||||
<el-button
|
||||
|
||||
@@ -103,8 +103,7 @@ const submitLoading = ref(false)
|
||||
const formRef = ref<ElFormInstance>()
|
||||
|
||||
const rules = ref({
|
||||
invalidReason: [{ required: true, message: '请选择作废原因', trigger: 'change' }],
|
||||
invalidRemark: [{ required: true, message: '请输入详细说明', trigger: 'blur' }]
|
||||
invalidReason: [{ required: true, message: '请选择作废原因', trigger: 'change' }]
|
||||
})
|
||||
|
||||
const hasPaymentOrInvoice = computed(() => paymentAmount.value > 0 || invoiceAmount.value > 0)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row db-list-toolbar-row">
|
||||
<ListToolbarDateShortcuts
|
||||
variant="select"
|
||||
variant="pills"
|
||||
:active="activeDateShortcut"
|
||||
aria-label="日期快捷筛选"
|
||||
@change="handleDateShortcut"
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row db-list-toolbar-row">
|
||||
<ListToolbarDateShortcuts
|
||||
variant="select"
|
||||
variant="pills"
|
||||
:active="activeDateShortcut"
|
||||
aria-label="日期快捷筛选"
|
||||
@change="handleDateShortcut"
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row db-list-toolbar-row">
|
||||
<ListToolbarDateShortcuts
|
||||
variant="select"
|
||||
variant="pills"
|
||||
:active="activeDateShortcut"
|
||||
aria-label="日期快捷筛选"
|
||||
@change="handleDateShortcut"
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row io-order-list-toolbar-row">
|
||||
<ListToolbarDateShortcuts
|
||||
variant="select"
|
||||
variant="pills"
|
||||
:active="activeDateShortcut"
|
||||
aria-label="计划日期快捷筛选"
|
||||
@change="handleDateShortcut"
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row pl-plan-list-toolbar-row">
|
||||
<ListToolbarDateShortcuts
|
||||
variant="select"
|
||||
variant="pills"
|
||||
:active="activeDateShortcut"
|
||||
aria-label="计划日期快捷筛选"
|
||||
@change="handleDateShortcut"
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row pl-plan-list-toolbar-row">
|
||||
<ListToolbarDateShortcuts
|
||||
variant="select"
|
||||
variant="pills"
|
||||
:active="activeDateShortcut"
|
||||
aria-label="计划日期快捷筛选"
|
||||
@change="handleDateShortcut"
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<div class="list-toolbar">
|
||||
<div class="list-toolbar-row pl-plan-list-toolbar-row">
|
||||
<ListToolbarDateShortcuts
|
||||
variant="select"
|
||||
variant="pills"
|
||||
:active="activeDateShortcut"
|
||||
aria-label="计划日期快捷筛选"
|
||||
@change="handleDateShortcut"
|
||||
|
||||
+22
-7
@@ -250,20 +250,34 @@ shanxia2.0 的 Nginx 写法**参照 CRM 的代理头、超时、Gzip、SPA fallb
|
||||
|
||||
## 6. 日常运维
|
||||
|
||||
### 6.1 更新后端
|
||||
### 6.0 一键发版(推荐)
|
||||
|
||||
macOS 本机从仓库根目录执行(凭据读自根目录 `生产机器账号密码`,密码不写进脚本):
|
||||
|
||||
```bash
|
||||
./生产环境部署/deploy-release.sh
|
||||
# 已有 dist 时可跳过构建:
|
||||
./生产环境部署/deploy-release.sh --skip-build
|
||||
```
|
||||
|
||||
顺序:本地 `pnpm build` → 备份远程 `web` → 同步 `dist`(**保留**远程 `dist/src`)→ 备份远程 `backend` → 替换 `backend/app` → `PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart` → 健康检查。
|
||||
|
||||
备份落在 `/iflytek/shanxia2.0/bak/web-*` 与 `backend-*`。依赖:`ssh`、`rsync`、`sshpass`(`brew install hudochenkov/sshpass/sshpass`)、`pnpm`。
|
||||
|
||||
### 6.1 更新后端(手工)
|
||||
|
||||
```bash
|
||||
cd /iflytek/shanxia2.0/backend
|
||||
# 上传新代码后
|
||||
./venv/bin/pip install -r requirements.txt
|
||||
PORT=9111 ENV_FILE=./.env.production ./start-prod.sh restart
|
||||
PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart
|
||||
```
|
||||
|
||||
### 6.2 更新前端
|
||||
### 6.2 更新前端(手工)
|
||||
|
||||
```bash
|
||||
# 本地 build 后上传 dist 覆盖
|
||||
rsync -avz --delete web-admin/dist/ root@121.43.228.102:/iflytek/shanxia2.0/web/dist/
|
||||
# 本地 build 后上传 dist;务必保留远程 dist/src
|
||||
rsync -avz --delete --exclude 'src/' web-admin/dist/ root@121.43.228.102:/iflytek/shanxia2.0/web/dist/
|
||||
# 无需重启后端;浏览器强刷或清缓存
|
||||
```
|
||||
|
||||
@@ -314,8 +328,8 @@ systemctl start shanxia2.0-backend
|
||||
|
||||
## 7. 回滚策略
|
||||
|
||||
1. **前端**:保留上一版 `dist` 备份目录,出问题直接 `rsync` 回滚
|
||||
2. **后端**:保留上一版代码目录或 tar 包,`start-prod.sh restart`
|
||||
1. **前端**:`/iflytek/shanxia2.0/bak/web-*` 中对应备份覆盖回 `web`(注意勿误删业务依赖的 `dist/src`)
|
||||
2. **后端**:从 `bak/backend-*` 还原后,在 `backend` 目录执行 `PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart`
|
||||
3. **数据库**:增量 SQL 应可逆或先备份;重大变更前 `mysqldump`
|
||||
|
||||
---
|
||||
@@ -334,6 +348,7 @@ systemctl start shanxia2.0-backend
|
||||
| 文件 | 用途 |
|
||||
|---|---|
|
||||
| `README.md` | 本文档 |
|
||||
| `deploy-release.sh` | macOS 一键发版(前端→后端,含备份与健康检查) |
|
||||
| `nginx-shanxia2.0.conf` | Nginx 站点模板 |
|
||||
| `backend.env.production.example` | 后端生产环境变量模板 |
|
||||
| `web-admin.env.production.example` | 前端构建环境变量模板 |
|
||||
|
||||
Executable
+235
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================
|
||||
# shanxia2.0 生产一键发版(前端 → 后端)
|
||||
#
|
||||
# 用法(在仓库任意目录执行均可):
|
||||
# ./生产环境部署/deploy-release.sh
|
||||
# ./生产环境部署/deploy-release.sh --skip-build # 跳过本地 pnpm build,使用已有 dist
|
||||
#
|
||||
# 凭据:仓库根目录「生产机器账号密码」
|
||||
# 生产路径:
|
||||
# 前端 /iflytek/shanxia2.0/web/dist (保留远程 dist/src,禁止删除)
|
||||
# 后端 /iflytek/shanxia2.0/backend/app
|
||||
# 备份 /iflytek/shanxia2.0/bak/
|
||||
# ============================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
CRED_FILE="${CRED_FILE:-$REPO_ROOT/生产机器账号密码}"
|
||||
|
||||
REMOTE_BASE="/iflytek/shanxia2.0"
|
||||
REMOTE_WEB="$REMOTE_BASE/web"
|
||||
REMOTE_DIST="$REMOTE_WEB/dist"
|
||||
REMOTE_BACKEND="$REMOTE_BASE/backend"
|
||||
REMOTE_BAK="$REMOTE_BASE/bak"
|
||||
|
||||
LOCAL_WEB_ADMIN="$REPO_ROOT/web-admin"
|
||||
LOCAL_DIST="$LOCAL_WEB_ADMIN/dist"
|
||||
LOCAL_APP="$REPO_ROOT/backend/app"
|
||||
|
||||
SSH_USER="root"
|
||||
SSH_OPTS=(-o StrictHostKeyChecking=accept-new -o ServerAliveInterval=30)
|
||||
|
||||
SKIP_BUILD=0
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--skip-build) SKIP_BUILD=1 ;;
|
||||
-h|--help)
|
||||
sed -n '2,16p' "$0" | sed 's/^# \?//'
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "未知参数: $arg(支持 --skip-build)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
log_err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
||||
|
||||
die() {
|
||||
log_err "$@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || die "缺少命令: $1。$2"
|
||||
}
|
||||
|
||||
# ---------- 前置检查 ----------
|
||||
require_cmd ssh "macOS 系统自带即可。"
|
||||
require_cmd rsync "macOS 系统自带即可。"
|
||||
require_cmd sshpass "请执行: brew install hudochenkov/sshpass/sshpass"
|
||||
|
||||
[[ -f "$CRED_FILE" ]] || die "凭据文件不存在: $CRED_FILE"
|
||||
[[ -d "$LOCAL_APP" ]] || die "本地后端不存在: $LOCAL_APP"
|
||||
|
||||
# ---------- 解析凭据 ----------
|
||||
# 支持:
|
||||
# ip: 1.2.3.4
|
||||
# root账号:xxx / root密码:xxx / 密码:xxx
|
||||
parse_credentials() {
|
||||
local ip="" pass=""
|
||||
local line key val
|
||||
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
line="${line#"${line%%[![:space:]]*}"}"
|
||||
line="${line%"${line##*[![:space:]]}"}"
|
||||
[[ -z "$line" || "$line" == \#* ]] && continue
|
||||
|
||||
# 勿用 [::] 字符类:bash 会把全角冒号与 : 当成范围,误匹配中文
|
||||
if [[ "$line" == *:* ]]; then
|
||||
key="${line%%:*}"
|
||||
val="${line#*:}"
|
||||
elif [[ "$line" == *:* ]]; then
|
||||
key="${line%%:*}"
|
||||
val="${line#*:}"
|
||||
else
|
||||
continue
|
||||
fi
|
||||
key="${key//[[:space:]]/}"
|
||||
val="${val#"${val%%[![:space:]]*}"}"
|
||||
val="${val%"${val##*[![:space:]]}"}"
|
||||
|
||||
case "$key" in
|
||||
ip|IP|host|Host|HOST) ip="$val" ;;
|
||||
root账号|root密码|密码|password|Password|PASSWORD|passwd) pass="$val" ;;
|
||||
esac
|
||||
done < "$CRED_FILE"
|
||||
|
||||
[[ -n "$ip" ]] || die "凭据文件未解析到 IP(期望行如: ip: 121.x.x.x)"
|
||||
[[ -n "$pass" ]] || die "凭据文件未解析到密码(期望行如: root账号:***)"
|
||||
|
||||
REMOTE_HOST="$ip"
|
||||
REMOTE_PASS="$pass"
|
||||
}
|
||||
|
||||
parse_credentials
|
||||
log_info "目标主机: ${SSH_USER}@${REMOTE_HOST}"
|
||||
|
||||
export SSHPASS="$REMOTE_PASS"
|
||||
trap 'unset SSHPASS REMOTE_PASS 2>/dev/null || true' EXIT
|
||||
|
||||
remote_ssh() {
|
||||
sshpass -e ssh "${SSH_OPTS[@]}" "${SSH_USER}@${REMOTE_HOST}" "$@"
|
||||
}
|
||||
|
||||
remote_rsync() {
|
||||
# 用法: remote_rsync [rsync-args...] src dest
|
||||
sshpass -e rsync -e "ssh ${SSH_OPTS[*]}" "$@"
|
||||
}
|
||||
|
||||
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
|
||||
GIT_SHA="$(git -C "$REPO_ROOT" rev-parse --short HEAD 2>/dev/null || echo unknown)"
|
||||
log_info "发版时间戳: $TIMESTAMP commit: $GIT_SHA"
|
||||
|
||||
# ---------- 1. 本地构建前端 ----------
|
||||
if [[ "$SKIP_BUILD" -eq 1 ]]; then
|
||||
log_warn "已跳过 pnpm build,使用现有 dist"
|
||||
else
|
||||
require_cmd pnpm "请安装 pnpm: npm i -g pnpm"
|
||||
[[ -f "$LOCAL_WEB_ADMIN/.env.production" ]] || log_warn "未找到 web-admin/.env.production,请确认生产构建配置正确"
|
||||
log_info "开始构建前端: cd web-admin && pnpm build"
|
||||
(
|
||||
cd "$LOCAL_WEB_ADMIN"
|
||||
pnpm build
|
||||
)
|
||||
fi
|
||||
|
||||
[[ -d "$LOCAL_DIST" ]] || die "前端产物不存在: $LOCAL_DIST(请先构建或去掉 --skip-build)"
|
||||
[[ -f "$LOCAL_DIST/index.html" ]] || die "前端产物异常: 缺少 $LOCAL_DIST/index.html"
|
||||
|
||||
# ---------- 2. 备份远程 web ----------
|
||||
log_info "备份远程 web → ${REMOTE_BAK}/web-${TIMESTAMP}"
|
||||
remote_ssh "mkdir -p '${REMOTE_BAK}' && \
|
||||
if [[ -d '${REMOTE_WEB}' ]]; then \
|
||||
cp -a '${REMOTE_WEB}' '${REMOTE_BAK}/web-${TIMESTAMP}'; \
|
||||
else \
|
||||
echo '远程 web 目录不存在,跳过备份' >&2; \
|
||||
exit 1; \
|
||||
fi"
|
||||
|
||||
# ---------- 3. 同步前端 dist(保留远程 dist/src)----------
|
||||
log_info "同步前端到 ${REMOTE_DIST}(rsync --delete,排除 src/)"
|
||||
remote_ssh "mkdir -p '${REMOTE_DIST}'"
|
||||
# --exclude 'src/':不同步也不删除远程 src
|
||||
# --delete:删除远程 dist 中本地已不存在的构建文件(不含被 exclude 的 src)
|
||||
remote_rsync -az --delete --exclude 'src/' --exclude '.DS_Store' \
|
||||
"${LOCAL_DIST}/" \
|
||||
"${SSH_USER}@${REMOTE_HOST}:${REMOTE_DIST}/"
|
||||
|
||||
remote_ssh "[[ -d '${REMOTE_DIST}/src' ]] && echo 'OK: dist/src 仍存在' || echo 'NOTE: 远程 dist/src 当前不存在(若业务依赖请检查)'"
|
||||
log_info "前端同步完成"
|
||||
|
||||
# ---------- 4. 备份远程 backend ----------
|
||||
log_info "备份远程 backend → ${REMOTE_BAK}/backend-${TIMESTAMP}"
|
||||
remote_ssh "mkdir -p '${REMOTE_BAK}' && \
|
||||
if [[ -d '${REMOTE_BACKEND}' ]]; then \
|
||||
cp -a '${REMOTE_BACKEND}' '${REMOTE_BAK}/backend-${TIMESTAMP}'; \
|
||||
else \
|
||||
echo '远程 backend 目录不存在,跳过备份' >&2; \
|
||||
exit 1; \
|
||||
fi"
|
||||
|
||||
# ---------- 5. 替换 backend/app,并同步依赖清单 ----------
|
||||
log_info "替换远程 ${REMOTE_BACKEND}/app"
|
||||
remote_ssh "rm -rf '${REMOTE_BACKEND}/app'"
|
||||
remote_rsync -az --delete \
|
||||
--exclude '__pycache__/' \
|
||||
--exclude '*.pyc' \
|
||||
--exclude '.DS_Store' \
|
||||
"${LOCAL_APP}/" \
|
||||
"${SSH_USER}@${REMOTE_HOST}:${REMOTE_BACKEND}/app/"
|
||||
if [[ -f "$REPO_ROOT/backend/requirements.txt" ]]; then
|
||||
log_info "同步 requirements.txt 并安装依赖"
|
||||
remote_rsync -az \
|
||||
"$REPO_ROOT/backend/requirements.txt" \
|
||||
"${SSH_USER}@${REMOTE_HOST}:${REMOTE_BACKEND}/requirements.txt"
|
||||
remote_ssh "cd '${REMOTE_BACKEND}' && \
|
||||
./venv/bin/pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple"
|
||||
fi
|
||||
log_info "后端 app 同步完成"
|
||||
|
||||
# ---------- 6. 重启后端 ----------
|
||||
log_info "重启后端服务 (PORT=9111 WORKERS=1)"
|
||||
remote_ssh "cd '${REMOTE_BACKEND}' && \
|
||||
chmod +x ./start-prod.sh && \
|
||||
PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart"
|
||||
|
||||
# ---------- 7. 健康检查(重启后进程可能尚未监听,重试数秒)----------
|
||||
log_info "健康检查 /health"
|
||||
HEALTH_OUT=""
|
||||
for _i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
HEALTH_OUT="$(remote_ssh "curl -fsS --max-time 5 http://127.0.0.1:9111/health" 2>/dev/null || true)"
|
||||
if [[ "$HEALTH_OUT" == *healthy* ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
if [[ "$HEALTH_OUT" == *healthy* ]]; then
|
||||
log_info "健康检查通过: $HEALTH_OUT"
|
||||
else
|
||||
log_err "健康检查未通过,远程输出: ${HEALTH_OUT:-<empty>}"
|
||||
log_warn "可手动排查: ssh ${SSH_USER}@${REMOTE_HOST} 'cd ${REMOTE_BACKEND} && ./start-prod.sh status|logs'"
|
||||
log_warn "备份位置: ${REMOTE_BAK}/web-${TIMESTAMP} ${REMOTE_BAK}/backend-${TIMESTAMP}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
unset SSHPASS REMOTE_PASS
|
||||
|
||||
echo
|
||||
log_info "发版成功"
|
||||
echo " commit: $GIT_SHA"
|
||||
echo " 前端备份: ${REMOTE_BAK}/web-${TIMESTAMP}"
|
||||
echo " 后端备份: ${REMOTE_BAK}/backend-${TIMESTAMP}"
|
||||
echo " 管理端: http://${REMOTE_HOST}:9911"
|
||||
echo
|
||||
Reference in new issue
Block a user