Compare commits
95 Commits
af7c652ed4
...
ops-test-0
| Author | SHA1 | Date | |
|---|---|---|---|
| a6a6198eaa | |||
| 9fbfe54f92 | |||
| fb9c5b9255 | |||
| 73247053dd | |||
| 695755546f | |||
| 43ce3433ce | |||
| 3e60e699ce | |||
| 5cbfb36fbf | |||
| 87ec4dff70 | |||
| 46559fe955 | |||
| c550369a4b | |||
| a9c2a499ce | |||
| 24dd0c17da | |||
| 913e9e63ad | |||
| 3abdc187fb | |||
| 809dc883f5 | |||
| 7c505f8169 | |||
| 3654ccb9db | |||
| 195aa7ccff | |||
| 7353c4eede | |||
| dbda9f76fb | |||
| c2c5afa82d | |||
| f5c7ebc59c | |||
| 98e1baf1bb | |||
| 51f938fbfc | |||
| e43ada5c7f | |||
| f2f4390ac2 | |||
| 52a0346c4c | |||
| 4b9a87638c | |||
| b4dba77229 | |||
| 7e61f330dc | |||
| 8c1772c784 | |||
| c9da54829d | |||
| db767de8bb | |||
| 9cbacf5998 | |||
| 947fa2f9b9 | |||
| e5df404aaa | |||
| 8a6ec3ef96 | |||
| 922f7dfc4b | |||
| ee101984f0 | |||
| 3f4d50b395 | |||
| 58365870ef | |||
| aa6db97457 | |||
| f5d0bae89b | |||
| cc6ea1acc6 | |||
| 7a20329594 | |||
| 83b713890b | |||
| c3f38f5e2a | |||
| c6d0df6fd2 | |||
| 93e8f3349f | |||
| fc5d653433 | |||
| fafdb0d830 | |||
| 99a5f8bd16 | |||
| 9f1c3eb660 | |||
| 1ad0323715 | |||
| b01a0f0979 | |||
| 8f3dd3e43e | |||
| 2107f77081 | |||
| fcaad4b3ae | |||
| cd5e8b5f2d | |||
| 18531bfcac | |||
| d104dd8df9 | |||
| bd61f722a2 | |||
| 27e1f335a6 | |||
| 026cff306a | |||
| 1af4075e9b | |||
| ea3e60c17c | |||
| ea9531313e | |||
| f7b34c5d60 | |||
| 39150be726 | |||
| 25e8eafc69 | |||
| e569571462 | |||
| 7f209b5fef | |||
| d9a0470ecf | |||
| 39d3254b8d | |||
| 0a12f54132 | |||
| 9afaa4b775 | |||
| 878cbea9a5 | |||
| d5df671ff6 | |||
| ba933457d4 | |||
| 01139f2874 | |||
| cb8bd05ff7 | |||
| 55170bceb0 | |||
| 8db158c390 | |||
| b8a7ba1cbb | |||
| e84cb75dda | |||
| f030f9c5c9 | |||
| 003c552238 | |||
| 1dcab7af96 | |||
| 5f4111aeb1 | |||
| c72af0bfa7 | |||
| 68a320b6c2 | |||
| a0ca86d98d | |||
| dc31084d87 | |||
| 8b3bd98e68 |
@@ -6,11 +6,18 @@ VITE_APP_WORKSPACE=ops
|
||||
# 应用标题
|
||||
VITE_APP_TITLE=标准管理系统
|
||||
VITE_APP_DESCRIPTION="default standard template"
|
||||
VITE_USE_MOCK=false
|
||||
|
||||
# API 基础URL
|
||||
VITE_API_BASE_URL=https://ops-api.apinb.com
|
||||
# 开发环境通过 Vite 同源代理访问 API,避免浏览器跨域
|
||||
VITE_API_BASE_URL=/api
|
||||
VITE_API_PROXY_TARGET=https://ops-api.apinb.com
|
||||
|
||||
# 海康 WebSDK 开发代理(按实际摄像头/NVR 地址填写,不要提交账号密码)
|
||||
VITE_HIKVISION_PROXY_TARGET=http://192.168.1.101:80
|
||||
VITE_HIKVISION_WS_PROXY_TARGET=
|
||||
|
||||
# Logs 本地调试地址(仅 logs 模块使用)
|
||||
VITE_LOGS_API_BASE_URL=http://127.0.0.1:12440
|
||||
|
||||
# 应用版本
|
||||
VITE_APP_VERSION=1.0.0
|
||||
|
||||
@@ -5,6 +5,7 @@ VITE_APP_WORKSPACE=ops
|
||||
|
||||
VITE_APP_TITLE=标准管理系统
|
||||
VITE_APP_DESCRIPTION="default standard template"
|
||||
VITE_USE_MOCK=false
|
||||
|
||||
# API 基础URL
|
||||
VITE_API_BASE_URL=https://ops-api.apinb.com
|
||||
|
||||
115
.kilo/package-lock.json
generated
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"name": ".kilo",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@kilocode/plugin": "7.2.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@kilocode/plugin": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@kilocode/plugin/-/plugin-7.2.14.tgz",
|
||||
"integrity": "sha512-mS+WA9HZIBH2qQ9ARA+v0q4MdQTSdfOvKbe4AOSkjP+P5hVA70OM/UVM9DVcvmjSOxU+wuUxmOy+j/EQIrgFmw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@kilocode/sdk": "7.2.14",
|
||||
"zod": "4.1.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentui/core": ">=0.1.97",
|
||||
"@opentui/solid": ">=0.1.97"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@opentui/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@opentui/solid": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@kilocode/sdk": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@kilocode/sdk/-/sdk-7.2.14.tgz",
|
||||
"integrity": "sha512-Naz83lFrsbavuDp6UwxRuglOaSNvRBsZfcRNvb7RpWYAwbuJP0dBdhpXj6uO3ta5qxeQ2JzxKNC9Ffz+LCLLDg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "7.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.1.8",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
115
.kilocode/package-lock.json
generated
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"name": ".kilocode",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@kilocode/plugin": "7.2.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@kilocode/plugin": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@kilocode/plugin/-/plugin-7.2.14.tgz",
|
||||
"integrity": "sha512-mS+WA9HZIBH2qQ9ARA+v0q4MdQTSdfOvKbe4AOSkjP+P5hVA70OM/UVM9DVcvmjSOxU+wuUxmOy+j/EQIrgFmw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@kilocode/sdk": "7.2.14",
|
||||
"zod": "4.1.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentui/core": ">=0.1.97",
|
||||
"@opentui/solid": ">=0.1.97"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@opentui/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@opentui/solid": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@kilocode/sdk": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@kilocode/sdk/-/sdk-7.2.14.tgz",
|
||||
"integrity": "sha512-Naz83lFrsbavuDp6UwxRuglOaSNvRBsZfcRNvb7RpWYAwbuJP0dBdhpXj6uO3ta5qxeQ2JzxKNC9Ffz+LCLLDg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "7.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.1.8",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,34 @@
|
||||
# Architect Mode Rules (Non-Obvious Only)
|
||||
|
||||
## Development Constraints
|
||||
|
||||
- Code is not deployed yet; do not spend effort preserving backward compatibility with old code.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
- Vue 3 SPA with dynamic route loading from server
|
||||
- Pinia stores: `app`, `user`, `tab-bar` (see [`src/store/`](src/store/))
|
||||
- Two-layer route guard: user login check + permission check
|
||||
|
||||
## Dynamic Route System
|
||||
|
||||
- Server menu fetched in [`app store`](src/store/modules/app/index.ts) via `fetchServerMenuConfig()`
|
||||
- Routes registered dynamically in [`permission.ts`](src/router/guard/permission.ts)
|
||||
- Uses `isMenuLoading`/`isMenuLoaded` flags to prevent duplicate loads
|
||||
|
||||
## API Architecture
|
||||
|
||||
- Two axios instances for different auth patterns:
|
||||
- [`request.ts`](src/api/request.ts): Workspace header + custom token format
|
||||
- [`interceptor.ts`](src/api/interceptor.ts): Bearer token + code 20000 validation
|
||||
- Choose based on backend API requirements
|
||||
|
||||
## State Management
|
||||
|
||||
- [`SafeStorage`](src/utils/safeStorage.ts) required for all localStorage access
|
||||
- Supports TTL expiry and type-safe keys via enum
|
||||
|
||||
## Component Patterns
|
||||
|
||||
- Global components registered in [`components/index.ts`](src/components/index.ts)
|
||||
- ECharts modules manually imported for bundle size optimization
|
||||
- ECharts modules manually imported for bundle size optimization
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
# Ask Mode Rules (Non-Obvious Only)
|
||||
|
||||
## Project Structure
|
||||
|
||||
- Vue 3 + Arco Design admin template with Pinia state management
|
||||
- Vite config files located in `config/` directory (not root)
|
||||
|
||||
## Key Directories
|
||||
|
||||
- `src/api/` - API layer with two axios instances
|
||||
- `src/views/ops/` - Main business modules (kb, netarch, asset, etc.)
|
||||
- `src/router/guard/` - Route guards including dynamic menu loading
|
||||
- `src/store/modules/app/` - App store with server menu fetching
|
||||
|
||||
## Documentation References
|
||||
|
||||
- Arco Design Vue: https://arco.design/vue
|
||||
- Vue Flow (for topology): https://vueflow.dev/
|
||||
|
||||
## API Patterns
|
||||
|
||||
- Use [`request.ts`](src/api/request.ts) for workspace-aware requests
|
||||
- Use [`interceptor.ts`](src/api/interceptor.ts) for standard Bearer token auth
|
||||
- Use [`interceptor.ts`](src/api/interceptor.ts) for standard Bearer token auth
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
# Code Mode Rules (Non-Obvious Only)
|
||||
|
||||
## Development Constraints
|
||||
|
||||
- Code is not deployed yet; do not spend effort preserving backward compatibility with old code.
|
||||
|
||||
## API Layer
|
||||
|
||||
- Two axios instances exist: [`request.ts`](src/api/request.ts) (custom with workspace header) and [`interceptor.ts`](src/api/interceptor.ts) (global with Bearer token). Choose based on whether you need workspace support.
|
||||
|
||||
## Storage
|
||||
|
||||
- Always use [`SafeStorage`](src/utils/safeStorage.ts) with `AppStorageKey` enum - never use localStorage directly. Supports TTL via third parameter.
|
||||
|
||||
## useRequest Hook
|
||||
|
||||
- [`useRequest()`](src/hooks/request.ts) invokes API immediately - does NOT work in async functions. Pass params via `.bind(null, params)` pattern.
|
||||
|
||||
## Dynamic Routes
|
||||
- Routes loaded from server in [`permission.ts`](src/router/guard/permission.ts) using `isMenuLoading`/`isMenuLoaded` flags. Don't modify these flags manually.
|
||||
|
||||
- Routes loaded from server in [`permission.ts`](src/router/guard/permission.ts) using `isMenuLoading`/`isMenuLoaded` flags. Don't modify these flags manually.
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
# Debug Mode Rules (Non-Obvious Only)
|
||||
|
||||
## API Response Codes
|
||||
|
||||
- [`interceptor.ts`](src/api/interceptor.ts) expects `code: 20000` for success. Other codes trigger error messages.
|
||||
- Token expiry codes: 50008, 50012, 50014 trigger logout modal.
|
||||
|
||||
## Token Storage
|
||||
|
||||
- Tokens stored via [`SafeStorage`](src/utils/safeStorage.ts) with key `AppStorageKey.TOKEN`.
|
||||
- Token expiry redirects to `/auth/login` (not `/login`).
|
||||
|
||||
## Route Loading Issues
|
||||
|
||||
- If routes not loading, check `isMenuLoading`/`isMenuLoaded` flags in [`permission.ts`](src/router/guard/permission.ts).
|
||||
- Server menu fetched via [`fetchServerMenuConfig()`](src/store/modules/app/index.ts).
|
||||
|
||||
## Environment
|
||||
|
||||
- Dev config: `.env.development`, Prod config: `.env.production`
|
||||
- API base URL: `VITE_API_BASE_URL`, Workspace: `VITE_APP_WORKSPACE`
|
||||
- API base URL: `VITE_API_BASE_URL`, Workspace: `VITE_APP_WORKSPACE`
|
||||
|
||||
1123
3D机房前后端接口文档.md
Normal file
@@ -13,6 +13,10 @@ This file provides guidance to agents when working with code in this repository.
|
||||
|
||||
## Critical Architecture Notes
|
||||
|
||||
### Development Constraints
|
||||
|
||||
- Code is not deployed yet; do not spend effort preserving backward compatibility with old code.
|
||||
|
||||
### Vite Config Location
|
||||
|
||||
Config files are in `config/` directory, NOT root. All vite commands reference `./config/vite.config.*.ts`.
|
||||
|
||||
196
PAGES_README.md
@@ -1,196 +0,0 @@
|
||||
# 官网首页和帮助中心页面说明
|
||||
|
||||
## 新增页面
|
||||
|
||||
本次为系统添加了两个全新的对外页面,无需登录即可访问:
|
||||
|
||||
### 1. 官网首页 (`/home`)
|
||||
|
||||
**功能特点:**
|
||||
- 🎨 现代化的渐变背景设计
|
||||
- 📱 响应式布局,适配各种设备
|
||||
- 🎯 清晰的功能特性展示区域
|
||||
- 📊 数据中心关键指标展示
|
||||
- 🔗 快速导航到登录系统和帮助中心
|
||||
- 💬 完整的页脚信息
|
||||
|
||||
**主要板块:**
|
||||
1. **顶部导航栏** - 包含 Logo、导航链接和登录按钮
|
||||
2. **Banner 区域** - 醒目的标题和行动号召按钮
|
||||
3. **功能特性** - 6 个核心功能卡片展示
|
||||
4. **数据中心** - 关键运行指标统计
|
||||
5. **行动号召** - 引导用户登录或查看帮助
|
||||
6. **页脚** - 版权信息和快速链接
|
||||
|
||||
**访问方式:**
|
||||
- 直接访问:`http://your-domain/#/home`
|
||||
- 根路径自动重定向到首页
|
||||
|
||||
### 2. 帮助中心页面 (`/help`)
|
||||
|
||||
**功能特点:**
|
||||
- 🔍 文档搜索功能
|
||||
- 📑 左侧分类导航菜单
|
||||
- ❓ 常见问题 FAQ(折叠面板)
|
||||
- 📖 使用指南卡片
|
||||
- 📥 操作手册下载
|
||||
- 📞 联系方式展示
|
||||
|
||||
**主要内容:**
|
||||
1. **常见问题** - 8 个典型问题的问答
|
||||
2. **使用指南** - 6 个分类的详细教程
|
||||
- 快速入门
|
||||
- 仪表盘
|
||||
- 告警管理
|
||||
- 数据中心
|
||||
- 报表分析
|
||||
- 系统设置
|
||||
3. **操作手册** - 可下载的文档资料
|
||||
4. **联系我们** - 电话、邮件、在线客服
|
||||
|
||||
**访问方式:**
|
||||
- 直接访问:`http://your-domain/#/help`
|
||||
- 从首页导航点击"帮助中心"
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 文件结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── views/
|
||||
│ ├── home/ # 官网首页
|
||||
│ │ └── index.vue
|
||||
│ └── help/ # 帮助中心
|
||||
│ └── index.vue
|
||||
├── layout/
|
||||
│ └── standalone-layout.vue # 独立布局(无侧边栏)
|
||||
└── router/
|
||||
├── index.ts # 路由配置
|
||||
└── constants.ts # 路由常量(白名单)
|
||||
```
|
||||
|
||||
### 路由配置
|
||||
|
||||
```typescript
|
||||
// 根路径配置
|
||||
{
|
||||
path: '/',
|
||||
name: 'root',
|
||||
component: () => import('@/layout/standalone-layout.vue'),
|
||||
redirect: '/home',
|
||||
children: [
|
||||
{
|
||||
path: '/home',
|
||||
name: 'Home',
|
||||
component: () => import('@/views/home/index.vue'),
|
||||
meta: { requiresAuth: false }
|
||||
},
|
||||
{
|
||||
path: '/help',
|
||||
name: 'Help',
|
||||
component: () => import('@/views/help/index.vue'),
|
||||
meta: { requiresAuth: false }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 权限控制
|
||||
|
||||
- 两个页面都设置了 `requiresAuth: false`,无需登录即可访问
|
||||
- 已添加到路由白名单 `WHITE_LIST` 中
|
||||
- 使用独立的 `standalone-layout`,不显示系统的导航栏和侧边栏
|
||||
|
||||
## 自定义内容
|
||||
|
||||
### 修改公司信息
|
||||
|
||||
在两个页面的页脚部分,可以修改:
|
||||
- 版权信息
|
||||
- 联系方式(电话、邮箱)
|
||||
- 公司地址
|
||||
|
||||
### 添加更多帮助文档
|
||||
|
||||
编辑 `help/index.vue` 中的数据:
|
||||
|
||||
```typescript
|
||||
// 添加 FAQ
|
||||
const faqs = ref([
|
||||
{
|
||||
question: '您的问题',
|
||||
answer: '您的答案',
|
||||
category: '分类'
|
||||
}
|
||||
])
|
||||
|
||||
// 添加使用指南
|
||||
const guides = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '指南标题',
|
||||
description: '描述',
|
||||
icon: '图标',
|
||||
category: '分类',
|
||||
categoryName: '分类名称',
|
||||
updatedAt: '更新日期'
|
||||
}
|
||||
])
|
||||
```
|
||||
|
||||
### 修改配色方案
|
||||
|
||||
页面使用了 Arco Design 的设计令牌(Design Tokens),可以通过修改主题变量来调整配色:
|
||||
|
||||
```less
|
||||
// 主要颜色
|
||||
rgb(var(--primary-6)) // 主色调
|
||||
rgb(var(--success-6)) // 成功色
|
||||
rgb(var(--warning-6)) // 警告色
|
||||
```
|
||||
|
||||
## 登录页面优化
|
||||
|
||||
在登录页面右上角添加了"访问官网首页"按钮,方便用户在登录前了解系统功能。
|
||||
|
||||
## 下一步建议
|
||||
|
||||
1. **添加真实数据** - 将演示数据替换为实际的帮助文档
|
||||
2. **集成客服系统** - 接入第三方在线客服工具
|
||||
3. **添加视频教学** - 在帮助中心增加视频教程
|
||||
4. **SEO 优化** - 添加 meta 标签、title 等 SEO 元素
|
||||
5. **多语言支持** - 如果需要,可以添加国际化支持
|
||||
6. **访问统计** - 集成网站分析工具(如百度统计、Google Analytics)
|
||||
|
||||
## 运行项目
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 启动开发服务器
|
||||
pnpm dev
|
||||
|
||||
# 构建生产版本
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## 浏览器兼容性
|
||||
|
||||
- ✅ Chrome (推荐)
|
||||
- ✅ Firefox
|
||||
- ✅ Edge
|
||||
- ✅ Safari
|
||||
- ⚠️ IE11(需要额外 polyfill)
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 确保 logo 文件路径正确(`@/assets/logo.svg`)
|
||||
2. 如果部署在子目录,需要调整路由的 base 配置
|
||||
3. 如需启用 SSR 或 SEO,建议使用 Vue Router 的 history 模式
|
||||
4. 生产环境部署时,确保服务器正确处理 hash 路由
|
||||
|
||||
---
|
||||
|
||||
如有任何问题或需要进一步的技术支持,请联系开发团队。
|
||||
@@ -1,86 +0,0 @@
|
||||
# 快速启动指南
|
||||
|
||||
## 🎉 新增功能
|
||||
|
||||
已成功为您的智能运维管理系统添加了两个全新的对外页面:
|
||||
|
||||
### ✅ 已完成的工作
|
||||
|
||||
1. **官网首页** (`/#/home`)
|
||||
- 现代化的 UI 设计
|
||||
- 功能特性展示(6 个核心功能)
|
||||
- 数据中心关键指标
|
||||
- 响应式布局
|
||||
|
||||
2. **帮助中心** (`/#/help`)
|
||||
- 常见问题 FAQ
|
||||
- 使用指南分类
|
||||
- 操作手册下载
|
||||
- 联系方式展示
|
||||
|
||||
3. **登录页面优化**
|
||||
- 添加"访问官网首页"按钮
|
||||
|
||||
4. **路由配置**
|
||||
- 无需登录即可访问
|
||||
- 独立布局(无侧边栏)
|
||||
- 根路径自动重定向到首页
|
||||
|
||||
## 🚀 立即查看效果
|
||||
|
||||
### 方式一:直接访问 URL
|
||||
|
||||
在浏览器中访问:
|
||||
```
|
||||
http://localhost:5173/#/home
|
||||
http://localhost:5173/#/help
|
||||
```
|
||||
|
||||
### 方式二:从登录页跳转
|
||||
|
||||
访问登录页面,点击右上角的"首页"图标即可跳转到官网首页。
|
||||
|
||||
## 📝 下一步自定义建议
|
||||
|
||||
### 1. 修改 Logo
|
||||
|
||||
替换 `src/assets/logo.svg` 文件为您公司的 logo
|
||||
|
||||
### 2. 更新联系信息
|
||||
|
||||
编辑以下文件中的联系方式:
|
||||
- `src/views/home/index.vue` - 页脚联系方式
|
||||
- `src/views/help/index.vue` - 联系我们板块
|
||||
|
||||
### 3. 添加真实的帮助文档
|
||||
|
||||
编辑 `src/views/help/index.vue` 中的:
|
||||
```typescript
|
||||
const faqs = ref([...]) // 常见问题
|
||||
const guides = ref([...]) // 使用指南
|
||||
const manuals = ref([...]) // 操作手册
|
||||
```
|
||||
|
||||
### 4. 调整配色方案
|
||||
|
||||
页面使用了 Arco Design 主题色,可以通过 CSS 变量调整:
|
||||
```less
|
||||
rgb(var(--primary-6)) // 主色调
|
||||
```
|
||||
|
||||
## 💡 提示
|
||||
|
||||
- 所有页面都已经适配移动端,可以在手机上查看效果
|
||||
- 页面使用了 Vue Router 的 hash 模式,部署简单
|
||||
- 无需后端支持,纯静态页面,可直接部署
|
||||
|
||||
## 📦 技术栈
|
||||
|
||||
- Vue 3 + TypeScript
|
||||
- Arco Design 组件库
|
||||
- Vite 构建工具
|
||||
- Vue Router 路由管理
|
||||
|
||||
---
|
||||
|
||||
享受您的新页面!🎊
|
||||
47
README.md
@@ -0,0 +1,47 @@
|
||||
# Front - OPS 前端
|
||||
|
||||
`front` 是 OPS 平台的统一前端入口,基于 Vue 3、Vite、Arco Design Vue、Pinia 和 Vue Router。页面以动态菜单为主,RBAC 菜单接口不可用时使用本地菜单数据兜底。
|
||||
|
||||
## 当前代码入口
|
||||
|
||||
| 类型 | 路径 |
|
||||
| --- | --- |
|
||||
| 应用入口 | `front/src/main.ts` |
|
||||
| 路由入口 | `front/src/router/index.ts` |
|
||||
| 静态路由 | `front/src/router/routes/modules/` |
|
||||
| 动态菜单转换 | `front/src/router/menu-data.ts` |
|
||||
| 本地菜单兜底 | `front/src/router/local-menu-items.ts`、`front/src/router/local-menu-flat.ts` |
|
||||
| 页面目录 | `front/src/views/` |
|
||||
| API 模块 | `front/src/api/module/` |
|
||||
| 构建配置 | `front/config/` |
|
||||
|
||||
## 主要页面域
|
||||
|
||||
| 页面域 | 目录 |
|
||||
| --- | --- |
|
||||
| 首页与概览 | `front/src/views/home`、`front/src/views/ops/pages/overview` |
|
||||
| 数据中心与资源 | `front/src/views/ops/pages/dc`、`datacenter`、`resource-context` |
|
||||
| 告警与治理 | `front/src/views/ops/pages/alert`、`governance` |
|
||||
| 工单闭环 | `front/src/views/ops/pages/feedback` |
|
||||
| 知识库 | `front/src/views/ops/pages/kb` |
|
||||
| 报表与自动化 | `front/src/views/ops/pages/report`、`automation` |
|
||||
| 业务系统与拓扑 | `front/src/views/ops/pages/business-system`、`business-topology` |
|
||||
| 大屏 | `front/src/views/ops/pages/big-screen`、`front/src/views/visualization` |
|
||||
| 日志管理 | `front/src/views/ops/pages/log-mgmt` |
|
||||
| 系统设置 | `front/src/views/ops/pages/system-settings` |
|
||||
|
||||
## 常用命令
|
||||
|
||||
```powershell
|
||||
cd D:\work\ops\front
|
||||
pnpm.cmd install
|
||||
pnpm.cmd dev
|
||||
pnpm.cmd build
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- `front/PAGES_README.md`:页面清单和路由说明。
|
||||
- `front/QUICK_START.md`:本地启动说明。
|
||||
- `front/docs/`:页面设计、适配验收和部分接口对接文档。
|
||||
- `docs/模块文档索引.md`:全工作区模块边界与文档入口。
|
||||
|
||||
376
asset-source-address-frontend-integration.md
Normal file
@@ -0,0 +1,376 @@
|
||||
# 资产设备源地址前端对接文档
|
||||
|
||||
## 1. 变更说明
|
||||
|
||||
设备资产新增可选字段 `source_address`,界面名称为“源地址”。该字段适用于所有设备分类,可用于保存 RTSP、HTTP、HTTPS、HLS 等形式的播放源地址。
|
||||
|
||||
| 属性 | 内容 |
|
||||
| --- | --- |
|
||||
| JSON 字段 | `source_address` |
|
||||
| TypeScript 类型 | `string` |
|
||||
| 是否必填 | 否 |
|
||||
| 最大长度 | 1000 个字符 |
|
||||
| 协议限制 | 无 |
|
||||
| 数据库字段 | `assets_assets.source_address` |
|
||||
| 数据库类型 | `varchar(1000)` |
|
||||
|
||||
前端不需要根据设备分类判断是否展示该字段。
|
||||
|
||||
## 2. 接口公共约定
|
||||
|
||||
资产接口基础路径:
|
||||
|
||||
```text
|
||||
/Assets/v1/asset
|
||||
```
|
||||
|
||||
请求头:
|
||||
|
||||
```http
|
||||
Authorization: Bearer <token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
统一响应结构:
|
||||
|
||||
```ts
|
||||
interface ApiResponse<T> {
|
||||
code: number
|
||||
message: string
|
||||
details: T
|
||||
timeseq: number
|
||||
}
|
||||
```
|
||||
|
||||
`code === 0` 表示请求成功,业务数据位于 `details`。
|
||||
|
||||
## 3. 前端类型
|
||||
|
||||
在资产表单类型中增加 `source_address`:
|
||||
|
||||
```ts
|
||||
export interface AssetForm {
|
||||
id?: number
|
||||
asset_name: string
|
||||
asset_code: string
|
||||
source_address?: string
|
||||
}
|
||||
```
|
||||
|
||||
当前项目已经在 `src/api/ops/asset.ts` 的 `AssetForm` 中加入该字段。其他以资产对象为基础的详情、列表和批量导入数据可以直接复用该字段。
|
||||
|
||||
## 4. 创建设备资产
|
||||
|
||||
### 4.1 接口
|
||||
|
||||
```http
|
||||
POST /Assets/v1/asset/create
|
||||
```
|
||||
|
||||
### 4.2 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"asset_name": "东门监控摄像头",
|
||||
"asset_code": "CAMERA-001",
|
||||
"category_id": 12,
|
||||
"model": "DS-2CD3T",
|
||||
"manufacturer": "海康威视",
|
||||
"serial_number": "SN20260817001",
|
||||
"source_address": "rtsp://192.168.1.100:554/Streaming/Channels/101",
|
||||
"status": "in_use"
|
||||
}
|
||||
```
|
||||
|
||||
未填写源地址时可以省略 `source_address`,也可以传空字符串:
|
||||
|
||||
```json
|
||||
{
|
||||
"asset_name": "普通设备",
|
||||
"asset_code": "DEVICE-001",
|
||||
"source_address": ""
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 成功响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"details": {
|
||||
"id": 101,
|
||||
"asset_name": "东门监控摄像头",
|
||||
"asset_code": "CAMERA-001",
|
||||
"source_address": "rtsp://192.168.1.100:554/Streaming/Channels/101",
|
||||
"status": "in_use"
|
||||
},
|
||||
"timeseq": 1786932000000
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 调用方式
|
||||
|
||||
```ts
|
||||
import { createAsset, type AssetForm } from '@/api/ops/asset'
|
||||
|
||||
const data: AssetForm = {
|
||||
asset_name: '东门监控摄像头',
|
||||
asset_code: 'CAMERA-001',
|
||||
source_address: 'rtsp://192.168.1.100:554/Streaming/Channels/101',
|
||||
status: 'in_use',
|
||||
}
|
||||
|
||||
const response = await createAsset(data)
|
||||
if (response.code !== 0) {
|
||||
throw new Error(response.message || '创建设备失败')
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 更新设备资产
|
||||
|
||||
### 5.1 接口
|
||||
|
||||
```http
|
||||
PUT /Assets/v1/asset/update
|
||||
```
|
||||
|
||||
### 5.2 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 101,
|
||||
"asset_name": "东门监控摄像头",
|
||||
"asset_code": "CAMERA-001",
|
||||
"source_address": "https://video.example.com/live/camera-001.m3u8",
|
||||
"status": "in_use"
|
||||
}
|
||||
```
|
||||
|
||||
更新接口需要同时传入:
|
||||
|
||||
- `id`
|
||||
- `asset_name`
|
||||
- `asset_code`
|
||||
|
||||
`source_address` 仍为选填字段。传入非空值时更新源地址;不传时保留原值。
|
||||
|
||||
当前后端使用 GORM 结构体更新,空字符串属于零值,因此传入 `source_address: ""` 不会清空已有源地址。前端暂时不要把“传空字符串”作为清空操作。
|
||||
|
||||
### 5.3 调用方式
|
||||
|
||||
```ts
|
||||
import { updateAsset, type AssetForm } from '@/api/ops/asset'
|
||||
|
||||
const data: AssetForm = {
|
||||
id: 101,
|
||||
asset_name: '东门监控摄像头',
|
||||
asset_code: 'CAMERA-001',
|
||||
source_address: 'https://video.example.com/live/camera-001.m3u8',
|
||||
status: 'in_use',
|
||||
}
|
||||
|
||||
const response = await updateAsset(data)
|
||||
if (response.code !== 0) {
|
||||
throw new Error(response.message || '更新设备失败')
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 查询设备详情
|
||||
|
||||
### 6.1 接口
|
||||
|
||||
```http
|
||||
GET /Assets/v1/asset/detail/{id}
|
||||
```
|
||||
|
||||
### 6.2 成功响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"details": {
|
||||
"id": 101,
|
||||
"asset_name": "东门监控摄像头",
|
||||
"asset_code": "CAMERA-001",
|
||||
"source_address": "rtsp://192.168.1.100:554/Streaming/Channels/101",
|
||||
"status": "in_use"
|
||||
},
|
||||
"timeseq": 1786932000000
|
||||
}
|
||||
```
|
||||
|
||||
未填写源地址时,`source_address` 返回空字符串。
|
||||
|
||||
### 6.3 表单回填
|
||||
|
||||
当前编辑页面使用详情对象整体回填:
|
||||
|
||||
```ts
|
||||
const response = await fetchAssetDetail(deviceId)
|
||||
if (response.code === 0) {
|
||||
form.value = { ...response.details } as AssetForm
|
||||
}
|
||||
```
|
||||
|
||||
`source_address` 会随其他资产字段自动回填,不需要单独请求。
|
||||
|
||||
## 7. 分页查询设备资产
|
||||
|
||||
### 7.1 接口
|
||||
|
||||
```http
|
||||
POST /Assets/v1/asset/list
|
||||
```
|
||||
|
||||
### 7.2 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"page": 1,
|
||||
"page_size": 20,
|
||||
"keyword": "",
|
||||
"status": "in_use"
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "",
|
||||
"details": {
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 20,
|
||||
"data": [
|
||||
{
|
||||
"id": 101,
|
||||
"asset_name": "东门监控摄像头",
|
||||
"asset_code": "CAMERA-001",
|
||||
"source_address": "rtsp://192.168.1.100:554/Streaming/Channels/101"
|
||||
}
|
||||
]
|
||||
},
|
||||
"timeseq": 1786932000000
|
||||
}
|
||||
```
|
||||
|
||||
以下接口返回的资产对象同样包含 `source_address`:
|
||||
|
||||
```http
|
||||
GET /Assets/v1/asset/page
|
||||
GET /Assets/v1/asset/all
|
||||
GET /Assets/v1/asset/export
|
||||
```
|
||||
|
||||
## 8. 批量导入
|
||||
|
||||
### 8.1 接口
|
||||
|
||||
```http
|
||||
POST /Assets/v1/asset/bulk_import
|
||||
```
|
||||
|
||||
### 8.2 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"dry_run": false,
|
||||
"items": [
|
||||
{
|
||||
"asset_name": "西门监控摄像头",
|
||||
"asset_code": "CAMERA-002",
|
||||
"source_address": "rtsp://192.168.1.101:554/live",
|
||||
"status": "in_use"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
每个 `items` 元素都可以单独填写或省略 `source_address`。
|
||||
|
||||
## 9. 表单接入
|
||||
|
||||
### 9.1 默认值
|
||||
|
||||
```ts
|
||||
const form = ref<AssetForm>({
|
||||
asset_name: '',
|
||||
asset_code: '',
|
||||
source_address: '',
|
||||
})
|
||||
```
|
||||
|
||||
### 9.2 表单组件
|
||||
|
||||
```vue
|
||||
<a-form-item label="源地址" field="source_address">
|
||||
<a-input
|
||||
v-model="form.source_address"
|
||||
placeholder="请输入源地址"
|
||||
:max-length="1000"
|
||||
allow-clear
|
||||
/>
|
||||
</a-form-item>
|
||||
```
|
||||
|
||||
该字段不设置 `required` 规则,也不校验具体协议格式。
|
||||
|
||||
### 9.3 提交
|
||||
|
||||
新增和编辑直接复用现有资产提交逻辑:
|
||||
|
||||
```ts
|
||||
const data = { ...form.value }
|
||||
|
||||
if (isEdit.value && deviceId.value) {
|
||||
await updateAsset({ ...data, id: deviceId.value })
|
||||
} else {
|
||||
await createAsset(data)
|
||||
}
|
||||
```
|
||||
|
||||
## 10. 详情展示
|
||||
|
||||
```vue
|
||||
<a-descriptions-item label="源地址" :span="2">
|
||||
<span class="source-address">{{ device?.source_address || '-' }}</span>
|
||||
</a-descriptions-item>
|
||||
```
|
||||
|
||||
长地址需要允许换行:
|
||||
|
||||
```css
|
||||
.source-address {
|
||||
word-break: break-all;
|
||||
}
|
||||
```
|
||||
|
||||
## 11. 播放功能使用建议
|
||||
|
||||
获取播放地址时直接读取资产对象的 `source_address`:
|
||||
|
||||
```ts
|
||||
const sourceAddress = record.source_address?.trim()
|
||||
|
||||
if (!sourceAddress) {
|
||||
Message.warning('该设备未配置源地址')
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
前端不要自动补全协议、转换大小写或修改地址内容。具体播放器需要支持对应的流媒体协议,例如浏览器不能直接原生播放 RTSP 地址。
|
||||
|
||||
## 12. 对接检查项
|
||||
|
||||
- 新增设备时可以不填写源地址。
|
||||
- 新增设备时填写源地址后可以正常保存。
|
||||
- 编辑设备时能够正确回填源地址。
|
||||
- 编辑设备时修改源地址后可以正常保存。
|
||||
- 详情接口和详情弹窗能够显示源地址。
|
||||
- 列表接口返回的每条资产数据包含 `source_address`。
|
||||
- 超长地址能够在详情区域正常换行。
|
||||
- 接口失败时优先显示响应中的 `message`。
|
||||
@@ -1,24 +1,132 @@
|
||||
import { mergeConfig } from 'vite'
|
||||
import type { IncomingMessage } from 'node:http'
|
||||
import { loadEnv, mergeConfig, type ConfigEnv, type ProxyOptions } from 'vite'
|
||||
// import eslint from 'vite-plugin-eslint'
|
||||
import baseConfig from './vite.config.base'
|
||||
|
||||
export default mergeConfig(
|
||||
{
|
||||
mode: 'development',
|
||||
server: {
|
||||
open: true,
|
||||
host: '0.0.0.0',
|
||||
fs: {
|
||||
strict: true,
|
||||
},
|
||||
const HIKVISION_PROXY_TIMEOUT = 8000
|
||||
|
||||
const proxyTarget = (port: number) => ({
|
||||
target: `http://127.0.0.1:${port}`,
|
||||
changeOrigin: true,
|
||||
})
|
||||
|
||||
/** 读取海康 WebSDK 写入的代理目标 Cookie。 */
|
||||
function getProxyCookie(request: IncomingMessage, name: string): string {
|
||||
const cookie = request.headers.cookie || ''
|
||||
const matched = cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]+)`))
|
||||
if (!matched) return ''
|
||||
try {
|
||||
return decodeURIComponent(matched[1])
|
||||
} catch (_error) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/** 从 SDK Cookie 解析 WebSocket 端口,并限制只能代理到已配置的录像机。 */
|
||||
function resolveHikvisionWebSocketTarget(request: IncomingMessage, allowedHost: string, fallbackTarget: string): string {
|
||||
const secureAddress = getProxyCookie(request, 'webVideoCtrlProxyWss')
|
||||
const address = secureAddress || getProxyCookie(request, 'webVideoCtrlProxyWs')
|
||||
if (!address) return fallbackTarget
|
||||
try {
|
||||
const target = new URL(`${secureAddress ? 'wss' : 'ws'}://${address}`)
|
||||
return target.hostname.toLowerCase() === allowedHost.toLowerCase() ? target.toString() : fallbackTarget
|
||||
} catch (_error) {
|
||||
return fallbackTarget
|
||||
}
|
||||
}
|
||||
|
||||
/** 创建开发环境 Vite 配置。 */
|
||||
export default ({ mode }: ConfigEnv) => {
|
||||
const env = loadEnv(mode, process.cwd(), '')
|
||||
const apiProxyTarget = env.VITE_API_PROXY_TARGET || 'https://ops-api.apinb.com'
|
||||
const proxy: Record<string, ProxyOptions> = {
|
||||
'/api': {
|
||||
target: apiProxyTarget,
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
},
|
||||
plugins: [
|
||||
// eslint({
|
||||
// cache: false,
|
||||
// include: ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.vue'],
|
||||
// exclude: ['node_modules'],
|
||||
// }),
|
||||
],
|
||||
},
|
||||
baseConfig
|
||||
)
|
||||
'/rbac2': proxyTarget(10001),
|
||||
'/Alert': proxyTarget(12427),
|
||||
'/alert': proxyTarget(12427),
|
||||
'/DC-Control': proxyTarget(3031),
|
||||
'/dc-control': proxyTarget(3031),
|
||||
'/dc-network': proxyTarget(12429),
|
||||
'/DC-Hardware': proxyTarget(12450),
|
||||
'/dc-hardware': proxyTarget(12450),
|
||||
'/dc-host': proxyTarget(9030),
|
||||
'/dc-middleware': proxyTarget(12428),
|
||||
'/dc-database': proxyTarget(12580),
|
||||
'/Feedback': proxyTarget(12432),
|
||||
'/feedback': proxyTarget(12432),
|
||||
'/Assets': proxyTarget(12430),
|
||||
'/assets': proxyTarget(12430),
|
||||
'/Logs': proxyTarget(12440),
|
||||
'/logs': proxyTarget(12440),
|
||||
'/Kb': proxyTarget(12434),
|
||||
'/kb': proxyTarget(12434),
|
||||
'/Mgt': proxyTarget(12436),
|
||||
'/mgt': proxyTarget(12436),
|
||||
'/Visual': proxyTarget(12438),
|
||||
'/visual': proxyTarget(12438),
|
||||
}
|
||||
|
||||
if (env.VITE_HIKVISION_PROXY_TARGET) {
|
||||
const hikvisionHttpTarget = new URL(env.VITE_HIKVISION_PROXY_TARGET)
|
||||
const hikvisionWebSocketTarget =
|
||||
env.VITE_HIKVISION_WS_PROXY_TARGET || `${hikvisionHttpTarget.protocol === 'https:' ? 'wss' : 'ws'}://${hikvisionHttpTarget.host}`
|
||||
proxy['/ISAPI'] = {
|
||||
target: env.VITE_HIKVISION_PROXY_TARGET,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
timeout: HIKVISION_PROXY_TIMEOUT,
|
||||
proxyTimeout: HIKVISION_PROXY_TIMEOUT,
|
||||
}
|
||||
proxy['/SDK'] = {
|
||||
target: env.VITE_HIKVISION_PROXY_TARGET,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
timeout: HIKVISION_PROXY_TIMEOUT,
|
||||
proxyTimeout: HIKVISION_PROXY_TIMEOUT,
|
||||
}
|
||||
proxy['/webSocketVideoCtrlProxy'] = {
|
||||
target: hikvisionWebSocketTarget,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
ws: true,
|
||||
timeout: HIKVISION_PROXY_TIMEOUT,
|
||||
proxyTimeout: HIKVISION_PROXY_TIMEOUT,
|
||||
router: env.VITE_HIKVISION_WS_PROXY_TARGET
|
||||
? undefined
|
||||
: (request) => resolveHikvisionWebSocketTarget(request, hikvisionHttpTarget.hostname, hikvisionWebSocketTarget),
|
||||
rewrite: (path) => path.replace(/^\/webSocketVideoCtrlProxy/, '/'),
|
||||
}
|
||||
}
|
||||
|
||||
return mergeConfig(
|
||||
{
|
||||
mode: 'development',
|
||||
server: {
|
||||
open: true,
|
||||
host: '0.0.0.0',
|
||||
headers: {
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Resource-Policy': 'cross-origin',
|
||||
},
|
||||
fs: {
|
||||
strict: true,
|
||||
},
|
||||
proxy,
|
||||
},
|
||||
plugins: [
|
||||
// eslint({
|
||||
// cache: false,
|
||||
// include: ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.vue'],
|
||||
// exclude: ['node_modules'],
|
||||
// }),
|
||||
],
|
||||
},
|
||||
baseConfig
|
||||
)
|
||||
}
|
||||
|
||||
24
dev/components.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// biome-ignore lint: disable
|
||||
// oxlint-disable
|
||||
// ------
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import { GlobalComponents } from 'vue'
|
||||
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
}
|
||||
|
||||
// For TSX support
|
||||
declare global {
|
||||
const RouterLink: typeof import('vue-router')['RouterLink']
|
||||
const RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="https://unpkg.byted-static.com/latest/byted/arco-config/assets/favicon.ico" />
|
||||
<link rel="icon" type="image/svg+xml" href="%BASE_URL%favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>智能运维管理系统</title>
|
||||
</head>
|
||||
|
||||
15673
package-lock.json
generated
Normal file
@@ -19,6 +19,7 @@
|
||||
"dependencies": {
|
||||
"@arco-design/web-vue": "^2.57.0",
|
||||
"@tabler/icons-vue": "^3.40.0",
|
||||
"@tweenjs/tween.js": "18.6.0",
|
||||
"@vue-flow/background": "^1.3.2",
|
||||
"@vue-flow/controls": "^1.1.3",
|
||||
"@vue-flow/core": "^1.48.2",
|
||||
@@ -33,6 +34,7 @@
|
||||
"pinia": "^3.0.4",
|
||||
"query-string": "^9.3.1",
|
||||
"sortablejs": "^1.15.7",
|
||||
"three": "0.115.0",
|
||||
"uuid": "^13.0.0",
|
||||
"vue": "^3.5.29",
|
||||
"vue-echarts": "^8.0.1",
|
||||
@@ -72,7 +74,6 @@
|
||||
"rollup": "^4.59.0",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"stylelint": "^17.4.0",
|
||||
"stylelint-config-prettier": "^9.0.5",
|
||||
"stylelint-config-rational-order": "^0.1.2",
|
||||
"stylelint-config-recommended-vue": "^1.6.1",
|
||||
"stylelint-config-standard": "^40.0.0",
|
||||
|
||||
3351
pnpm-lock.yaml
generated
5
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
allowBuilds:
|
||||
esbuild: true
|
||||
less: true
|
||||
unrs-resolver: true
|
||||
vue-demi: true
|
||||
4
public/favicon.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="33" height="33">
|
||||
<path d="M0 240.941176a240.941176 240.941176 0 0 1 240.941176-240.941176h542.117648a240.941176 240.941176 0 0 1 240.941176 240.941176v542.117648a240.941176 240.941176 0 0 1-240.941176 240.941176H240.941176a240.941176 240.941176 0 0 1-240.941176-240.941176V240.941176z" fill="#287BF7"></path>
|
||||
<path d="M340.931765 388.969412a120.621176 120.621176 0 1 0 115.260235 209.799529l70.776471 97.490824a241.091765 241.091765 0 1 1 82.522353-283.587765c15.751529 39.936 14.516706 83.546353 13.763764 110.290824-0.150588 4.879059-0.271059 9.216-0.271059 12.860235 0 22.648471 5.812706 48.519529 18.221177 66.831059 10.24 15.058824 26.654118 28.310588 61.108706 28.310588 31.804235 0 49.152-10.721882 59.331764-22.40753 11.264-12.950588 18.974118-33.370353 18.974118-59.452235 0-18.642824-9.396706-39.574588-27.166118-53.067294-16.022588-12.137412-43.550118-21.594353-86.768941-8.734118l-34.42447-115.440941c75.926588-22.618353 144.112941-9.637647 193.987764 28.190118 48.128 36.502588 74.842353 93.093647 74.842353 149.082353 0 48.489412-14.245647 99.087059-48.609882 138.541176-35.418353 40.719059-87.341176 63.728941-150.166588 63.728941-75.294118 0-128.662588-33.792-160.768-81.106823-29.936941-44.062118-39.032471-95.864471-39.032471-134.475294 0-9.396706 0.150588-17.588706 0.240941-24.847059 0.421647-25.057882 0.632471-38.972235-5.330823-54.091294a120.621176 120.621176 0 0 0-156.491294-67.915294z" fill="#FFFFFF"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/three-machine-room/images/server1.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/three-machine-room/images/server2.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
public/three-machine-room/rack/homebg.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.9 MiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 469 KiB |
|
After Width: | Height: | Size: 276 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 285 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 586 KiB |
|
After Width: | Height: | Size: 612 KiB |
BIN
public/three-machine-room/rack/qd/maps/Map__106_Noise.tga
Normal file
BIN
public/three-machine-room/rack/qd/maps/Map__107_Noise.tga
Normal file
BIN
public/three-machine-room/rack/qd/maps/Map__19_Falloff.tga
Normal file
BIN
public/three-machine-room/rack/qd/maps/Map__1_颜色校正.tga
Normal file
BIN
public/three-machine-room/rack/qd/maps/Map__614327418_VR-贴图.tga
Normal file
BIN
public/three-machine-room/rack/qd/maps/t1.jpg
Normal file
|
After Width: | Height: | Size: 766 KiB |
BIN
public/three-machine-room/rack/qd/maps/t2.jpg
Normal file
|
After Width: | Height: | Size: 603 KiB |
BIN
public/three-machine-room/rack/qd/maps/t3.jpg
Normal file
|
After Width: | Height: | Size: 840 KiB |
BIN
public/three-machine-room/rack/qd/maps/t5.jpg
Normal file
|
After Width: | Height: | Size: 451 KiB |
BIN
public/three-machine-room/rack/qd/maps/t7.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
public/three-machine-room/rack/qd/maps/贴图__123_Noise.tga
Normal file
962
public/three-machine-room/rack/qd/quding.mtl
Normal file
@@ -0,0 +1,962 @@
|
||||
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
|
||||
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>:04.08.2026 13:21:15
|
||||
|
||||
newmtl Mat3d66_10994759_12_33214
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.3686 0.3686 0.3686
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_10994759_11_76789
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 1.0000 1.0000 1.0000
|
||||
Kd 1.0000 1.0000 1.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\Map__107_Noise.tga
|
||||
map_Kd maps\Map__107_Noise.tga
|
||||
map_bump -bm 0.2000 maps\Map__106_Noise.tga
|
||||
|
||||
newmtl Mat3d66_10994759_30_54055
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.6667 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66_17938251_color_VR-<2D><>ɫ.tga
|
||||
map_Kd maps\3d66_17938251_color_VR-<2D><>ɫ.tga
|
||||
map_bump -bm 0.0500 maps\3d66_17938251_color_VR-<2D><>ɫ.tga
|
||||
|
||||
newmtl Mat3d66_11807706_26_30152
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0196 0.0196 0.0196
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_bump maps\3d66Model-11807706-files-51.png
|
||||
bump maps\3d66Model-11807706-files-51.png
|
||||
|
||||
newmtl Mat3d66_10994759_29_37910
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.6078 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_10994759_22_2dad4012
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.1373 0.1373 0.1373
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_10994759_34_15870
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.6392 0.6392 0.6392
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Model-10994759-files-1.jpg
|
||||
map_Kd maps\3d66Model-10994759-files-1.jpg
|
||||
|
||||
newmtl Mat3d66_10994759_22_24012
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0039 0.0039 0.0039
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_10994759_37_59834
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl wire_198225087
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.7765 0.8824 0.3412
|
||||
Kd 0.7765 0.8824 0.3412
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
|
||||
newmtl Mat3d66_10994759_35_21635
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0588 0.0588 0.0588
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl wire_115115115
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.4510 0.4510 0.4510
|
||||
Kd 0.4510 0.4510 0.4510
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
|
||||
newmtl Mat3d66_10994759_25_25429
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.8549 0.9098 0.9412
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Model-10994759-files-13.jpg
|
||||
map_Kd maps\3d66Model-10994759-files-13.jpg
|
||||
map_bump maps\3d66Model-10994759-files-13.jpg
|
||||
bump maps\3d66Model-10994759-files-13.jpg
|
||||
|
||||
newmtl wire_000000000
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.0000 0.0000 0.0000
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
|
||||
newmtl 3d66_VRayMtl_23563919_021
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.7529 0.7647 0.7294
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_23563919_022
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5961 0.6039 0.5765
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_23563919_018
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.6314 0.0392 0.0392
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_23563919_019
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_23563919_020
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0275 0.0275 0.0275
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl <20><>ҵ<EFBFBD><D2B5><EFBFBD>Ұ<EFBFBD>ɫ<EFBFBD>߹<EFBFBD><DFB9>⻬<EFBFBD><E2BBAC>ƺ<EFBFBD><C6BA>_Ϳ<5F><CDBF>_VR
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.3922 0.3922 0.3922
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Mat-14871359-maps-3.jpg
|
||||
map_Kd maps\3d66Mat-14871359-maps-3.jpg
|
||||
map_bump -bm 0.0150 maps\<5C><>ͼ__123_Noise.tga
|
||||
|
||||
newmtl <20>ִ<EFBFBD><D6B4><EFBFBD>ɫ<EFBFBD>ƹ<EFBFBD><C6B9>⻬<EFBFBD><E2BBAC><EFBFBD><EFBFBD>_<EFBFBD><5F>_VR
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0196 0.0196 0.0196
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_11807706_4_39763
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0196 0.0196 0.0196
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_11807706_5_89594
|
||||
Ns 41.0000
|
||||
Ni 1.5000
|
||||
d 0.8000
|
||||
Tr 0.2000
|
||||
Tf 0.8000 0.8000 0.8000
|
||||
illum 2
|
||||
Ka 0.9725 0.0000 0.0000
|
||||
Kd 0.9725 0.0000 0.0000
|
||||
Ks 0.3960 0.3960 0.3960
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl wire_225198087
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.8824 0.7765 0.3412
|
||||
Kd 0.8824 0.7765 0.3412
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
|
||||
newmtl Mat3d66_11807706_7_95731
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5333 0.5294 0.5255
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_11807706_8_21117
|
||||
Ns 76.0000
|
||||
Ni 1.5000
|
||||
d 0.4000
|
||||
Tr 0.6000
|
||||
Tf 0.4000 0.4000 0.4000
|
||||
illum 2
|
||||
Ka 0.1608 0.1569 0.1843
|
||||
Kd 0.1608 0.1569 0.1843
|
||||
Ks 0.7920 0.7920 0.7920
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_refl maps\Map__614327418_VR-<2D><>ͼ.tga
|
||||
|
||||
newmtl Mat3d66_11807706_9_83349
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0863 0.0745 0.0667
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_11807706_10_61673
|
||||
Ns 76.0000
|
||||
Ni 1.5000
|
||||
d 0.0500
|
||||
Tr 0.9500
|
||||
Tf 0.0500 0.0500 0.0500
|
||||
illum 2
|
||||
Ka 0.1608 0.1569 0.1843
|
||||
Kd 0.1608 0.1569 0.1843
|
||||
Ks 0.7920 0.7920 0.7920
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_refl maps\Map__614327418_VR-<2D><>ͼ.tga
|
||||
|
||||
newmtl Mat3d66_11807706_11_67368
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0863 0.0745 0.0667
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Model-11807706-files-3.jpg
|
||||
map_Kd maps\3d66Model-11807706-files-3.jpg
|
||||
|
||||
newmtl 22___Default
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0039 0.0039 0.0039
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_11807706_29_27585
|
||||
Ns 38.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5882 0.5882 0.5882
|
||||
Kd 0.5882 0.5882 0.5882
|
||||
Ks 0.1800 0.1800 0.1800
|
||||
Ke 0.0706 0.0706 0.0706
|
||||
map_Ka maps\3d66Model-11807706-files-60.jpg
|
||||
map_Kd maps\3d66Model-11807706-files-60.jpg
|
||||
map_bump maps\3d66Model-11807706-files-60.jpg
|
||||
bump maps\3d66Model-11807706-files-60.jpg
|
||||
|
||||
newmtl Mat3d66_11807706_120_47020
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\Map__1_<31><5F>ɫУ<C9AB><D0A3>.tga
|
||||
map_Kd maps\Map__1_<31><5F>ɫУ<C9AB><D0A3>.tga
|
||||
map_bump maps\Map__1_<31><5F>ɫУ<C9AB><D0A3>.tga
|
||||
|
||||
newmtl wire_010140195
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.0392 0.5490 0.7647
|
||||
Kd 0.0392 0.5490 0.7647
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
|
||||
newmtl Mat3d66_11807706_28_26251
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.8941 0.8941 0.8941
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_15185da96_31_5088
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0275 0.0275 0.0235
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_10994759_49_69999
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.1373 0.1373 0.1373
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_10994759_31_26985
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0392 0.0392 0.0392
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_bump maps\3d66Model-10994759-files-15.JPG
|
||||
bump maps\3d66Model-10994759-files-15.JPG
|
||||
|
||||
newmtl 24___Default
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\t7.jpg
|
||||
map_Kd maps\t7.jpg
|
||||
|
||||
newmtl 3d66_VRayMtl_20092954_028
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.9216 0.9216 0.9216
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_20092954_034
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.1176 0.1176 0.1176
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_7566050_1_94391
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.9020 0.9020 0.9020
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_1518596_31_5088
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.6471 0.6235 0.6000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_23605226_030
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5882 0.5882 0.5882
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_23605226_031
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Model-23605226-files-005.png
|
||||
map_Kd maps\3d66Model-23605226-files-005.png
|
||||
map_bump maps\3d66_VRayNormalMap_23605226_023_VR-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ.tga
|
||||
|
||||
newmtl Mat3d66_7859414_4_42689
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.3529 0.3529 0.3529
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_7859414_3_41489
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.8627 0.8549 0.8471
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_7859414_7_21754
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.1765 0.1765 0.1765
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_7859414_5_93165
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.8235 0.8196 0.8157
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl wire_135006006
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.5294 0.0235 0.0235
|
||||
Kd 0.5294 0.0235 0.0235
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_046
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_047
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0275 0.0275 0.0275
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_045
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.6314 0.0392 0.0392
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_048
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.7529 0.7647 0.7294
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_049
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5961 0.6039 0.5765
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_052
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0510 0.0510 0.0510
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_069
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 1.0000 1.0000 1.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_070
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.7176 0.7882 0.8510
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_071
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_074
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66_Bricks_22568095_021_Tiles.tga
|
||||
map_Kd maps\3d66_Bricks_22568095_021_Tiles.tga
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_025
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0902 0.0902 0.0902
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_Standardmaterial_22568095_004
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5882 0.5882 0.5882
|
||||
Kd 0.5882 0.5882 0.5882
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 3d66_VRayMtl_22568095_066
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0392 0.0392 0.0392
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl 17___Default
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\t3.jpg
|
||||
map_Kd maps\t3.jpg
|
||||
|
||||
newmtl 18___Default
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\t5.jpg
|
||||
map_Kd maps\t5.jpg
|
||||
|
||||
newmtl 16___Default
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\t2.jpg
|
||||
map_Kd maps\t2.jpg
|
||||
|
||||
newmtl 15___Default
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.5000 0.5000 0.5000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\t1.jpg
|
||||
map_Kd maps\t1.jpg
|
||||
|
||||
newmtl Mat3d66_14662737_11_91260
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 1.0000 1.0000 1.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Model-14662737-files-5.jpg
|
||||
map_Kd maps\3d66Model-14662737-files-5.jpg
|
||||
|
||||
newmtl Mat3d66_14662737_12_48868
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 1.0000 1.0000 1.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Model-14662737-files-5.jpg
|
||||
map_Kd maps\3d66Model-14662737-files-5.jpg
|
||||
|
||||
newmtl wire_154185229
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.6039 0.7255 0.8980
|
||||
Kd 0.6039 0.7255 0.8980
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
|
||||
newmtl Glass
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Mat3d66_8099876_13_28564
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.4667 0.4510 0.4353
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Material__53
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl Material__52
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.1451 0.1451 0.1451
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_Ka maps\3d66Model-8099876-files-4.jpg
|
||||
map_Kd maps\3d66Model-8099876-files-4.jpg
|
||||
|
||||
newmtl Material__109
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.0000 0.0000 0.0000
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl <20><><EFBFBD>ݧ<EFBFBD><DDA7>ާڧߧڧ<DFA7>_<EFBFBD><5F><EFBFBD><EFBFBD><EFBFBD>ݧڧ<DDA7><DAA7><EFBFBD><EFBFBD>ӧѧߧߧ<DFA7><DFA7><EFBFBD>
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.1872 0.1872 0.1872
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl <20><><EFBFBD><EFBFBD><EFBFBD>ݧ<EFBFBD>
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.5880 0.5880 0.5880
|
||||
Kd 0.7529 0.7529 0.7529
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
map_d maps\Map__19_Falloff.tga
|
||||
|
||||
newmtl wire_154215229
|
||||
Ns 32
|
||||
d 1
|
||||
Tr 0
|
||||
Tf 1 1 1
|
||||
illum 2
|
||||
Ka 0.6039 0.8431 0.8980
|
||||
Kd 0.6039 0.8431 0.8980
|
||||
Ks 0.3500 0.3500 0.3500
|
||||
2938085
public/three-machine-room/rack/qd/quding.obj
Normal file
621
public/vendor/hikvision/encryption/AES.js
vendored
Normal file
@@ -0,0 +1,621 @@
|
||||
(function() {
|
||||
var Nr = 10;
|
||||
// convert two-dimensional indicies to one-dim array indices
|
||||
var I00 = 0;
|
||||
var I01 = 1;
|
||||
var I02 = 2;
|
||||
var I03 = 3;
|
||||
var I10 = 4;
|
||||
var I11 = 5;
|
||||
var I12 = 6;
|
||||
var I13 = 7;
|
||||
var I20 = 8;
|
||||
var I21 = 9;
|
||||
var I22 = 10;
|
||||
var I23 = 11;
|
||||
var I30 = 12;
|
||||
var I31 = 13;
|
||||
var I32 = 14;
|
||||
var I33 = 15;
|
||||
|
||||
// S-Box substitution table
|
||||
var S_enc = new Array(
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
|
||||
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
|
||||
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
|
||||
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
|
||||
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
|
||||
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
|
||||
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
|
||||
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
|
||||
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
|
||||
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
|
||||
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
|
||||
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
|
||||
|
||||
// inverse S-Box for decryptions
|
||||
var S_dec = new Array(
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
|
||||
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
|
||||
0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
|
||||
0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
||||
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
|
||||
0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
|
||||
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
|
||||
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
|
||||
0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
|
||||
0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
|
||||
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
|
||||
0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
|
||||
0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
|
||||
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
|
||||
0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
|
||||
0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
|
||||
|
||||
function cvt_hex8 (val) {
|
||||
var vh = (val>>>4)&0x0f;
|
||||
return vh.toString(16) + (val&0x0f).toString(16);
|
||||
}
|
||||
function cvt_byte (str) {
|
||||
// get the first hex digit
|
||||
var val1 = str.charCodeAt(0);
|
||||
// do some error checking
|
||||
if (val1 >= 48 && val1 <= 57) {
|
||||
// have a valid digit 0-9
|
||||
val1 -= 48;
|
||||
} else if (val1 >= 65 && val1 <= 70) {
|
||||
// have a valid digit A-F
|
||||
val1 -= 55;
|
||||
} else if (val1 >= 97 && val1 <= 102) {
|
||||
// have a valid digit A-F
|
||||
val1 -= 87;
|
||||
} else {
|
||||
// not 0-9 or A-F, complain
|
||||
console.log( str.charAt(1)+" is not a valid hex digit" );
|
||||
return -1;
|
||||
}
|
||||
// get the second hex digit
|
||||
var val2 = str.charCodeAt(1);
|
||||
// do some error checking
|
||||
if ( val2 >= 48 && val2 <= 57 ) {
|
||||
// have a valid digit 0-9
|
||||
val2 -= 48;
|
||||
} else if ( val2 >= 65 && val2 <= 70 ) {
|
||||
// have a valid digit A-F
|
||||
val2 -= 55;
|
||||
} else if ( val2 >= 97 && val2 <= 102 ) {
|
||||
// have a valid digit A-F
|
||||
val2 -= 87;
|
||||
} else {
|
||||
// not 0-9 or A-F, complain
|
||||
console.log( str.charAt(2)+" is not a valid hex digit" );
|
||||
return -1;
|
||||
}
|
||||
// all is ok, return the value
|
||||
return val1*16 + val2;
|
||||
}
|
||||
|
||||
// conversion function for non-constant subscripts
|
||||
// assume subscript range 0..3
|
||||
function I(x,y) {
|
||||
return (x*4) + y;
|
||||
}
|
||||
|
||||
// remove spaces from input
|
||||
function remove_spaces(instr) {
|
||||
var i;
|
||||
var outstr = "";
|
||||
for(i=0; i<instr.length; i++) {
|
||||
if ( instr.charAt(i) != " " )
|
||||
// not a space, include it
|
||||
outstr += instr.charAt(i);
|
||||
}
|
||||
return outstr;
|
||||
}
|
||||
|
||||
// get the message to encrypt/decrypt or the key
|
||||
// return as a 16-byte array
|
||||
function get_value(str, isASCII) {
|
||||
var dbyte = new Array(16);
|
||||
var i;
|
||||
var val; // one hex digit
|
||||
if (isASCII) {
|
||||
// check length of data
|
||||
if (str.length > 16) {
|
||||
console.log("is too long, using the first 16 ASCII characters" );
|
||||
}
|
||||
// have ASCII data
|
||||
// 16 characters?
|
||||
if (str.length >= 16) {
|
||||
// 16 or more characters
|
||||
for(i=0; i<16; i++) {
|
||||
dbyte[i] = str.charCodeAt(i);
|
||||
}
|
||||
} else {
|
||||
// less than 16 characters - fill with NULLs
|
||||
for(i=0; i<str.length; i++) {
|
||||
dbyte[i] = str.charCodeAt(i);
|
||||
}
|
||||
for( i=str.length; i<16; i++) {
|
||||
dbyte[i] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// have hex data - remove any spaces they used, then convert
|
||||
//str = remove_spaces(str);
|
||||
// check length of data
|
||||
if ( str.length != 32 ) {
|
||||
//console.log("\tget_value:\tstr = " + str + "\tisASCII = " + isASCII); //isASCII = false
|
||||
console.log("length wrong: Is " + str.length + " hex digits, but must be 128 bits (32 hex digits)");
|
||||
dbyte[0] = -1;
|
||||
return dbyte;
|
||||
}
|
||||
for( i=0; i<16; i++ ) {
|
||||
// isolate and convert this substring
|
||||
dbyte[i] = cvt_byte( str.substr(i*2,2) );
|
||||
if( dbyte[i] < 0 ) {
|
||||
// have an error
|
||||
dbyte[0] = -1;
|
||||
return dbyte;
|
||||
}
|
||||
}
|
||||
}
|
||||
// return successful conversion
|
||||
return dbyte;
|
||||
}
|
||||
//do the AES GF(2**8) multiplication
|
||||
// do this by the shift-and-"add" approach
|
||||
function aes_mul(a, b) {
|
||||
var res = 0;
|
||||
while(a > 0) {
|
||||
if((a&1) != 0)
|
||||
res = res ^ b; // "add" to the result
|
||||
a >>>= 1; // shift a to get next higher-order bit
|
||||
b <<= 1; // shift multiplier also
|
||||
}
|
||||
// now reduce it modulo x**8 + x**4 + x**3 + x + 1
|
||||
var hbit = 0x10000; // bit to test if we need to take action
|
||||
var modulus = 0x11b00; // modulus - XOR by this to change value
|
||||
while(hbit >= 0x100) {
|
||||
if ((res & hbit) != 0) {
|
||||
res ^= modulus; // XOR with the modulus
|
||||
}
|
||||
// prepare for the next loop
|
||||
hbit >>= 1;
|
||||
modulus >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// apply the S-box substitution to the key expansion
|
||||
function SubWord(word_ary) {
|
||||
var i;
|
||||
for(i=0; i<16; i++) {
|
||||
word_ary[i] = S_enc[word_ary[i]];
|
||||
}
|
||||
return word_ary;
|
||||
}
|
||||
|
||||
// rotate the bytes in a word
|
||||
function RotWord(word_ary) {
|
||||
return new Array(word_ary[1], word_ary[2], word_ary[3], word_ary[0]);
|
||||
}
|
||||
|
||||
// calculate the first item Rcon[i] = { x^(i-1), 0, 0, 0 }
|
||||
// note we only return the first item
|
||||
function Rcon(exp) {
|
||||
var val = 2;
|
||||
var result = 1;
|
||||
|
||||
// remember to calculate x^(exp-1)
|
||||
exp--;
|
||||
|
||||
// process the exponent using normal shift and multiply
|
||||
while ( exp > 0 )
|
||||
{
|
||||
if ( (exp & 1) != 0 )
|
||||
result = aes_mul( result, val );
|
||||
|
||||
// square the value
|
||||
val = aes_mul( val, val );
|
||||
|
||||
// move to the next bit
|
||||
exp >>= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// round key generation
|
||||
// return a byte array with the expanded key information
|
||||
function key_expand( key )
|
||||
{
|
||||
var temp = new Array(4);
|
||||
var i, j;
|
||||
var w = new Array(4*(Nr+1));
|
||||
|
||||
// copy initial key stuff
|
||||
for( i=0; i<16; i++ )
|
||||
{
|
||||
w[i] = key[i];
|
||||
}
|
||||
|
||||
// generate rest of key schedule using 32-bit words
|
||||
i = 4;
|
||||
while ( i < 4*(Nr+1)) // blocksize * ( rounds + 1 )
|
||||
{
|
||||
// copy word W[i-1] to temp
|
||||
for( j=0; j<4; j++ )
|
||||
temp[j] = w[(i-1)*4+j];
|
||||
|
||||
if ( i % 4 == 0)
|
||||
{
|
||||
// temp = SubWord(RotWord(temp)) ^ Rcon[i/4];
|
||||
temp = RotWord( temp );
|
||||
temp = SubWord( temp );
|
||||
temp[0] ^= Rcon( i>>>2 );
|
||||
}
|
||||
|
||||
// word = word ^ temp
|
||||
for( j=0; j<4; j++ )
|
||||
w[i*4+j] = w[(i-4)*4+j] ^ temp[j];
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
// do S-Box substitution
|
||||
function SubBytes(state, Sbox)
|
||||
{
|
||||
var i;
|
||||
|
||||
for( i=0; i<16; i++ )
|
||||
state[i] = Sbox[ state[i] ];
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// shift each row as appropriate
|
||||
function ShiftRows(state)
|
||||
{
|
||||
var t0, t1, t2, t3;
|
||||
|
||||
// top row (row 0) isn't shifted
|
||||
|
||||
// next row (row 1) rotated left 1 place
|
||||
t0 = state[I10];
|
||||
t1 = state[I11];
|
||||
t2 = state[I12];
|
||||
t3 = state[I13];
|
||||
state[I10] = t1;
|
||||
state[I11] = t2;
|
||||
state[I12] = t3;
|
||||
state[I13] = t0;
|
||||
|
||||
// next row (row 2) rotated left 2 places
|
||||
t0 = state[I20];
|
||||
t1 = state[I21];
|
||||
t2 = state[I22];
|
||||
t3 = state[I23];
|
||||
state[I20] = t2;
|
||||
state[I21] = t3;
|
||||
state[I22] = t0;
|
||||
state[I23] = t1;
|
||||
|
||||
// bottom row (row 3) rotated left 3 places
|
||||
t0 = state[I30];
|
||||
t1 = state[I31];
|
||||
t2 = state[I32];
|
||||
t3 = state[I33];
|
||||
state[I30] = t3;
|
||||
state[I31] = t0;
|
||||
state[I32] = t1;
|
||||
state[I33] = t2;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// inverset shift each row as appropriate
|
||||
function InvShiftRows(state)
|
||||
{
|
||||
var t0, t1, t2, t3;
|
||||
|
||||
// top row (row 0) isn't shifted
|
||||
|
||||
// next row (row 1) rotated left 1 place
|
||||
t0 = state[I10];
|
||||
t1 = state[I11];
|
||||
t2 = state[I12];
|
||||
t3 = state[I13];
|
||||
state[I10] = t3;
|
||||
state[I11] = t0;
|
||||
state[I12] = t1;
|
||||
state[I13] = t2;
|
||||
|
||||
// next row (row 2) rotated left 2 places
|
||||
t0 = state[I20];
|
||||
t1 = state[I21];
|
||||
t2 = state[I22];
|
||||
t3 = state[I23];
|
||||
state[I20] = t2;
|
||||
state[I21] = t3;
|
||||
state[I22] = t0;
|
||||
state[I23] = t1;
|
||||
|
||||
// bottom row (row 3) rotated left 3 places
|
||||
t0 = state[I30];
|
||||
t1 = state[I31];
|
||||
t2 = state[I32];
|
||||
t3 = state[I33];
|
||||
state[I30] = t1;
|
||||
state[I31] = t2;
|
||||
state[I32] = t3;
|
||||
state[I33] = t0;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// process column info
|
||||
function MixColumns(state)
|
||||
{
|
||||
var col;
|
||||
var c0, c1, c2, c3;
|
||||
|
||||
for( col=0; col<4; col++ )
|
||||
{
|
||||
c0 = state[I(0,col)];
|
||||
c1 = state[I(1,col)];
|
||||
c2 = state[I(2,col)];
|
||||
c3 = state[I(3,col)];
|
||||
|
||||
// do mixing, and put back into array
|
||||
state[I(0,col)] = aes_mul(2,c0) ^ aes_mul(3,c1) ^ c2 ^ c3;
|
||||
state[I(1,col)] = c0 ^ aes_mul(2,c1) ^ aes_mul(3,c2) ^ c3;
|
||||
state[I(2,col)] = c0 ^ c1 ^ aes_mul(2,c2) ^ aes_mul(3,c3);
|
||||
state[I(3,col)] = aes_mul(3,c0) ^ c1 ^ c2 ^ aes_mul(2,c3);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// inverse process column info
|
||||
function InvMixColumns(state)
|
||||
{
|
||||
var col;
|
||||
var c0, c1, c2, c3;
|
||||
|
||||
for( col=0; col<4; col++ )
|
||||
{
|
||||
c0 = state[I(0,col)];
|
||||
c1 = state[I(1,col)];
|
||||
c2 = state[I(2,col)];
|
||||
c3 = state[I(3,col)];
|
||||
|
||||
// do inverse mixing, and put back into array
|
||||
state[I(0,col)] = aes_mul(0x0e,c0) ^ aes_mul(0x0b,c1)
|
||||
^ aes_mul(0x0d,c2) ^ aes_mul(0x09,c3);
|
||||
state[I(1,col)] = aes_mul(0x09,c0) ^ aes_mul(0x0e,c1)
|
||||
^ aes_mul(0x0b,c2) ^ aes_mul(0x0d,c3);
|
||||
state[I(2,col)] = aes_mul(0x0d,c0) ^ aes_mul(0x09,c1)
|
||||
^ aes_mul(0x0e,c2) ^ aes_mul(0x0b,c3);
|
||||
state[I(3,col)] = aes_mul(0x0b,c0) ^ aes_mul(0x0d,c1)
|
||||
^ aes_mul(0x09,c2) ^ aes_mul(0x0e,c3);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// insert subkey information
|
||||
function AddRoundKey( state, w, base )
|
||||
{
|
||||
var col;
|
||||
|
||||
for( col=0; col<4; col++ )
|
||||
{
|
||||
state[I(0,col)] ^= w[base+col*4];
|
||||
state[I(1,col)] ^= w[base+col*4+1];
|
||||
state[I(2,col)] ^= w[base+col*4+2];
|
||||
state[I(3,col)] ^= w[base+col*4+3];
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// return a transposed array
|
||||
function transpose( msg )
|
||||
{
|
||||
var row, col;
|
||||
var state = new Array( 16 );
|
||||
|
||||
for( row=0; row<4; row++ )
|
||||
for( col=0; col<4; col++ )
|
||||
state[I(row,col)] = msg[I(col,row)];
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// final AES state
|
||||
var AES_output = new Array(16);
|
||||
|
||||
// format AES output
|
||||
// -- uses the global array DES_output
|
||||
function format_AES_output(bASCII)
|
||||
{
|
||||
var i;
|
||||
var bits;
|
||||
var str="";
|
||||
|
||||
// what type of data do we have to work with?
|
||||
if (bASCII)
|
||||
{
|
||||
// convert each set of bits back to ASCII
|
||||
for( i=0; i<16; i++ )
|
||||
str += String.fromCharCode( AES_output[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// output hexdecimal data (insert spaces)
|
||||
str = cvt_hex8( AES_output[0] );
|
||||
for( i=1; i<16; i++ )
|
||||
{
|
||||
str += "" + cvt_hex8( AES_output[i] );
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// do encrytion
|
||||
function aes_encrypt(str, key, bASCII)
|
||||
{
|
||||
//console.log(" aes_encrypt:\tstr = " + str + "\tkey = " + key + "\t bASCII = " + bASCII);
|
||||
var w = new Array( 4*(Nr+1) ); // subkey information
|
||||
var state = new Array( 16 ); // working state
|
||||
var round;
|
||||
|
||||
//accumulated_output_info = "";
|
||||
|
||||
// get the message from the user
|
||||
// also check if it is ASCII or hex
|
||||
var msg = get_value(str, bASCII);
|
||||
|
||||
// problems??
|
||||
if ( msg[0] < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the key from the user
|
||||
var key = get_value(key, false);
|
||||
// problems??
|
||||
if ( key[0] < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// expand the key
|
||||
w = key_expand( key );
|
||||
|
||||
// initial state = message in columns (transposed from what we input)
|
||||
state = transpose( msg );
|
||||
|
||||
// display the round key - Transpose due to the way it is stored/used
|
||||
state = AddRoundKey(state, w, 0);
|
||||
|
||||
for( round=1; round<Nr; round++ )
|
||||
{
|
||||
state = SubBytes(state, S_enc);
|
||||
state = ShiftRows(state);
|
||||
state = MixColumns(state);
|
||||
// display the round key - Transpose due to the way it is stored/used
|
||||
// note here the spec uses 32-bit words, we are using bytes, so an extra *4
|
||||
state = AddRoundKey(state, w, round*4*4);
|
||||
}
|
||||
|
||||
SubBytes(state, S_enc);
|
||||
ShiftRows(state);
|
||||
AddRoundKey(state, w, Nr*4*4);
|
||||
|
||||
// process output
|
||||
AES_output = transpose( state );
|
||||
var szOutput = format_AES_output(!bASCII);
|
||||
return szOutput;
|
||||
}
|
||||
|
||||
// do decryption
|
||||
function aes_decrypt(str, key, bASCII)
|
||||
{
|
||||
//console.log(" aes_decrypt:\tstr = " + str + "\tkey = " + key + "\tbASCII = " + bASCII);
|
||||
var w = new Array( 4*(Nr+1) ); // subkey information
|
||||
var state = new Array( 16 ); // working state
|
||||
var round;
|
||||
|
||||
//accumulated_output_info = "";
|
||||
|
||||
// get the message from the user
|
||||
// also check if it is ASCII or hex
|
||||
var msg = get_value(str, bASCII);
|
||||
|
||||
// problems??
|
||||
if ( msg[0] < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the key from the user
|
||||
var key = get_value(key, false);
|
||||
// problems??
|
||||
if ( key[0] < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// expand the key
|
||||
w = key_expand( key );
|
||||
|
||||
// initial state = message
|
||||
state = transpose( msg );
|
||||
// display the round key - Transpose due to the way it is stored/used
|
||||
state = AddRoundKey(state, w, Nr*4*4);
|
||||
|
||||
for( round=Nr-1; round>=1; round-- )
|
||||
{
|
||||
state = InvShiftRows(state);
|
||||
state = SubBytes(state, S_dec);
|
||||
// display the round key - Transpose due to the way it is stored/used
|
||||
// note here the spec uses 32-bit words, we are using bytes, so an extra *4
|
||||
state = AddRoundKey(state, w, round*4*4);
|
||||
state = InvMixColumns(state);
|
||||
}
|
||||
|
||||
InvShiftRows(state);
|
||||
SubBytes(state, S_dec);
|
||||
AddRoundKey(state, w, 0);
|
||||
|
||||
// process output
|
||||
AES_output = transpose( state );
|
||||
var szOutput = format_AES_output(!bASCII);
|
||||
return szOutput;
|
||||
}
|
||||
window.aes_encrypt = aes_encrypt;
|
||||
window.aes_decrypt = aes_decrypt;
|
||||
window.console = window.console || {
|
||||
log: function() {}
|
||||
};
|
||||
}());
|
||||
106
public/vendor/hikvision/encryption/cryptico.min.js
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
var dbits,canary=244837814094590,j_lm=(canary&16777215)==15715070;function BigInteger(a,b,c){a!=null&&("number"==typeof a?this.fromNumber(a,b,c):b==null&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}function am1(a,b,c,d,e,g){for(;--g>=0;){var h=b*this[a++]+c[d]+e,e=Math.floor(h/67108864);c[d++]=h&67108863}return e}
|
||||
function am2(a,b,c,d,e,g){var h=b&32767;for(b>>=15;--g>=0;){var f=this[a]&32767,o=this[a++]>>15,p=b*f+o*h,f=h*f+((p&32767)<<15)+c[d]+(e&1073741823),e=(f>>>30)+(p>>>15)+b*o+(e>>>30);c[d++]=f&1073741823}return e}function am3(a,b,c,d,e,g){var h=b&16383;for(b>>=14;--g>=0;){var f=this[a]&16383,o=this[a++]>>14,p=b*f+o*h,f=h*f+((p&16383)<<14)+c[d]+e,e=(f>>28)+(p>>14)+b*o;c[d++]=f&268435455}return e}
|
||||
j_lm&&navigator.appName=="Microsoft Internet Explorer"?(BigInteger.prototype.am=am2,dbits=30):j_lm&&navigator.appName!="Netscape"?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28);BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=(1<<dbits)-1;BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz",BI_RC=[],rr,vv;
|
||||
rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr="a".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr="A".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return c==null?-1:c}function bnpCopyTo(a){for(var b=this.t-1;b>=0;--b)a[b]=this[b];a.t=this.t;a.s=this.s}function bnpFromInt(a){this.t=1;this.s=a<0?-1:0;a>0?this[0]=a:a<-1?this[0]=a+DV:this.t=0}
|
||||
function nbv(a){var b=nbi();b.fromInt(a);return b}
|
||||
function bnpFromString(a,b){var c;if(b==16)c=4;else if(b==8)c=3;else if(b==256)c=8;else if(b==2)c=1;else if(b==32)c=5;else if(b==4)c=2;else{this.fromRadix(a,b);return}this.s=this.t=0;for(var d=a.length,e=!1,g=0;--d>=0;){var h=c==8?a[d]&255:intAt(a,d);h<0?a.charAt(d)=="-"&&(e=!0):(e=!1,g==0?this[this.t++]=h:g+c>this.DB?(this[this.t-1]|=(h&(1<<this.DB-g)-1)<<g,this[this.t++]=h>>this.DB-g):this[this.t-1]|=h<<g,g+=c,g>=this.DB&&(g-=this.DB))}if(c==8&&(a[0]&128)!=0)this.s=-1,g>0&&(this[this.t-1]|=(1<<
|
||||
this.DB-g)-1<<g);this.clamp();e&&BigInteger.ZERO.subTo(this,this)}function bnpClamp(){for(var a=this.s&this.DM;this.t>0&&this[this.t-1]==a;)--this.t}
|
||||
function bnToString(a){if(this.s<0)return"-"+this.negate().toString(a);if(a==16)a=4;else if(a==8)a=3;else if(a==2)a=1;else if(a==32)a=5;else if(a==64)a=6;else if(a==4)a=2;else return this.toRadix(a);var b=(1<<a)-1,c,d=!1,e="",g=this.t,h=this.DB-g*this.DB%a;if(g-- >0){if(h<this.DB&&(c=this[g]>>h)>0)d=!0,e=int2char(c);for(;g>=0;)h<a?(c=(this[g]&(1<<h)-1)<<a-h,c|=this[--g]>>(h+=this.DB-a)):(c=this[g]>>(h-=a)&b,h<=0&&(h+=this.DB,--g)),c>0&&(d=!0),d&&(e+=int2char(c))}return d?e:"0"}
|
||||
function bnNegate(){var a=nbi();BigInteger.ZERO.subTo(this,a);return a}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(b!=0)return b;var c=this.t,b=c-a.t;if(b!=0)return b;for(;--c>=0;)if((b=this[c]-a[c])!=0)return b;return 0}function nbits(a){var b=1,c;if((c=a>>>16)!=0)a=c,b+=16;if((c=a>>8)!=0)a=c,b+=8;if((c=a>>4)!=0)a=c,b+=4;if((c=a>>2)!=0)a=c,b+=2;a>>1!=0&&(b+=1);return b}
|
||||
function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;c>=0;--c)b[c+a]=this[c];for(c=a-1;c>=0;--c)b[c]=0;b.t=this.t+a;b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c<this.t;++c)b[c-a]=this[c];b.t=Math.max(this.t-a,0);b.s=this.s}
|
||||
function bnpLShiftTo(a,b){var c=a%this.DB,d=this.DB-c,e=(1<<d)-1,g=Math.floor(a/this.DB),h=this.s<<c&this.DM,f;for(f=this.t-1;f>=0;--f)b[f+g+1]=this[f]>>d|h,h=(this[f]&e)<<c;for(f=g-1;f>=0;--f)b[f]=0;b[g]=h;b.t=this.t+g+1;b.s=this.s;b.clamp()}
|
||||
function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)b.t=0;else{var d=a%this.DB,e=this.DB-d,g=(1<<d)-1;b[0]=this[c]>>d;for(var h=c+1;h<this.t;++h)b[h-c-1]|=(this[h]&g)<<e,b[h-c]=this[h]>>d;d>0&&(b[this.t-c-1]|=(this.s&g)<<e);b.t=this.t-c;b.clamp()}}
|
||||
function bnpSubTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d-=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d-=a[c],b[c++]=d&this.DM,d>>=this.DB;d-=a.s}b.s=d<0?-1:0;d<-1?b[c++]=this.DV+d:d>0&&(b[c++]=d);b.t=c;b.clamp()}
|
||||
function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;--e>=0;)b[e]=0;for(e=0;e<d.t;++e)b[e+c.t]=c.am(0,d[e],b,e,0,c.t);b.s=0;b.clamp();this.s!=a.s&&BigInteger.ZERO.subTo(b,b)}function bnpSquareTo(a){for(var b=this.abs(),c=a.t=2*b.t;--c>=0;)a[c]=0;for(c=0;c<b.t-1;++c){var d=b.am(c,b[c],a,2*c,0,1);if((a[c+b.t]+=b.am(c+1,2*b[c],a,2*c+1,d,b.t-c-1))>=b.DV)a[c+b.t]-=b.DV,a[c+b.t+1]=1}a.t>0&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1));a.s=0;a.clamp()}
|
||||
function bnpDivRemTo(a,b,c){var d=a.abs();if(!(d.t<=0)){var e=this.abs();if(e.t<d.t)b!=null&&b.fromInt(0),c!=null&&this.copyTo(c);else{c==null&&(c=nbi());var g=nbi(),h=this.s,a=a.s,f=this.DB-nbits(d[d.t-1]);f>0?(d.lShiftTo(f,g),e.lShiftTo(f,c)):(d.copyTo(g),e.copyTo(c));d=g.t;e=g[d-1];if(e!=0){var o=e*(1<<this.F1)+(d>1?g[d-2]>>this.F2:0),p=this.FV/o,o=(1<<this.F1)/o,q=1<<this.F2,n=c.t,k=n-d,j=b==null?nbi():b;g.dlShiftTo(k,j);c.compareTo(j)>=0&&(c[c.t++]=1,c.subTo(j,c));BigInteger.ONE.dlShiftTo(d,
|
||||
j);for(j.subTo(g,g);g.t<d;)g[g.t++]=0;for(;--k>=0;){var l=c[--n]==e?this.DM:Math.floor(c[n]*p+(c[n-1]+q)*o);if((c[n]+=g.am(0,l,c,k,0,d))<l){g.dlShiftTo(k,j);for(c.subTo(j,c);c[n]<--l;)c.subTo(j,c)}}b!=null&&(c.drShiftTo(d,b),h!=a&&BigInteger.ZERO.subTo(b,b));c.t=d;c.clamp();f>0&&c.rShiftTo(f,c);h<0&&BigInteger.ZERO.subTo(c,c)}}}}function bnMod(a){var b=nbi();this.abs().divRemTo(a,null,b);this.s<0&&b.compareTo(BigInteger.ZERO)>0&&a.subTo(b,b);return b}function Classic(a){this.m=a}
|
||||
function cConvert(a){return a.s<0||a.compareTo(this.m)>=0?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}function cSqrTo(a,b){a.squareTo(b);this.reduce(b)}Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;
|
||||
function bnpInvDigit(){if(this.t<1)return 0;var a=this[0];if((a&1)==0)return 0;var b=a&3,b=b*(2-(a&15)*b)&15,b=b*(2-(a&255)*b)&255,b=b*(2-((a&65535)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV;return b>0?this.DV-b:-b}function Montgomery(a){this.m=a;this.mp=a.invDigit();this.mpl=this.mp&32767;this.mph=this.mp>>15;this.um=(1<<a.DB-15)-1;this.mt2=2*a.t}
|
||||
function montConvert(a){var b=nbi();a.abs().dlShiftTo(this.m.t,b);b.divRemTo(this.m,null,b);a.s<0&&b.compareTo(BigInteger.ZERO)>0&&this.m.subTo(b,b);return b}function montRevert(a){var b=nbi();a.copyTo(b);this.reduce(b);return b}
|
||||
function montReduce(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b<this.m.t;++b){var c=a[b]&32767,d=c*this.mpl+((c*this.mph+(a[b]>>15)*this.mpl&this.um)<<15)&a.DM,c=b+this.m.t;for(a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp();a.drShiftTo(this.m.t,a);a.compareTo(this.m)>=0&&a.subTo(this.m,a)}function montSqrTo(a,b){a.squareTo(b);this.reduce(b)}function montMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Montgomery.prototype.convert=montConvert;
|
||||
Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return(this.t>0?this[0]&1:this.s)==0}function bnpExp(a,b){if(a>4294967295||a<1)return BigInteger.ONE;var c=nbi(),d=nbi(),e=b.convert(this),g=nbits(a)-1;for(e.copyTo(c);--g>=0;)if(b.sqrTo(c,d),(a&1<<g)>0)b.mulTo(d,e,c);else var h=c,c=d,d=h;return b.revert(c)}
|
||||
function bnModPowInt(a,b){var c;c=a<256||b.isEven()?new Classic(b):new Montgomery(b);return this.exp(a,c)}BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;
|
||||
BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;
|
||||
BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function bnClone(){var a=nbi();this.copyTo(a);return a}function bnIntValue(){if(this.s<0)if(this.t==1)return this[0]-this.DV;else{if(this.t==0)return-1}else if(this.t==1)return this[0];else if(this.t==0)return 0;return(this[1]&(1<<32-this.DB)-1)<<this.DB|this[0]}function bnByteValue(){return this.t==0?this.s:this[0]<<24>>24}function bnShortValue(){return this.t==0?this.s:this[0]<<16>>16}
|
||||
function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}function bnSigNum(){return this.s<0?-1:this.t<=0||this.t==1&&this[0]<=0?0:1}function bnpToRadix(a){a==null&&(a=10);if(this.signum()==0||a<2||a>36)return"0";var b=this.chunkSize(a),b=Math.pow(a,b),c=nbv(b),d=nbi(),e=nbi(),g="";for(this.divRemTo(c,d,e);d.signum()>0;)g=(b+e.intValue()).toString(a).substr(1)+g,d.divRemTo(c,d,e);return e.intValue().toString(a)+g}
|
||||
function bnpFromRadix(a,b){this.fromInt(0);b==null&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,g=0,h=0,f=0;f<a.length;++f){var o=intAt(a,f);o<0?a.charAt(f)=="-"&&this.signum()==0&&(e=!0):(h=b*h+o,++g>=c&&(this.dMultiply(d),this.dAddOffset(h,0),h=g=0))}g>0&&(this.dMultiply(Math.pow(b,g)),this.dAddOffset(h,0));e&&BigInteger.ZERO.subTo(this,this)}
|
||||
function bnpFromNumber(a,b,c){if("number"==typeof b)if(a<2)this.fromInt(1);else{this.fromNumber(a,c);this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);for(this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this)}else{var c=[],d=a&7;c.length=(a>>3)+1;b.nextBytes(c);d>0?c[0]&=(1<<d)-1:c[0]=0;this.fromString(c,256)}}
|
||||
function bnToByteArray(){var a=this.t,b=[];b[0]=this.s;var c=this.DB-a*this.DB%8,d,e=0;if(a-- >0){if(c<this.DB&&(d=this[a]>>c)!=(this.s&this.DM)>>c)b[e++]=d|this.s<<this.DB-c;for(;a>=0;)if(c<8?(d=(this[a]&(1<<c)-1)<<8-c,d|=this[--a]>>(c+=this.DB-8)):(d=this[a]>>(c-=8)&255,c<=0&&(c+=this.DB,--a)),(d&128)!=0&&(d|=-256),e==0&&(this.s&128)!=(d&128)&&++e,e>0||d!=this.s)b[e++]=d}return b}function bnEquals(a){return this.compareTo(a)==0}function bnMin(a){return this.compareTo(a)<0?this:a}
|
||||
function bnMax(a){return this.compareTo(a)>0?this:a}function bnpBitwiseTo(a,b,c){var d,e,g=Math.min(a.t,this.t);for(d=0;d<g;++d)c[d]=b(this[d],a[d]);if(a.t<this.t){e=a.s&this.DM;for(d=g;d<this.t;++d)c[d]=b(this[d],e);c.t=this.t}else{e=this.s&this.DM;for(d=g;d<a.t;++d)c[d]=b(e,a[d]);c.t=a.t}c.s=b(this.s,a.s);c.clamp()}function op_and(a,b){return a&b}function bnAnd(a){var b=nbi();this.bitwiseTo(a,op_and,b);return b}function op_or(a,b){return a|b}
|
||||
function bnOr(a){var b=nbi();this.bitwiseTo(a,op_or,b);return b}function op_xor(a,b){return a^b}function bnXor(a){var b=nbi();this.bitwiseTo(a,op_xor,b);return b}function op_andnot(a,b){return a&~b}function bnAndNot(a){var b=nbi();this.bitwiseTo(a,op_andnot,b);return b}function bnNot(){for(var a=nbi(),b=0;b<this.t;++b)a[b]=this.DM&~this[b];a.t=this.t;a.s=~this.s;return a}function bnShiftLeft(a){var b=nbi();a<0?this.rShiftTo(-a,b):this.lShiftTo(a,b);return b}
|
||||
function bnShiftRight(a){var b=nbi();a<0?this.lShiftTo(-a,b):this.rShiftTo(a,b);return b}function lbit(a){if(a==0)return-1;var b=0;(a&65535)==0&&(a>>=16,b+=16);(a&255)==0&&(a>>=8,b+=8);(a&15)==0&&(a>>=4,b+=4);(a&3)==0&&(a>>=2,b+=2);(a&1)==0&&++b;return b}function bnGetLowestSetBit(){for(var a=0;a<this.t;++a)if(this[a]!=0)return a*this.DB+lbit(this[a]);return this.s<0?this.t*this.DB:-1}function cbit(a){for(var b=0;a!=0;)a&=a-1,++b;return b}
|
||||
function bnBitCount(){for(var a=0,b=this.s&this.DM,c=0;c<this.t;++c)a+=cbit(this[c]^b);return a}function bnTestBit(a){var b=Math.floor(a/this.DB);return b>=this.t?this.s!=0:(this[b]&1<<a%this.DB)!=0}function bnpChangeBit(a,b){var c=BigInteger.ONE.shiftLeft(a);this.bitwiseTo(c,b,c);return c}function bnSetBit(a){return this.changeBit(a,op_or)}function bnClearBit(a){return this.changeBit(a,op_andnot)}function bnFlipBit(a){return this.changeBit(a,op_xor)}
|
||||
function bnpAddTo(a,b){for(var c=0,d=0,e=Math.min(a.t,this.t);c<e;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t<this.t){for(d+=a.s;c<this.t;)d+=this[c],b[c++]=d&this.DM,d>>=this.DB;d+=this.s}else{for(d+=this.s;c<a.t;)d+=a[c],b[c++]=d&this.DM,d>>=this.DB;d+=a.s}b.s=d<0?-1:0;d>0?b[c++]=d:d<-1&&(b[c++]=this.DV+d);b.t=c;b.clamp()}function bnAdd(a){var b=nbi();this.addTo(a,b);return b}function bnSubtract(a){var b=nbi();this.subTo(a,b);return b}
|
||||
function bnMultiply(a){var b=nbi();this.multiplyTo(a,b);return b}function bnSquare(){var a=nbi();this.squareTo(a);return a}function bnDivide(a){var b=nbi();this.divRemTo(a,b,null);return b}function bnRemainder(a){var b=nbi();this.divRemTo(a,null,b);return b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();this.divRemTo(a,b,c);return[b,c]}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t);++this.t;this.clamp()}
|
||||
function bnpDAddOffset(a,b){if(a!=0){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}NullExp.prototype.convert=nNop;NullExp.prototype.revert=nNop;NullExp.prototype.mulTo=nMulTo;NullExp.prototype.sqrTo=nSqrTo;function bnPow(a){return this.exp(a,new NullExp)}
|
||||
function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);c.s=0;for(c.t=d;d>0;)c[--d]=0;var e;for(e=c.t-this.t;d<e;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);d<e;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;--d>=0;)c[d]=0;for(d=Math.max(b-this.t,0);d<a.t;++d)c[this.t+d-b]=this.am(b-d,a[d],c,0,0,this.t+d-b);c.clamp();c.drShiftTo(1,c)}
|
||||
function Barrett(a){this.r2=nbi();this.q3=nbi();BigInteger.ONE.dlShiftTo(2*a.t,this.r2);this.mu=this.r2.divide(a);this.m=a}function barrettConvert(a){if(a.s<0||a.t>2*this.m.t)return a.mod(this.m);else if(a.compareTo(this.m)<0)return a;else{var b=nbi();a.copyTo(b);this.reduce(b);return b}}function barrettRevert(a){return a}
|
||||
function barrettReduce(a){a.drShiftTo(this.m.t-1,this.r2);if(a.t>this.m.t+1)a.t=this.m.t+1,a.clamp();this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);for(this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);a.compareTo(this.r2)<0;)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);a.compareTo(this.m)>=0;)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b);this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c);this.reduce(c)}Barrett.prototype.convert=barrettConvert;
|
||||
Barrett.prototype.revert=barrettRevert;Barrett.prototype.reduce=barrettReduce;Barrett.prototype.mulTo=barrettMulTo;Barrett.prototype.sqrTo=barrettSqrTo;
|
||||
function bnModPow(a,b){var c=a.bitLength(),d,e=nbv(1),g;if(c<=0)return e;else d=c<18?1:c<48?3:c<144?4:c<768?5:6;g=c<8?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var h=[],f=3,o=d-1,p=(1<<d)-1;h[1]=g.convert(this);if(d>1){c=nbi();for(g.sqrTo(h[1],c);f<=p;)h[f]=nbi(),g.mulTo(c,h[f-2],h[f]),f+=2}for(var q=a.t-1,n,k=!0,j=nbi(),c=nbits(a[q])-1;q>=0;){c>=o?n=a[q]>>c-o&p:(n=(a[q]&(1<<c+1)-1)<<o-c,q>0&&(n|=a[q-1]>>this.DB+c-o));for(f=d;(n&1)==0;)n>>=1,--f;if((c-=f)<0)c+=this.DB,--q;if(k)h[n].copyTo(e),
|
||||
k=!1;else{for(;f>1;)g.sqrTo(e,j),g.sqrTo(j,e),f-=2;f>0?g.sqrTo(e,j):(f=e,e=j,j=f);g.mulTo(j,h[n],e)}for(;q>=0&&(a[q]&1<<c)==0;)g.sqrTo(e,j),f=e,e=j,j=f,--c<0&&(c=this.DB-1,--q)}return g.revert(e)}
|
||||
function bnGCD(a){var b=this.s<0?this.negate():this.clone(),a=a.s<0?a.negate():a.clone();if(b.compareTo(a)<0)var c=b,b=a,a=c;var c=b.getLowestSetBit(),d=a.getLowestSetBit();if(d<0)return b;c<d&&(d=c);d>0&&(b.rShiftTo(d,b),a.rShiftTo(d,a));for(;b.signum()>0;)(c=b.getLowestSetBit())>0&&b.rShiftTo(c,b),(c=a.getLowestSetBit())>0&&a.rShiftTo(c,a),b.compareTo(a)>=0?(b.subTo(a,b),b.rShiftTo(1,b)):(a.subTo(b,a),a.rShiftTo(1,a));d>0&&a.lShiftTo(d,a);return a}
|
||||
function bnpModInt(a){if(a<=0)return 0;var b=this.DV%a,c=this.s<0?a-1:0;if(this.t>0)if(b==0)c=this[0]%a;else for(var d=this.t-1;d>=0;--d)c=(b*c+this[d])%a;return c}
|
||||
function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||a.signum()==0)return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),g=nbv(0),h=nbv(0),f=nbv(1);c.signum()!=0;){for(;c.isEven();){c.rShiftTo(1,c);if(b){if(!e.isEven()||!g.isEven())e.addTo(this,e),g.subTo(a,g);e.rShiftTo(1,e)}else g.isEven()||g.subTo(a,g);g.rShiftTo(1,g)}for(;d.isEven();){d.rShiftTo(1,d);if(b){if(!h.isEven()||!f.isEven())h.addTo(this,h),f.subTo(a,f);h.rShiftTo(1,h)}else f.isEven()||f.subTo(a,f);f.rShiftTo(1,
|
||||
f)}c.compareTo(d)>=0?(c.subTo(d,c),b&&e.subTo(h,e),g.subTo(f,g)):(d.subTo(c,d),b&&h.subTo(e,h),f.subTo(g,f))}if(d.compareTo(BigInteger.ONE)!=0)return BigInteger.ZERO;if(f.compareTo(a)>=0)return f.subtract(a);if(f.signum()<0)f.addTo(a,f);else return f;return f.signum()<0?f.add(a):f}
|
||||
var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,
|
||||
733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],lplim=67108864/lowprimes[lowprimes.length-1];
|
||||
function bnIsProbablePrime(a){var b,c=this.abs();if(c.t==1&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;b<lowprimes.length;++b)if(c[0]==lowprimes[b])return!0;return!1}if(c.isEven())return!1;for(b=1;b<lowprimes.length;){for(var d=lowprimes[b],e=b+1;e<lowprimes.length&&d<lplim;)d*=lowprimes[e++];for(d=c.modInt(d);b<e;)if(d%lowprimes[b++]==0)return!1}return c.millerRabin(a)}
|
||||
function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(c<=0)return!1;var d=b.shiftRight(c),a=a+1>>1;if(a>lowprimes.length)a=lowprimes.length;for(var e=nbi(),g=0;g<a;++g){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var h=e.modPow(d,this);if(h.compareTo(BigInteger.ONE)!=0&&h.compareTo(b)!=0){for(var f=1;f++<c&&h.compareTo(b)!=0;)if(h=h.modPowInt(2,this),h.compareTo(BigInteger.ONE)==0)return!1;if(h.compareTo(b)!=0)return!1}}return!0}
|
||||
BigInteger.prototype.chunkSize=bnpChunkSize;BigInteger.prototype.toRadix=bnpToRadix;BigInteger.prototype.fromRadix=bnpFromRadix;BigInteger.prototype.fromNumber=bnpFromNumber;BigInteger.prototype.bitwiseTo=bnpBitwiseTo;BigInteger.prototype.changeBit=bnpChangeBit;BigInteger.prototype.addTo=bnpAddTo;BigInteger.prototype.dMultiply=bnpDMultiply;BigInteger.prototype.dAddOffset=bnpDAddOffset;BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo;BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo;
|
||||
BigInteger.prototype.modInt=bnpModInt;BigInteger.prototype.millerRabin=bnpMillerRabin;BigInteger.prototype.clone=bnClone;BigInteger.prototype.intValue=bnIntValue;BigInteger.prototype.byteValue=bnByteValue;BigInteger.prototype.shortValue=bnShortValue;BigInteger.prototype.signum=bnSigNum;BigInteger.prototype.toByteArray=bnToByteArray;BigInteger.prototype.equals=bnEquals;BigInteger.prototype.min=bnMin;BigInteger.prototype.max=bnMax;BigInteger.prototype.and=bnAnd;BigInteger.prototype.or=bnOr;
|
||||
BigInteger.prototype.xor=bnXor;BigInteger.prototype.andNot=bnAndNot;BigInteger.prototype.not=bnNot;BigInteger.prototype.shiftLeft=bnShiftLeft;BigInteger.prototype.shiftRight=bnShiftRight;BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit;BigInteger.prototype.bitCount=bnBitCount;BigInteger.prototype.testBit=bnTestBit;BigInteger.prototype.setBit=bnSetBit;BigInteger.prototype.clearBit=bnClearBit;BigInteger.prototype.flipBit=bnFlipBit;BigInteger.prototype.add=bnAdd;BigInteger.prototype.subtract=bnSubtract;
|
||||
BigInteger.prototype.multiply=bnMultiply;BigInteger.prototype.divide=bnDivide;BigInteger.prototype.remainder=bnRemainder;BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder;BigInteger.prototype.modPow=bnModPow;BigInteger.prototype.modInverse=bnModInverse;BigInteger.prototype.pow=bnPow;BigInteger.prototype.gcd=bnGCD;BigInteger.prototype.isProbablePrime=bnIsProbablePrime;BigInteger.prototype.square=bnSquare;
|
||||
(function(a,b,c,d,e,g,h){function f(a){var b,d,e=this,g=a.length,f=0,h=e.i=e.j=e.m=0;e.S=[];e.c=[];for(g||(a=[g++]);f<c;)e.S[f]=f++;for(f=0;f<c;f++)b=e.S[f],h=h+b+a[f%g]&c-1,d=e.S[h],e.S[f]=d,e.S[h]=b;e.g=function(a){var b=e.S,d=e.i+1&c-1,g=b[d],f=e.j+g&c-1,h=b[f];b[d]=h;b[f]=g;for(var k=b[g+h&c-1];--a;)d=d+1&c-1,g=b[d],f=f+g&c-1,h=b[f],b[d]=h,b[f]=g,k=k*c+b[g+h&c-1];e.i=d;e.j=f;return k};e.g(c)}function o(a,b,c,d,e){c=[];e=typeof a;if(b&&e=="object")for(d in a)if(d.indexOf("S")<5)try{c.push(o(a[d],
|
||||
b-1))}catch(g){}return c.length?c:a+(e!="string"?"\x00":"")}function p(a,b,d,e){a+="";for(e=d=0;e<a.length;e++){var g=b,f=e&c-1,h=(d^=b[e&c-1]*19)+a.charCodeAt(e);g[f]=h&c-1}a="";for(e in b)a+=String.fromCharCode(b[e]);return a}b.seedrandom=function(q,n){var k=[],j,q=p(o(n?[q,a]:arguments.length?q:[(new Date).getTime(),a,window],3),k);j=new f(k);p(j.S,a);b.random=function(){for(var a=j.g(d),b=h,f=0;a<e;)a=(a+f)*c,b*=c,f=j.g(1);for(;a>=g;)a/=2,b/=2,f>>>=1;return(a+f)/b};return q};h=b.pow(c,d);e=b.pow(2,
|
||||
e);g=e*2;p(b.random(),a)})([],Math,256,6,52);function SeededRandom(){}function SRnextBytes(a){var b;for(b=0;b<a.length;b++)a[b]=Math.floor(Math.random()*256)}SeededRandom.prototype.nextBytes=SRnextBytes;function Arcfour(){this.j=this.i=0;this.S=[]}function ARC4init(a){var b,c,d;for(b=0;b<256;++b)this.S[b]=b;for(b=c=0;b<256;++b)c=c+this.S[b]+a[b%a.length]&255,d=this.S[b],this.S[b]=this.S[c],this.S[c]=d;this.j=this.i=0}
|
||||
function ARC4next(){var a;this.i=this.i+1&255;this.j=this.j+this.S[this.i]&255;a=this.S[this.i];this.S[this.i]=this.S[this.j];this.S[this.j]=a;return this.S[a+this.S[this.i]&255]}Arcfour.prototype.init=ARC4init;Arcfour.prototype.next=ARC4next;function prng_newstate(){return new Arcfour}var rng_psize=256,rng_state,rng_pool,rng_pptr;
|
||||
function rng_seed_int(a){rng_pool[rng_pptr++]^=a&255;rng_pool[rng_pptr++]^=a>>8&255;rng_pool[rng_pptr++]^=a>>16&255;rng_pool[rng_pptr++]^=a>>24&255;rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}
|
||||
if(rng_pool==null){rng_pool=[];rng_pptr=0;var t;if(navigator.appName=="Netscape"&&navigator.appVersion<"5"&&window.crypto){var z=window.crypto.random(32);for(t=0;t<z.length;++t)rng_pool[rng_pptr++]=z.charCodeAt(t)&255}for(;rng_pptr<rng_psize;)t=Math.floor(65536*Math.random()),rng_pool[rng_pptr++]=t>>>8,rng_pool[rng_pptr++]=t&255;rng_pptr=0;rng_seed_time()}
|
||||
function rng_get_byte(){if(rng_state==null){rng_seed_time();rng_state=prng_newstate();rng_state.init(rng_pool);for(rng_pptr=0;rng_pptr<rng_pool.length;++rng_pptr)rng_pool[rng_pptr]=0;rng_pptr=0}return rng_state.next()}function rng_get_bytes(a){var b;for(b=0;b<a.length;++b)a[b]=rng_get_byte()}function SecureRandom(){}SecureRandom.prototype.nextBytes=rng_get_bytes;
|
||||
function SHA256(a){function b(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535}function c(a,b){return a>>>b|a<<32-b}a=function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var h=a.charCodeAt(c);h<128?b+=String.fromCharCode(h):(h>127&&h<2048?b+=String.fromCharCode(h>>6|192):(b+=String.fromCharCode(h>>12|224),b+=String.fromCharCode(h>>6&63|128)),b+=String.fromCharCode(h&63|128))}return b}(a);return function(a){for(var b="",c=0;c<a.length*4;c++)b+="0123456789abcdef".charAt(a[c>>
|
||||
2]>>(3-c%4)*8+4&15)+"0123456789abcdef".charAt(a[c>>2]>>(3-c%4)*8&15);return b}(function(a,e){var g=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,
|
||||
2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],h=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],f=Array(64),o,p,q,n,k,j,l,m,s,r,u,w;a[e>>5]|=128<<24-e%32;a[(e+64>>9<<4)+15]=e;for(s=0;s<a.length;s+=16){o=h[0];p=h[1];q=h[2];n=h[3];
|
||||
k=h[4];j=h[5];l=h[6];m=h[7];for(r=0;r<64;r++)f[r]=r<16?a[r+s]:b(b(b(c(f[r-2],17)^c(f[r-2],19)^f[r-2]>>>10,f[r-7]),c(f[r-15],7)^c(f[r-15],18)^f[r-15]>>>3),f[r-16]),u=b(b(b(b(m,c(k,6)^c(k,11)^c(k,25)),k&j^~k&l),g[r]),f[r]),w=b(c(o,2)^c(o,13)^c(o,22),o&p^o&q^p&q),m=l,l=j,j=k,k=b(n,u),n=q,q=p,p=o,o=b(u,w);h[0]=b(o,h[0]);h[1]=b(p,h[1]);h[2]=b(q,h[2]);h[3]=b(n,h[3]);h[4]=b(k,h[4]);h[5]=b(j,h[5]);h[6]=b(l,h[6]);h[7]=b(m,h[7])}return h}(function(a){for(var b=[],c=0;c<a.length*8;c+=8)b[c>>5]|=(a.charCodeAt(c/
|
||||
8)&255)<<24-c%32;return b}(a),a.length*8))}var sha256={hex:function(a){return SHA256(a)}};
|
||||
function SHA1(a){function b(a,b){return a<<b|a>>>32-b}function c(a){var b="",c,d;for(c=7;c>=0;c--)d=a>>>c*4&15,b+=d.toString(16);return b}var d,e,g=Array(80),h=1732584193,f=4023233417,o=2562383102,p=271733878,q=3285377520,n,k,j,l,m,a=function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var d=a.charCodeAt(c);d<128?b+=String.fromCharCode(d):(d>127&&d<2048?b+=String.fromCharCode(d>>6|192):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128)),b+=String.fromCharCode(d&
|
||||
63|128))}return b}(a);n=a.length;var s=[];for(d=0;d<n-3;d+=4)e=a.charCodeAt(d)<<24|a.charCodeAt(d+1)<<16|a.charCodeAt(d+2)<<8|a.charCodeAt(d+3),s.push(e);switch(n%4){case 0:d=2147483648;break;case 1:d=a.charCodeAt(n-1)<<24|8388608;break;case 2:d=a.charCodeAt(n-2)<<24|a.charCodeAt(n-1)<<16|32768;break;case 3:d=a.charCodeAt(n-3)<<24|a.charCodeAt(n-2)<<16|a.charCodeAt(n-1)<<8|128}for(s.push(d);s.length%16!=14;)s.push(0);s.push(n>>>29);s.push(n<<3&4294967295);for(a=0;a<s.length;a+=16){for(d=0;d<16;d++)g[d]=
|
||||
s[a+d];for(d=16;d<=79;d++)g[d]=b(g[d-3]^g[d-8]^g[d-14]^g[d-16],1);e=h;n=f;k=o;j=p;l=q;for(d=0;d<=19;d++)m=b(e,5)+(n&k|~n&j)+l+g[d]+1518500249&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;for(d=20;d<=39;d++)m=b(e,5)+(n^k^j)+l+g[d]+1859775393&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;for(d=40;d<=59;d++)m=b(e,5)+(n&k|n&j|k&j)+l+g[d]+2400959708&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;for(d=60;d<=79;d++)m=b(e,5)+(n^k^j)+l+g[d]+3395469782&4294967295,l=j,j=k,k=b(n,30),n=e,e=m;h=h+e&4294967295;f=f+n&4294967295;o=o+k&4294967295;
|
||||
p=p+j&4294967295;q=q+l&4294967295}m=c(h)+c(f)+c(o)+c(p)+c(q);return m.toLowerCase()}
|
||||
var sha1={hex:function(a){return SHA1(a)}},MD5=function(a){function b(a,b){var c,d,e,f,g;e=a&2147483648;f=b&2147483648;c=a&1073741824;d=b&1073741824;g=(a&1073741823)+(b&1073741823);return c&d?g^2147483648^e^f:c|d?g&1073741824?g^3221225472^e^f:g^1073741824^e^f:g^e^f}function c(a,c,d,e,f,g,h){a=b(a,b(b(c&d|~c&e,f),h));return b(a<<g|a>>>32-g,c)}function d(a,c,d,e,f,g,h){a=b(a,b(b(c&e|d&~e,f),h));return b(a<<g|a>>>32-g,c)}function e(a,c,d,e,f,g,h){a=b(a,b(b(c^d^e,f),h));return b(a<<g|a>>>32-g,c)}function g(a,
|
||||
c,d,e,f,g,h){a=b(a,b(b(d^(c|~e),f),h));return b(a<<g|a>>>32-g,c)}function h(a){var b="",c="",d;for(d=0;d<=3;d++)c=a>>>d*8&255,c="0"+c.toString(16),b+=c.substr(c.length-2,2);return b}var f=[],o,p,q,n,k,j,l,m,a=function(a){for(var a=a.replace(/\r\n/g,"\n"),b="",c=0;c<a.length;c++){var d=a.charCodeAt(c);d<128?b+=String.fromCharCode(d):(d>127&&d<2048?b+=String.fromCharCode(d>>6|192):(b+=String.fromCharCode(d>>12|224),b+=String.fromCharCode(d>>6&63|128)),b+=String.fromCharCode(d&63|128))}return b}(a),
|
||||
f=function(a){var b,c=a.length;b=c+8;for(var d=((b-b%64)/64+1)*16,e=Array(d-1),f=0,g=0;g<c;)b=(g-g%4)/4,f=g%4*8,e[b]|=a.charCodeAt(g)<<f,g++;e[(g-g%4)/4]|=128<<g%4*8;e[d-2]=c<<3;e[d-1]=c>>>29;return e}(a);k=1732584193;j=4023233417;l=2562383102;m=271733878;for(a=0;a<f.length;a+=16)o=k,p=j,q=l,n=m,k=c(k,j,l,m,f[a+0],7,3614090360),m=c(m,k,j,l,f[a+1],12,3905402710),l=c(l,m,k,j,f[a+2],17,606105819),j=c(j,l,m,k,f[a+3],22,3250441966),k=c(k,j,l,m,f[a+4],7,4118548399),m=c(m,k,j,l,f[a+5],12,1200080426),l=c(l,
|
||||
m,k,j,f[a+6],17,2821735955),j=c(j,l,m,k,f[a+7],22,4249261313),k=c(k,j,l,m,f[a+8],7,1770035416),m=c(m,k,j,l,f[a+9],12,2336552879),l=c(l,m,k,j,f[a+10],17,4294925233),j=c(j,l,m,k,f[a+11],22,2304563134),k=c(k,j,l,m,f[a+12],7,1804603682),m=c(m,k,j,l,f[a+13],12,4254626195),l=c(l,m,k,j,f[a+14],17,2792965006),j=c(j,l,m,k,f[a+15],22,1236535329),k=d(k,j,l,m,f[a+1],5,4129170786),m=d(m,k,j,l,f[a+6],9,3225465664),l=d(l,m,k,j,f[a+11],14,643717713),j=d(j,l,m,k,f[a+0],20,3921069994),k=d(k,j,l,m,f[a+5],5,3593408605),
|
||||
m=d(m,k,j,l,f[a+10],9,38016083),l=d(l,m,k,j,f[a+15],14,3634488961),j=d(j,l,m,k,f[a+4],20,3889429448),k=d(k,j,l,m,f[a+9],5,568446438),m=d(m,k,j,l,f[a+14],9,3275163606),l=d(l,m,k,j,f[a+3],14,4107603335),j=d(j,l,m,k,f[a+8],20,1163531501),k=d(k,j,l,m,f[a+13],5,2850285829),m=d(m,k,j,l,f[a+2],9,4243563512),l=d(l,m,k,j,f[a+7],14,1735328473),j=d(j,l,m,k,f[a+12],20,2368359562),k=e(k,j,l,m,f[a+5],4,4294588738),m=e(m,k,j,l,f[a+8],11,2272392833),l=e(l,m,k,j,f[a+11],16,1839030562),j=e(j,l,m,k,f[a+14],23,4259657740),
|
||||
k=e(k,j,l,m,f[a+1],4,2763975236),m=e(m,k,j,l,f[a+4],11,1272893353),l=e(l,m,k,j,f[a+7],16,4139469664),j=e(j,l,m,k,f[a+10],23,3200236656),k=e(k,j,l,m,f[a+13],4,681279174),m=e(m,k,j,l,f[a+0],11,3936430074),l=e(l,m,k,j,f[a+3],16,3572445317),j=e(j,l,m,k,f[a+6],23,76029189),k=e(k,j,l,m,f[a+9],4,3654602809),m=e(m,k,j,l,f[a+12],11,3873151461),l=e(l,m,k,j,f[a+15],16,530742520),j=e(j,l,m,k,f[a+2],23,3299628645),k=g(k,j,l,m,f[a+0],6,4096336452),m=g(m,k,j,l,f[a+7],10,1126891415),l=g(l,m,k,j,f[a+14],15,2878612391),
|
||||
j=g(j,l,m,k,f[a+5],21,4237533241),k=g(k,j,l,m,f[a+12],6,1700485571),m=g(m,k,j,l,f[a+3],10,2399980690),l=g(l,m,k,j,f[a+10],15,4293915773),j=g(j,l,m,k,f[a+1],21,2240044497),k=g(k,j,l,m,f[a+8],6,1873313359),m=g(m,k,j,l,f[a+15],10,4264355552),l=g(l,m,k,j,f[a+6],15,2734768916),j=g(j,l,m,k,f[a+13],21,1309151649),k=g(k,j,l,m,f[a+4],6,4149444226),m=g(m,k,j,l,f[a+11],10,3174756917),l=g(l,m,k,j,f[a+2],15,718787259),j=g(j,l,m,k,f[a+9],21,3951481745),k=b(k,o),j=b(j,p),l=b(l,q),m=b(m,n);return(h(k)+h(j)+h(l)+
|
||||
h(m)).toLowerCase()};function parseBigInt(a,b){return new BigInteger(a,b)}function linebrk(a,b){for(var c="",d=0;d+b<a.length;)c+=a.substring(d,d+b)+"\n",d+=b;return c+a.substring(d,a.length)}function byte2Hex(a){return a<16?"0"+a.toString(16):a.toString(16)}
|
||||
function pkcs1pad2(a,b){if(b<a.length+11)throw"Message too long for RSA (n="+b+", l="+a.length+")";for(var c=[],d=a.length-1;d>=0&&b>0;){var e=a.charCodeAt(d--);e<128?c[--b]=e:e>127&&e<2048?(c[--b]=e&63|128,c[--b]=e>>6|192):(c[--b]=e&63|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;d=new SecureRandom;for(e=[];b>2;){for(e[0]=0;e[0]==0;)d.nextBytes(e);c[--b]=e[0]}c[--b]=2;c[--b]=0;return new BigInteger(c)}
|
||||
function RSAKey(){this.n=null;this.e=0;this.coeff=this.dmq1=this.dmp1=this.q=this.p=this.d=null}function RSASetPublic(a,b){a!=null&&b!=null&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):alert("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(a){a=pkcs1pad2(a,this.n.bitLength()+7>>3);if(a==null)return null;a=this.doPublic(a);if(a==null)return null;a=a.toString(16);return(a.length&1)==0?a:"0"+a}
|
||||
RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;function pkcs1unpad2(a,b){for(var c=a.toByteArray(),d=0;d<c.length&&c[d]==0;)++d;if(c.length-d!=b-1||c[d]!=2)return null;for(++d;c[d]!=0;)if(++d>=c.length)return null;for(var e="";++d<c.length;){var g=c[d]&255;g<128?e+=String.fromCharCode(g):g>191&&g<224?(e+=String.fromCharCode((g&31)<<6|c[d+1]&63),++d):(e+=String.fromCharCode((g&15)<<12|(c[d+1]&63)<<6|c[d+2]&63),d+=2)}return e}
|
||||
function RSASetPrivate(a,b,c){a!=null&&b!=null&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):alert("Invalid RSA private key")}
|
||||
function RSASetPrivateEx(a,b,c,d,e,g,h,f){a!=null&&b!=null&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(g,16),this.dmq1=parseBigInt(h,16),this.coeff=parseBigInt(f,16)):alert("Invalid RSA private key")}
|
||||
function RSAGenerate(a,b){var c=new SeededRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;;)if(this.p=new BigInteger(a-d,1,c),this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)==0&&this.p.isProbablePrime(10))break;for(;;)if(this.q=new BigInteger(d,1,c),this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)==0&&this.q.isProbablePrime(10))break;if(this.p.compareTo(this.q)<=0){var g=this.p;this.p=this.q;this.q=g}var g=this.p.subtract(BigInteger.ONE),
|
||||
h=this.q.subtract(BigInteger.ONE),f=g.multiply(h);if(f.gcd(e).compareTo(BigInteger.ONE)==0){this.n=this.p.multiply(this.q);this.d=e.modInverse(f);this.dmp1=this.d.mod(g);this.dmq1=this.d.mod(h);this.coeff=this.q.modInverse(this.p);break}}}
|
||||
function RSADoPrivate(a){if(this.p==null||this.q==null)return a.modPow(this.d,this.n);for(var b=a.mod(this.p).modPow(this.dmp1,this.p),a=a.mod(this.q).modPow(this.dmq1,this.q);b.compareTo(a)<0;)b=b.add(this.p);return b.subtract(a).multiply(this.coeff).mod(this.p).multiply(this.q).add(a)}function RSADecrypt(a){a=this.doPrivate(parseBigInt(a,16));return a==null?null:pkcs1unpad2(a,this.n.bitLength()+7>>3)}RSAKey.prototype.doPrivate=RSADoPrivate;RSAKey.prototype.setPrivate=RSASetPrivate;
|
||||
RSAKey.prototype.setPrivateEx=RSASetPrivateEx;RSAKey.prototype.generate=RSAGenerate;RSAKey.prototype.decrypt=RSADecrypt;var _RSASIGN_DIHEAD=[];_RSASIGN_DIHEAD.sha1="3021300906052b0e03021a05000414";_RSASIGN_DIHEAD.sha256="3031300d060960864801650304020105000420";var _RSASIGN_HASHHEXFUNC=[];_RSASIGN_HASHHEXFUNC.sha1=sha1.hex;_RSASIGN_HASHHEXFUNC.sha256=sha256.hex;
|
||||
function _rsasign_getHexPaddedDigestInfoForString(a,b,c){b/=4;for(var a=(0,_RSASIGN_HASHHEXFUNC[c])(a),c="00"+_RSASIGN_DIHEAD[c]+a,a="",b=b-4-c.length,d=0;d<b;d+=2)a+="ff";return sPaddedMessageHex="0001"+a+c}function _rsasign_signString(a,b){var c=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),b);return this.doPrivate(parseBigInt(c,16)).toString(16)}
|
||||
function _rsasign_signStringWithSHA1(a){a=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),"sha1");return this.doPrivate(parseBigInt(a,16)).toString(16)}function _rsasign_signStringWithSHA256(a){a=_rsasign_getHexPaddedDigestInfoForString(a,this.n.bitLength(),"sha256");return this.doPrivate(parseBigInt(a,16)).toString(16)}function _rsasign_getDecryptSignatureBI(a,b,c){var d=new RSAKey;d.setPublic(b,c);return d.doPublic(a)}
|
||||
function _rsasign_getHexDigestInfoFromSig(a,b,c){return _rsasign_getDecryptSignatureBI(a,b,c).toString(16).replace(/^1f+00/,"")}function _rsasign_getAlgNameAndHashFromHexDisgestInfo(a){for(var b in _RSASIGN_DIHEAD){var c=_RSASIGN_DIHEAD[b],d=c.length;if(a.substring(0,d)==c)return[b,a.substring(d)]}return[]}
|
||||
function _rsasign_verifySignatureWithArgs(a,b,c,d){b=_rsasign_getHexDigestInfoFromSig(b,c,d);c=_rsasign_getAlgNameAndHashFromHexDisgestInfo(b);if(c.length==0)return!1;b=c[1];a=(0,_RSASIGN_HASHHEXFUNC[c[0]])(a);return b==a}function _rsasign_verifyHexSignatureForMessage(a,b){var c=parseBigInt(a,16);return _rsasign_verifySignatureWithArgs(b,c,this.n.toString(16),this.e.toString(16))}
|
||||
function _rsasign_verifyString(a,b){var b=b.replace(/[ \n]+/g,""),c=this.doPublic(parseBigInt(b,16)).toString(16).replace(/^1f+00/,""),d=_rsasign_getAlgNameAndHashFromHexDisgestInfo(c);if(d.length==0)return!1;c=d[1];d=(0,_RSASIGN_HASHHEXFUNC[d[0]])(a);return c==d}RSAKey.prototype.signString=_rsasign_signString;RSAKey.prototype.signStringWithSHA1=_rsasign_signStringWithSHA1;RSAKey.prototype.signStringWithSHA256=_rsasign_signStringWithSHA256;RSAKey.prototype.verifyString=_rsasign_verifyString;
|
||||
RSAKey.prototype.verifyHexSignatureForMessage=_rsasign_verifyHexSignatureForMessage;
|
||||
var aes=function(){var a={Sbox:[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,
|
||||
95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22],ShiftRowTab:[0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11]};a.Init=
|
||||
function(){a.Sbox_Inv=Array(256);for(var b=0;b<256;b++)a.Sbox_Inv[a.Sbox[b]]=b;a.ShiftRowTab_Inv=Array(16);for(b=0;b<16;b++)a.ShiftRowTab_Inv[a.ShiftRowTab[b]]=b;a.xtime=Array(256);for(b=0;b<128;b++)a.xtime[b]=b<<1,a.xtime[128+b]=b<<1^27};a.Done=function(){delete a.Sbox_Inv;delete a.ShiftRowTab_Inv;delete a.xtime};a.ExpandKey=function(b){var c=b.length,d,e=1;switch(c){case 16:d=176;break;case 24:d=208;break;case 32:d=240;break;default:alert("my.ExpandKey: Only key lengths of 16, 24 or 32 bytes allowed!")}for(var g=
|
||||
c;g<d;g+=4){var h=b.slice(g-4,g);if(g%c==0){if(h=[a.Sbox[h[1]]^e,a.Sbox[h[2]],a.Sbox[h[3]],a.Sbox[h[0]]],(e<<=1)>=256)e^=283}else c>24&&g%c==16&&(h=[a.Sbox[h[0]],a.Sbox[h[1]],a.Sbox[h[2]],a.Sbox[h[3]]]);for(var f=0;f<4;f++)b[g+f]=b[g+f-c]^h[f]}};a.Encrypt=function(b,c){var d=c.length;a.AddRoundKey(b,c.slice(0,16));for(var e=16;e<d-16;e+=16)a.SubBytes(b,a.Sbox),a.ShiftRows(b,a.ShiftRowTab),a.MixColumns(b),a.AddRoundKey(b,c.slice(e,e+16));a.SubBytes(b,a.Sbox);a.ShiftRows(b,a.ShiftRowTab);a.AddRoundKey(b,
|
||||
c.slice(e,d))};a.Decrypt=function(b,c){var d=c.length;a.AddRoundKey(b,c.slice(d-16,d));a.ShiftRows(b,a.ShiftRowTab_Inv);a.SubBytes(b,a.Sbox_Inv);for(d-=32;d>=16;d-=16)a.AddRoundKey(b,c.slice(d,d+16)),a.MixColumns_Inv(b),a.ShiftRows(b,a.ShiftRowTab_Inv),a.SubBytes(b,a.Sbox_Inv);a.AddRoundKey(b,c.slice(0,16))};a.SubBytes=function(a,c){for(var d=0;d<16;d++)a[d]=c[a[d]]};a.AddRoundKey=function(a,c){for(var d=0;d<16;d++)a[d]^=c[d]};a.ShiftRows=function(a,c){for(var d=[].concat(a),e=0;e<16;e++)a[e]=d[c[e]]};
|
||||
a.MixColumns=function(b){for(var c=0;c<16;c+=4){var d=b[c+0],e=b[c+1],g=b[c+2],h=b[c+3],f=d^e^g^h;b[c+0]^=f^a.xtime[d^e];b[c+1]^=f^a.xtime[e^g];b[c+2]^=f^a.xtime[g^h];b[c+3]^=f^a.xtime[h^d]}};a.MixColumns_Inv=function(b){for(var c=0;c<16;c+=4){var d=b[c+0],e=b[c+1],g=b[c+2],h=b[c+3],f=d^e^g^h,o=a.xtime[f],p=a.xtime[a.xtime[o^d^g]]^f;f^=a.xtime[a.xtime[o^e^h]];b[c+0]^=p^a.xtime[d^e];b[c+1]^=f^a.xtime[e^g];b[c+2]^=p^a.xtime[g^h];b[c+3]^=f^a.xtime[h^d]}};return a}(),cryptico=function(){var a={};aes.Init();
|
||||
a.b256to64=function(a){var c,d,e,g="",h=0,f=0,o=a.length;for(e=0;e<o;e++)d=a.charCodeAt(e),f==0?(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d>>2&63),c=(d&3)<<4):f==1?(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c|d>>4&15),c=(d&15)<<2):f==2&&(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c|d>>6&3),h+=1,g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d&63)),h+=1,f+=1,f==3&&
|
||||
(f=0);f>0&&(g+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(c),g+="=");f==1&&(g+="=");return g};a.b64to256=function(a){var c,d,e="",g=0,h=0,f=a.length;for(d=0;d<f;d++)c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(d)),c>=0&&(g&&(e+=String.fromCharCode(h|c>>6-g&255)),g=g+2&7,h=c<<g&255);return e};a.b16to64=function(a){var c,d,e="";a.length%2==1&&(a="0"+a);for(c=0;c+3<=a.length;c+=3)d=parseInt(a.substring(c,c+3),16),e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d>>
|
||||
6)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d&63);c+1==a.length?(d=parseInt(a.substring(c,c+1),16),e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d<<2)):c+2==a.length&&(d=parseInt(a.substring(c,c+2),16),e+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(d>>2)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((d&3)<<4));for(;(e.length&3)>0;)e+="=";return e};a.b64to16=function(a){var c="",
|
||||
d,e=0,g;for(d=0;d<a.length;++d){if(a.charAt(d)=="=")break;v="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(a.charAt(d));v<0||(e==0?(c+=int2char(v>>2),g=v&3,e=1):e==1?(c+=int2char(g<<2|v>>4),g=v&15,e=2):e==2?(c+=int2char(g),c+=int2char(v>>2),g=v&3,e=3):(c+=int2char(g<<2|v>>4),c+=int2char(v&15),e=0))}e==1&&(c+=int2char(g<<2));return c};a.string2bytes=function(a){for(var c=[],d=0;d<a.length;d++)c.push(a.charCodeAt(d));return c};a.bytes2string=function(a){for(var c="",d=0;d<
|
||||
a.length;d++)c+=String.fromCharCode(a[d]);return c};a.blockXOR=function(a,c){for(var d=Array(16),e=0;e<16;e++)d[e]=a[e]^c[e];return d};a.blockIV=function(){var a=new SecureRandom,c=Array(16);a.nextBytes(c);return c};a.pad16=function(a){var c=a.slice(0),d=(16-a.length%16)%16;for(i=a.length;i<a.length+d;i++)c.push(0);return c};a.depad=function(a){for(a=a.slice(0);a[a.length-1]==0;)a=a.slice(0,a.length-1);return a};a.encryptAESCBC=function(b,c){var d=c.slice(0);aes.ExpandKey(d);for(var e=a.string2bytes(b),
|
||||
e=a.pad16(e),g=a.blockIV(),h=0;h<e.length/16;h++){var f=e.slice(h*16,h*16+16),o=g.slice(h*16,h*16+16),f=a.blockXOR(o,f);aes.Encrypt(f,d);g=g.concat(f)}d=a.bytes2string(g);return a.b256to64(d)};a.decryptAESCBC=function(b,c){var d=c.slice(0);aes.ExpandKey(d);for(var b=a.b64to256(b),e=a.string2bytes(b),g=[],h=1;h<e.length/16;h++){var f=e.slice(h*16,h*16+16),o=e.slice((h-1)*16,(h-1)*16+16);aes.Decrypt(f,d);f=a.blockXOR(o,f);g=g.concat(f)}g=a.depad(g);return a.bytes2string(g)};a.wrap60=function(a){for(var c=
|
||||
"",d=0;d<a.length;d++)d%60==0&&d!=0&&(c+="\n"),c+=a[d];return c};a.generateAESKey=function(){var a=Array(16);(new SecureRandom).nextBytes(a);return a};a.generateRSAKey=function(a,c){Math.seedrandom(sha256.hex(a));var d=new RSAKey;d.generate(c,"10001");return d};a.publicKeyString=function(b){return pubkey=b.n.toString(16)};a.publicKeyID=function(a){return MD5(a)};a.publicKeyFromString=function(b){var b=b.split("|")[0],c=new RSAKey;c.setPublic(b,"10001");return c};a.encrypt=function(b,
|
||||
c,d){var e="";try{var h=a.publicKeyFromString(c);e+=h.encrypt(b)+"?"}catch(f){return{status:"Invalid public key"}};return{status:"success",cipher:e}};a.decrypt=function(b,c){var d=b.split("?"),e=c.decrypt(d[0]);return{status:"success",plaintext:e,signature:"unsigned"}};return a}();
|
||||
35
public/vendor/hikvision/encryption/crypto-3.1.2.min.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
|
||||
r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k<a;k++)c[j+k>>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535<e.length)for(k=0;k<a;k+=4)c[j+k>>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
|
||||
32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e<a;e+=4)c.push(4294967296*u.random()|0);return new r.init(c,a)}}),w=d.enc={},v=w.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++){var k=c[j>>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j+=2)e[j>>>3]|=parseInt(a.substr(j,
|
||||
2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++)e.push(String.fromCharCode(c[j>>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j++)e[j>>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}},
|
||||
q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q<a;q+=k)this._doProcessBlock(e,q);q=e.splice(0,a);c.sigBytes-=j}return new r.init(q,j)},clone:function(){var a=t.clone.call(this);
|
||||
a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=q.extend({cfg:t.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,e){return(new a.init(e)).finalize(b)}},_createHmacHelper:function(a){return function(b,e){return(new n.HMAC.init(a,
|
||||
e)).finalize(b)}}});var n=d.algo={};return d}(Math);
|
||||
(function(){var u=CryptoJS,p=u.lib.WordArray;u.enc.Base64={stringify:function(d){var l=d.words,p=d.sigBytes,t=this._map;d.clamp();d=[];for(var r=0;r<p;r+=3)for(var w=(l[r>>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v<p;v++)d.push(t.charAt(w>>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<
|
||||
l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
|
||||
(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<<j|b>>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<<j|b>>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<<j|b>>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<<j|b>>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])},
|
||||
_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),
|
||||
f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,
|
||||
m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,
|
||||
E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/
|
||||
4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math);
|
||||
(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length<q;){n&&s.update(n);var n=s.update(d).finalize(r);s.reset();for(var a=1;a<p;a++)n=s.finalize(n),s.reset();b.concat(n)}b.sigBytes=4*q;return b}});u.EvpKDF=function(d,l,p){return s.create(p).compute(d,
|
||||
l)}})();
|
||||
CryptoJS.lib.Cipher||function(u){var p=CryptoJS,d=p.lib,l=d.Base,s=d.WordArray,t=d.BufferedBlockAlgorithm,r=p.enc.Base64,w=p.algo.EvpKDF,v=d.Cipher=t.extend({cfg:l.extend(),createEncryptor:function(e,a){return this.create(this._ENC_XFORM_MODE,e,a)},createDecryptor:function(e,a){return this.create(this._DEC_XFORM_MODE,e,a)},init:function(e,a,b){this.cfg=this.cfg.extend(b);this._xformMode=e;this._key=a;this.reset()},reset:function(){t.reset.call(this);this._doReset()},process:function(e){this._append(e);return this._process()},
|
||||
finalize:function(e){e&&this._append(e);return this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(e){return{encrypt:function(b,k,d){return("string"==typeof k?c:a).encrypt(e,b,k,d)},decrypt:function(b,k,d){return("string"==typeof k?c:a).decrypt(e,b,k,d)}}}});d.StreamCipher=v.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var b=p.mode={},x=function(e,a,b){var c=this._iv;c?this._iv=u:c=this._prevBlock;for(var d=0;d<b;d++)e[a+d]^=
|
||||
c[d]},q=(d.BlockCipherMode=l.extend({createEncryptor:function(e,a){return this.Encryptor.create(e,a)},createDecryptor:function(e,a){return this.Decryptor.create(e,a)},init:function(e,a){this._cipher=e;this._iv=a}})).extend();q.Encryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize;x.call(this,e,a,c);b.encryptBlock(e,a);this._prevBlock=e.slice(a,a+c)}});q.Decryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize,d=e.slice(a,a+c);b.decryptBlock(e,a);x.call(this,
|
||||
e,a,c);this._prevBlock=d}});b=b.CBC=q;q=(p.pad={}).Pkcs7={pad:function(a,b){for(var c=4*b,c=c-a.sigBytes%c,d=c<<24|c<<16|c<<8|c,l=[],n=0;n<c;n+=4)l.push(d);c=s.create(l,c);a.concat(c)},unpad:function(a){a.sigBytes-=a.words[a.sigBytes-1>>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a,
|
||||
this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,
|
||||
1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},
|
||||
decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,
|
||||
b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();
|
||||
(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,
|
||||
16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j<a;j++)if(j<d)e[j]=c[j];else{var k=e[j-1];j%d?6<d&&4==j%d&&(k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;d<a;d++)j=a-d,k=d%4?e[j]:e[j-4],c[d]=4>d||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>
|
||||
8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r<m;r++)var q=d[g>>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=
|
||||
d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})();
|
||||
2
public/vendor/hikvision/jsPlugin/jquery.min.js
vendored
Normal file
301
public/vendor/hikvision/jsPlugin/jsPlugin-3.0.0.min.js
vendored
Normal file
174
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV1/Decoder.js
vendored
Normal file
21
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3/Decoder.js
vendored
Normal file
BIN
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3/Decoder.wasm
vendored
Normal file
1
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3/Decoder.worker.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}JSPlayerModule(Module)}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage;
|
||||
21
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3_NoSIMD/Decoder.js
vendored
Normal file
BIN
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3_NoSIMD/Decoder.wasm
vendored
Normal file
1
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3_NoSIMD/Decoder.worker.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}JSPlayerModule(Module)}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage;
|
||||
21
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3_NoWorker/Decoder.js
vendored
Normal file
BIN
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/playctrlV3_NoWorker/Decoder.wasm
vendored
Normal file
1
public/vendor/hikvision/jsPlugin/playctrl/PlayCtrlWasm/wasmplayer.min.js
vendored
Normal file
6630
public/vendor/hikvision/jsPlugin/transform/libSystemTransform.js
vendored
Normal file
BIN
public/vendor/hikvision/jsPlugin/transform/libSystemTransform.wasm
vendored
Normal file
240
public/vendor/hikvision/jsPlugin/transform/systemTransform-worker.js
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
importScripts('libSystemTransform.js');
|
||||
const RECORDRTP = 0; //录制一份未经过转封装的码流原始数据,用于定位问题
|
||||
let dataType = 1;
|
||||
|
||||
// 字母字符串转byte数组
|
||||
function stringToBytes (str) {
|
||||
var ch;
|
||||
var st;
|
||||
var re = [];
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
ch = str.charCodeAt(i); // get char
|
||||
st = []; // set up "stack"
|
||||
do {
|
||||
st.push(ch & 0xFF); // push byte to stack
|
||||
ch = ch >> 8; // shift value down by 1 byte
|
||||
}
|
||||
while (ch);
|
||||
// add stack contents to result
|
||||
// done because chars have "wrong" endianness
|
||||
re = re.concat(st.reverse());
|
||||
}
|
||||
// return an array of bytes
|
||||
return re;
|
||||
}
|
||||
|
||||
// 转封装库回调函数
|
||||
self.STCallBack = function (fileIndex, indexLen, data, dataLen) {
|
||||
//stFrameInfo的类型见DETAIL_FRAME_INFO
|
||||
let stFrameInfo = Module._GetDetialFrameInfo();
|
||||
let nIsMp4Index = stFrameInfo.nIsMp4Index;
|
||||
|
||||
//console.log("FrameType is " , stFrameInfo);
|
||||
//console.log("nIsMp4Index is " + nIsMp4Index);
|
||||
//debugger
|
||||
var pData = null;
|
||||
pData = new Uint8Array(dataLen);
|
||||
pData.set(Module.HEAPU8.subarray(data, data + dataLen));
|
||||
if (dataType === 1) {
|
||||
postMessage({ type: "outputData",
|
||||
buf: pData.buffer,
|
||||
dType: 1,
|
||||
frameInfo: stFrameInfo }, [pData.buffer]);
|
||||
dataType = 2;
|
||||
} else {
|
||||
if (nIsMp4Index) {
|
||||
postMessage({ type: "outputData",
|
||||
buf: pData.buffer,
|
||||
dType: 6,
|
||||
frameInfo: stFrameInfo }, [pData.buffer]); //6:索引类型
|
||||
} else {
|
||||
postMessage({ type: "outputData",
|
||||
buf: pData.buffer,
|
||||
dType: 2,
|
||||
frameInfo: stFrameInfo }, [pData.buffer]); //2:码流
|
||||
}
|
||||
}
|
||||
|
||||
//stFrameInfo的类型见DETAIL_FRAME_INFO
|
||||
//let stFrameInfo = Module._GetDetialFrameInfo();
|
||||
//let stFrameType = stFrameInfo.nFrameType;
|
||||
//let nFrameNum = stFrameInfo.nFrameNum;
|
||||
//let nTimeStamp = stFrameInfo.nTimeStamp;
|
||||
//let nIsMp4Index = stFrameInfo.nIsMp4Index;
|
||||
|
||||
//console.log("FrameType is " + stFrameType);
|
||||
//console.log("nIsMp4Index is " + nIsMp4Index);
|
||||
};
|
||||
|
||||
// self.Module = { memoryInitializerRequest: loadMemInitFile(), TOTAL_MEMORY: 128*1024*1024 };
|
||||
// importScripts('SystemTransform.js');
|
||||
|
||||
self.Module['onRuntimeInitialized'] = function () {
|
||||
postMessage({type: "loaded"});
|
||||
};
|
||||
onmessage = function (e) {
|
||||
var data = e.data;
|
||||
if ("create" === data.type) {
|
||||
if (RECORDRTP) {
|
||||
postMessage({ type: "created" });
|
||||
postMessage({ type: "outputData",
|
||||
buf: data.buf,
|
||||
dType: 1 }, [data.buf]);
|
||||
} else {
|
||||
var iHeadLen = data.len;
|
||||
var pHead = Module._malloc(iHeadLen);
|
||||
if (pHead === null) {
|
||||
console.log("inputdata malloc failed!!!");
|
||||
return -1;
|
||||
}
|
||||
var iTransType = data.packType;//目标格式
|
||||
var iRet = 0;
|
||||
var buf = new Uint8Array(data.buf);
|
||||
//PS流(只有ps支持探测),并且编码格式异常(正常是265和264,11位和10位 不可能全是0,全0 并且是ps就探测策略)的情况下,使用探测策略
|
||||
if (buf[9] === 0 && buf[8] === 2 && buf[11] === 0 && buf[10] === 0) {
|
||||
iRet = Module._CreatHandle(0, iTransType, iHeadLen); //用探测的策略
|
||||
} else {
|
||||
self.writeArrayToMemory(buf, pHead);
|
||||
iRet = Module._CreatHandle(pHead, iTransType, iHeadLen);
|
||||
//-2147483645代表的是参数错误,此种情况,大概率发生在头信息错误,例如大华设备的情况,此时用 无头探测的策略
|
||||
//其他情况 按海康标准处理流程,不要做任何特殊处理
|
||||
if (iRet == -2147483645) {
|
||||
iRet = Module._CreatHandle(0, iTransType, iHeadLen); //失败了,用探测的策略再试一次
|
||||
}
|
||||
}
|
||||
if (iRet != 0) {
|
||||
if (iRet == -2147483647) {
|
||||
postMessage({ type: "outputData",
|
||||
dType: 1501 }); //标记为格式不支持
|
||||
} else {
|
||||
postMessage({ type: "outputData",
|
||||
dType: 1501 }); //转封装创建失败,也同样提示码流格式不支持,如果后续要细化再区分
|
||||
}
|
||||
console.log("_CreatHandle failed!" + iRet);
|
||||
} else {
|
||||
if (data.options && typeof data.options.pKeyData !== "undefined" && data.options.pKeyData !== null) {
|
||||
if ((2 === iTransType && "" === data.options.pKeyData)) {
|
||||
//转ps的时候,如果密码是空是允许的,即使码流加密了,导出加密后的码流就行
|
||||
//此时不要设置密码否则反而会提示密码错误
|
||||
} else {
|
||||
var secretInfo = data.options;
|
||||
var keyLen = secretInfo.nKeyLen;
|
||||
var pKeyData = Module._malloc(keyLen);
|
||||
if (pKeyData === null) {
|
||||
console.log("setEncryptKey malloc failed!!!");
|
||||
return -1;
|
||||
}
|
||||
var nKeySize = secretInfo.pKeyData.length;
|
||||
var bufData = stringToBytes(secretInfo.pKeyData);
|
||||
|
||||
let inputData = new Uint8Array(bufData);
|
||||
Module.writeArrayToMemory(inputData, pKeyData);
|
||||
inputData = null;
|
||||
|
||||
iRet = Module._SysTransSetEncryptKey(secretInfo.nKeyType, pKeyData, keyLen, nKeySize);
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransSetEncryptKey failed!");
|
||||
}
|
||||
if (pKeyData != null) {
|
||||
Module._free(pKeyData);
|
||||
pKeyData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
//带samplingParam参数,代表需要 用到 音频替换功能
|
||||
if (data.options && typeof data.options.samplingParam !== "undefined") {
|
||||
var oParam = data.options.samplingParam;
|
||||
var nCapacityType = 1; //写死1 代表 剔除音频
|
||||
var nType = 3; //写死3 代表 修改输出目标的海康头配置,内部包含视频参数、音频参数
|
||||
var nAudioEnable = 1; //音频参数修改使能开关,0=不启用,1=启用
|
||||
var nAudioFormat = oParam.iAudioType; //音频编码类型 对应关系参考海康媒体头规范,PCM 0x7001 G711_U 0x7110 G711_A 0x7111 AAC 0x2001
|
||||
var nAudioChannels = oParam.iChannel; //音频通道数直接设置为
|
||||
var nAudioBitsPerSample = oParam.iAudioBitWidth; //音频位样率
|
||||
var nAudioSamplesrate = oParam.iAudioSamplingRate; //音频采样率
|
||||
var nAudioBitrate = oParam.iAudioBitRate; //音频比特率
|
||||
iRet = Module._SysTransConfig(nCapacityType, nType, nAudioEnable, nAudioFormat,
|
||||
nAudioChannels, nAudioBitsPerSample, nAudioSamplesrate, nAudioBitrate);
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransConfig Failed:" + iRet);
|
||||
}
|
||||
} else {
|
||||
iRet = Module._SysTransConfig(128, 0, 0, 0, 0, 0, 0, 0); //nCapacityType = 0x00000080 代表开启私有信息回调 解决转mp4后,私有信息丢失问题
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransConfig Failed:" + iRet);
|
||||
}
|
||||
}
|
||||
iRet = Module._SysTransRegisterDataCallBack();
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransRegisterDataCallBack Failed:" + iRet);
|
||||
}
|
||||
|
||||
iRet = Module._SysTransStart(null, null);
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransStart Failed:" + iRet);
|
||||
}
|
||||
postMessage({type: "created"});
|
||||
}
|
||||
if (pHead != null) {
|
||||
Module._free(pHead);
|
||||
pHead = null;
|
||||
}
|
||||
}
|
||||
} else if ("inputData" === data.type) {
|
||||
if (RECORDRTP) {
|
||||
var aFileData = new Uint8Array(data.buf); // 拷贝一份
|
||||
var iBufferLen = aFileData.length;
|
||||
var szBufferLen = iBufferLen.toString(16);
|
||||
if (szBufferLen.length === 1) {
|
||||
szBufferLen = "000" + szBufferLen;
|
||||
} else if (szBufferLen.length === 2) {
|
||||
szBufferLen = "00" + szBufferLen;
|
||||
} else if (szBufferLen.length === 3) {
|
||||
szBufferLen = "0" + szBufferLen;
|
||||
}
|
||||
var aData = [0, 0, parseInt(szBufferLen.substring(0, 2), 16), parseInt(szBufferLen.substring(2, 4), 16)];
|
||||
for (var iIndex = 0, iDataLength = aFileData.length; iIndex < iDataLength; iIndex++) {
|
||||
aData[iIndex + 4] = aFileData[iIndex];
|
||||
}
|
||||
var dataUint8 = new Uint8Array(aData);
|
||||
postMessage({type: "outputData",
|
||||
buf: dataUint8.buffer,
|
||||
dType: 2});
|
||||
} else {
|
||||
let inputMode = 0; //代表输入原始数据
|
||||
if (data.samplingParam) {
|
||||
iRet = Module._SysTransInputAudioPara(5, data.samplingParam.iChannel, data.samplingParam.iAudioBitWidth,
|
||||
data.samplingParam.iAudioSamplingRate, data.samplingParam.iTimeStamp, data.samplingParam.iAudioBitRate); //参数含义和_SysTransConfig类似
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransInputAudioPara Failed:" + iRet);
|
||||
}
|
||||
inputMode = 2; //输入替换的音频
|
||||
}
|
||||
var pInputDataBuf = Module._malloc(data.len);
|
||||
var idataLen = data.len;
|
||||
self.writeArrayToMemory(new Uint8Array(data.buf), pInputDataBuf);
|
||||
// 输入数据,每次最多2m
|
||||
let pp = Module._SysTransInputData(inputMode, pInputDataBuf, idataLen);
|
||||
if (pp == -2147483627) {
|
||||
//-2147483627 对应十六进制的80000015
|
||||
postMessage({ type: "outputData",
|
||||
dType: 1500 }); //标记为密码错误
|
||||
} else if (pp == -2147483647) {
|
||||
postMessage({ type: "outputData",
|
||||
dType: 1501 }); //标记为格式不支持
|
||||
} else if (pp != 0) {
|
||||
console.log("InputData Failed:" + pp);
|
||||
}
|
||||
Module._free(pInputDataBuf);
|
||||
}
|
||||
} else if ("release" === data.type) {
|
||||
var iRet = Module._SysTransStop();
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransStop failed!");
|
||||
}
|
||||
Module._SysTransRelease();
|
||||
if (iRet != 0) {
|
||||
console.log("_SysTransRelease failed!");
|
||||
}
|
||||
close();
|
||||
}
|
||||
};
|
||||
1
public/vendor/hikvision/webVideoCtrl.js
vendored
Normal file
@@ -1,26 +0,0 @@
|
||||
import { AxiosProgressEvent } from "axios";
|
||||
import { request } from "@/api/request";
|
||||
|
||||
/** 上传文件 */
|
||||
const FtsUpload = (data: FormData, onUploadProgress?: (progress: number) => void) => {
|
||||
data.append('provider', 'local');
|
||||
data.append('bucket', 'visual');
|
||||
|
||||
return request.post(
|
||||
`/fts/v1/uploader`,
|
||||
data,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
onUploadProgress: onUploadProgress ? (progressEvent: AxiosProgressEvent) => {
|
||||
if (progressEvent.total) {
|
||||
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
onUploadProgress(percentCompleted);
|
||||
}
|
||||
} : undefined
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default FtsUpload;
|
||||
@@ -1,93 +1,86 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
import type { KbReply } from './types'
|
||||
|
||||
/** 分类类型 */
|
||||
/** 公共分类状态。 */
|
||||
export type CategoryStatus = 'active' | 'inactive'
|
||||
|
||||
/** 公共分类。 */
|
||||
export interface Category {
|
||||
id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
name: string;
|
||||
description: string;
|
||||
type: string;
|
||||
icon: string;
|
||||
color: string;
|
||||
parent_id: number;
|
||||
level: number;
|
||||
path: string;
|
||||
sort_order: number;
|
||||
status: string;
|
||||
creator_id: number;
|
||||
creator_name: string;
|
||||
doc_count: number;
|
||||
faq_count: number;
|
||||
metadata: string | null;
|
||||
remarks: string;
|
||||
id: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
name: string
|
||||
description: string
|
||||
type: 'general'
|
||||
icon: string
|
||||
color: string
|
||||
parent_id: number
|
||||
level: 1 | 2 | 3
|
||||
path: string
|
||||
sort_order: number
|
||||
status: CategoryStatus
|
||||
creator_id: number
|
||||
creator_name: string
|
||||
doc_count: number
|
||||
faq_count: number
|
||||
metadata: string
|
||||
remarks: string
|
||||
}
|
||||
|
||||
/** API响应包装类型 */
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number;
|
||||
message: string;
|
||||
data: T;
|
||||
/** 公共分类树节点;详情字段需通过详情接口获取。 */
|
||||
export interface CategoryTreeNode {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
type: 'general'
|
||||
icon: string
|
||||
color: string
|
||||
parent_id: number
|
||||
level: 1 | 2 | 3
|
||||
path: string
|
||||
sort_order: number
|
||||
status: CategoryStatus
|
||||
doc_count: number
|
||||
faq_count: number
|
||||
children: CategoryTreeNode[]
|
||||
}
|
||||
|
||||
/** 创建分类请求参数 */
|
||||
/** 创建分类参数。 */
|
||||
export interface CreateCategoryParams {
|
||||
name: string;
|
||||
description?: string;
|
||||
type?: string;
|
||||
icon?: string;
|
||||
color?: string;
|
||||
parent_id?: number;
|
||||
sort_order?: number;
|
||||
remarks?: string;
|
||||
name: string
|
||||
description: string
|
||||
icon: string
|
||||
color: string
|
||||
parent_id: number
|
||||
sort_order: number
|
||||
status: CategoryStatus
|
||||
remarks: string
|
||||
}
|
||||
|
||||
/** 更新分类请求参数 */
|
||||
export interface UpdateCategoryParams {
|
||||
id: number;
|
||||
name?: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
color?: string;
|
||||
sort_order?: number;
|
||||
status?: string;
|
||||
remarks?: string;
|
||||
/** 更新分类参数。 */
|
||||
export interface UpdateCategoryParams extends CreateCategoryParams {
|
||||
id: number
|
||||
}
|
||||
|
||||
/** 获取分类列表参数 */
|
||||
/** 分类列表参数。 */
|
||||
export interface FetchCategoryListParams {
|
||||
type?: string;
|
||||
parent_id?: number;
|
||||
parent_id?: number
|
||||
}
|
||||
|
||||
/** 创建分类 */
|
||||
export const createCategory = (data: CreateCategoryParams) => {
|
||||
return request.post<ApiResponse<Category>>("/Kb/v1/category/create", data);
|
||||
};
|
||||
/** 创建公共分类。 */
|
||||
export const createCategory = (data: CreateCategoryParams) => request.post<KbReply<Category>>('/Kb/v1/category/create', data)
|
||||
|
||||
/** 更新分类 */
|
||||
export const updateCategory = (data: UpdateCategoryParams) => {
|
||||
return request.post<ApiResponse<Category>>("/Kb/v1/category/update", data);
|
||||
};
|
||||
/** 更新公共分类。 */
|
||||
export const updateCategory = (data: UpdateCategoryParams) => request.post<KbReply<Category>>('/Kb/v1/category/update', data)
|
||||
|
||||
/** 删除分类 */
|
||||
export const deleteCategory = (id: number) => {
|
||||
return request.delete<ApiResponse<string>>(`/Kb/v1/category/${id}`);
|
||||
};
|
||||
/** 删除公共分类。 */
|
||||
export const deleteCategory = (id: number) => request.delete<KbReply<string>>(`/Kb/v1/category/${id}`)
|
||||
|
||||
/** 获取分类详情 */
|
||||
export const fetchCategoryDetail = (id: number) => {
|
||||
return request.get<ApiResponse<Category>>(`/Kb/v1/category/${id}`);
|
||||
};
|
||||
/** 获取公共分类详情。 */
|
||||
export const fetchCategoryDetail = (id: number) => request.get<KbReply<Category>>(`/Kb/v1/category/${id}`)
|
||||
|
||||
/** 获取分类列表 */
|
||||
export const fetchCategoryList = (params?: FetchCategoryListParams) => {
|
||||
return request.get<ApiResponse<Category[]>>("/Kb/v1/category/list", { params });
|
||||
};
|
||||
/** 获取公共分类列表。 */
|
||||
export const fetchCategoryList = (params?: FetchCategoryListParams) => request.get<KbReply<Category[]>>('/Kb/v1/category/list', { params })
|
||||
|
||||
/** 获取分类树 */
|
||||
export const fetchCategoryTree = (type?: string) => {
|
||||
return request.get<ApiResponse<Category[]>>("/Kb/v1/category/tree", {
|
||||
params: type ? { type } : undefined,
|
||||
});
|
||||
};
|
||||
/** 获取完整公共分类树,包含停用节点。 */
|
||||
export const fetchCategoryTree = () => request.get<KbReply<CategoryTreeNode[]>>('/Kb/v1/category/tree')
|
||||
|
||||
@@ -1,218 +1,118 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
import type { KbReply } from './types'
|
||||
|
||||
/** 文档状态 */
|
||||
export type DocumentStatus = 'draft' | 'published' | 'reviewed' | 'rejected';
|
||||
/** 文档状态。 */
|
||||
export type DocumentStatus = 'draft' | 'published' | 'reviewed' | 'rejected'
|
||||
/** 文档类型。 */
|
||||
export type DocumentType = 'common' | 'guide' | 'solution' | 'troubleshoot' | 'process' | 'technical'
|
||||
/** 文档列表范围。 */
|
||||
export type DocumentScope = 'my' | 'all'
|
||||
|
||||
/** 文档类型 */
|
||||
export type DocumentType = 'common' | 'guide' | 'solution' | 'troubleshoot' | 'process' | 'technical';
|
||||
|
||||
/** 文档接口类型 */
|
||||
/** 文档资源。 */
|
||||
export interface Document {
|
||||
id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
doc_no: string;
|
||||
title: string;
|
||||
description: string;
|
||||
content: string;
|
||||
type: DocumentType;
|
||||
status: DocumentStatus;
|
||||
category_id: number;
|
||||
sub_category: string;
|
||||
author_id: number;
|
||||
author_name: string;
|
||||
reviewer_id: number;
|
||||
reviewer_name: string;
|
||||
reviewed_at: string | null;
|
||||
published_at: string | null;
|
||||
publisher_id: number;
|
||||
view_count: number;
|
||||
like_count: number;
|
||||
comment_count: number;
|
||||
download_count: number;
|
||||
version: string;
|
||||
version_notes: string;
|
||||
tags: string;
|
||||
attachments: string | null;
|
||||
related_docs: string | null;
|
||||
metadata: string | null;
|
||||
keywords: string;
|
||||
remarks: string;
|
||||
is_favorited?: boolean;
|
||||
id: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
doc_no: string
|
||||
title: string
|
||||
description: string
|
||||
content: string
|
||||
type: DocumentType
|
||||
status: DocumentStatus
|
||||
category_id: number
|
||||
sub_category: string
|
||||
author_id: number
|
||||
author_name: string
|
||||
reviewer_id: number
|
||||
reviewer_name: string
|
||||
reviewed_at: string | null
|
||||
published_at: string | null
|
||||
publisher_id: number
|
||||
view_count: number
|
||||
like_count: number
|
||||
comment_count: number
|
||||
download_count: number
|
||||
version: string
|
||||
version_notes: string
|
||||
tags: string
|
||||
attachments: string
|
||||
related_docs: string
|
||||
detection_point_ids: string
|
||||
metadata: string
|
||||
keywords: string
|
||||
remarks: string
|
||||
is_favorited: boolean
|
||||
}
|
||||
|
||||
/** API响应包装类型 */
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number;
|
||||
message: string;
|
||||
data: T;
|
||||
/** 文档分页结果。 */
|
||||
export interface DocumentPage {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: Document[]
|
||||
}
|
||||
|
||||
/** 分页响应类型 */
|
||||
export interface PaginatedResponse<T> {
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
data: T[];
|
||||
}
|
||||
|
||||
/** 创建文档请求参数 */
|
||||
/** 文档创建字段。 */
|
||||
export interface CreateDocumentParams {
|
||||
title: string;
|
||||
description?: string;
|
||||
content: string;
|
||||
type?: DocumentType;
|
||||
category_id?: number;
|
||||
sub_category?: string;
|
||||
keywords?: string;
|
||||
tags?: string;
|
||||
remarks?: string;
|
||||
title: string
|
||||
description: string
|
||||
content: string
|
||||
type: DocumentType
|
||||
category_id: number
|
||||
sub_category: string
|
||||
keywords: string
|
||||
tags: string
|
||||
detection_point_ids: string
|
||||
remarks: string
|
||||
}
|
||||
|
||||
/** 更新文档请求参数 */
|
||||
export interface UpdateDocumentParams {
|
||||
id: number;
|
||||
title?: string;
|
||||
description?: string;
|
||||
content?: string;
|
||||
type?: DocumentType;
|
||||
category_id?: number;
|
||||
sub_category?: string;
|
||||
keywords?: string;
|
||||
tags?: string;
|
||||
remarks?: string;
|
||||
/** 文档编辑字段。 */
|
||||
export interface UpdateDocumentParams extends CreateDocumentParams {
|
||||
id: number
|
||||
}
|
||||
|
||||
/** 获取文档列表参数 */
|
||||
/** 文档列表参数。 */
|
||||
export interface FetchDocumentListParams {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
keyword?: string;
|
||||
type?: DocumentType;
|
||||
status?: DocumentStatus;
|
||||
category_id?: number;
|
||||
page?: number
|
||||
page_size?: number
|
||||
scope?: DocumentScope
|
||||
keyword?: string
|
||||
type?: DocumentType
|
||||
status?: DocumentStatus
|
||||
category_id?: number
|
||||
}
|
||||
|
||||
/** 文档类型选项 */
|
||||
export const documentTypeOptions = [
|
||||
export const documentTypeOptions: Array<{ label: string; value: DocumentType }> = [
|
||||
{ label: '通用文档', value: 'common' },
|
||||
{ label: '操作指南', value: 'guide' },
|
||||
{ label: '解决方案', value: 'solution' },
|
||||
{ label: '故障排查', value: 'troubleshoot' },
|
||||
{ label: '流程规范', value: 'process' },
|
||||
{ label: '技术文档', value: 'technical' },
|
||||
];
|
||||
]
|
||||
|
||||
/** 文档状态选项 */
|
||||
export const documentStatusOptions = [
|
||||
{ label: '草稿', value: 'draft' },
|
||||
{ label: '已发布', value: 'published' },
|
||||
{ label: '已审核', value: 'reviewed' },
|
||||
{ label: '未通过审核', value: 'rejected' },
|
||||
];
|
||||
/** 创建文档草稿。 */
|
||||
export const createDocument = (data: CreateDocumentParams) => request.post<KbReply<Document>>('/Kb/v1/document/create', data)
|
||||
|
||||
/** 获取文档状态文本 */
|
||||
export const getDocumentStatusText = (status: DocumentStatus): string => {
|
||||
const statusMap: Record<DocumentStatus, string> = {
|
||||
draft: '草稿',
|
||||
published: '已发布',
|
||||
reviewed: '已审核',
|
||||
rejected: '未通过审核',
|
||||
};
|
||||
return statusMap[status] || status;
|
||||
};
|
||||
/** 更新文档。 */
|
||||
export const updateDocument = (data: UpdateDocumentParams) => request.post<KbReply<Document>>('/Kb/v1/document/update', data)
|
||||
|
||||
/** 获取文档状态颜色 */
|
||||
export const getDocumentStatusColor = (status: DocumentStatus): string => {
|
||||
const colorMap: Record<DocumentStatus, string> = {
|
||||
draft: 'gray',
|
||||
published: 'blue',
|
||||
reviewed: 'green',
|
||||
rejected: 'red',
|
||||
};
|
||||
return colorMap[status] || 'gray';
|
||||
};
|
||||
/** 删除文档并移入回收站。 */
|
||||
export const deleteDocument = (id: number) => request.delete<KbReply<string>>(`/Kb/v1/document/${id}`)
|
||||
|
||||
/** 获取文档类型文本 */
|
||||
export const getDocumentTypeText = (type: DocumentType): string => {
|
||||
const typeMap: Record<DocumentType, string> = {
|
||||
common: '通用文档',
|
||||
guide: '操作指南',
|
||||
solution: '解决方案',
|
||||
troubleshoot: '故障排查',
|
||||
process: '流程规范',
|
||||
technical: '技术文档',
|
||||
};
|
||||
return typeMap[type] || type;
|
||||
};
|
||||
/** 获取文档详情。 */
|
||||
export const fetchDocumentDetail = (id: number) => request.get<KbReply<Document>>(`/Kb/v1/document/${id}`)
|
||||
|
||||
/** 创建文档 */
|
||||
export const createDocument = (data: CreateDocumentParams) => {
|
||||
return request.post<ApiResponse<Document>>("/Kb/v1/document/create", data);
|
||||
};
|
||||
/** 获取指定可见范围的文档列表。 */
|
||||
export const fetchDocumentList = (params: FetchDocumentListParams) => request.get<KbReply<DocumentPage>>('/Kb/v1/document/list', { params })
|
||||
|
||||
/** 更新文档 */
|
||||
export const updateDocument = (data: UpdateDocumentParams) => {
|
||||
return request.post<ApiResponse<Document>>("/Kb/v1/document/update", data);
|
||||
};
|
||||
/** 提交文档审核。 */
|
||||
export const publishDocument = (id: number) => request.post<KbReply<string>>('/Kb/v1/document/publish', { id })
|
||||
|
||||
/** 删除文档(移入回收站) */
|
||||
export const deleteDocument = (id: number) => {
|
||||
return request.delete<ApiResponse<string>>(`/Kb/v1/document/${id}`);
|
||||
};
|
||||
/** 收藏文档。 */
|
||||
export const favoriteDocument = (id: number) =>
|
||||
request.post<KbReply<unknown>>('/Kb/v1/favorite/collect', { resource_type: 'document', resource_id: id })
|
||||
|
||||
/** 获取文档详情 */
|
||||
export const fetchDocumentDetail = (id: number) => {
|
||||
return request.get<ApiResponse<Document>>(`/Kb/v1/document/${id}`);
|
||||
};
|
||||
|
||||
/** 获取文档列表 */
|
||||
export const fetchDocumentList = (params?: FetchDocumentListParams) => {
|
||||
return request.get<ApiResponse<PaginatedResponse<Document>>>("/Kb/v1/document/list", { params });
|
||||
};
|
||||
|
||||
/** 发布文档 */
|
||||
export const publishDocument = (id: number) => {
|
||||
return request.post<ApiResponse<string>>("/Kb/v1/document/publish", { id });
|
||||
};
|
||||
|
||||
/** 移入回收站 */
|
||||
export const moveToTrash = (resourceId: number, resourceType: string) => {
|
||||
return request.post<ApiResponse<string>>("/Kb/v1/trash/move", {
|
||||
resource_id: resourceId,
|
||||
resource_type: resourceType,
|
||||
});
|
||||
};
|
||||
|
||||
/** 获取我的文档列表(由我创建的所有文档) */
|
||||
export const fetchMyDocumentList = (params?: FetchDocumentListParams) => {
|
||||
return request.get<ApiResponse<PaginatedResponse<Document>>>("/Kb/v1/review/publish/list", { params });
|
||||
};
|
||||
|
||||
/** 获取已审核通过的文档列表 */
|
||||
export const fetchApprovedDocumentList = (params?: FetchDocumentListParams) => {
|
||||
return request.get<ApiResponse<PaginatedResponse<Document>>>("/Kb/v1/review/approved/list", { params });
|
||||
};
|
||||
|
||||
/** 收藏文档 */
|
||||
export const favoriteDocument = (id: number, remarks?: string) => {
|
||||
return request.post<ApiResponse<string>>("/Kb/v1/favorite/collect", {
|
||||
resource_type: 'document',
|
||||
resource_id: id,
|
||||
remarks,
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消收藏文档 */
|
||||
export const unfavoriteDocument = (id: number) => {
|
||||
return request.post<ApiResponse<string>>("/Kb/v1/favorite/uncollect", {
|
||||
resource_type: 'document',
|
||||
resource_id: id,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/** 下载文档 */
|
||||
export const downloadDocument = (id: number) => {
|
||||
return request.get<Blob>(`/Kb/v1/document/${id}/download`, { responseType: 'blob' });
|
||||
};
|
||||
/** 取消收藏文档。 */
|
||||
export const unfavoriteDocument = (id: number) =>
|
||||
request.post<KbReply<string>>('/Kb/v1/favorite/uncollect', { resource_type: 'document', resource_id: id })
|
||||
|
||||
177
src/api/kb/faq.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
import { request } from '@/api/request'
|
||||
import type { KbReply } from './types'
|
||||
|
||||
export { fetchCategoryTree as fetchGeneralCategoryTree } from './category'
|
||||
export type { CategoryTreeNode } from './category'
|
||||
export type { KbReply } from './types'
|
||||
|
||||
/** FAQ 审核状态。 */
|
||||
export type FaqStatus = 'draft' | 'published' | 'reviewed' | 'rejected'
|
||||
/** FAQ 优先级。 */
|
||||
export type FaqPriority = 'low' | 'medium' | 'high'
|
||||
/** FAQ 列表可见范围。 */
|
||||
export type FaqScope = 'my' | 'all'
|
||||
|
||||
/** FAQ 资源。 */
|
||||
export interface Faq {
|
||||
id: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
faq_no: string
|
||||
question: string
|
||||
answer: string
|
||||
status: FaqStatus
|
||||
priority: FaqPriority
|
||||
category_id: number
|
||||
sub_category: string
|
||||
problem_type: string
|
||||
solution: string
|
||||
process_steps: string
|
||||
prerequisites: string
|
||||
author_id: number
|
||||
author_name: string
|
||||
reviewer_id: number
|
||||
reviewer_name: string
|
||||
reviewed_at: string | null
|
||||
published_at: string | null
|
||||
view_count: number
|
||||
use_count: number
|
||||
helpful_count: number
|
||||
useless_count: number
|
||||
tags: string
|
||||
related_faqs: string
|
||||
related_docs: string
|
||||
related_links: string
|
||||
detection_point_ids: string
|
||||
attachments: string
|
||||
keywords: string
|
||||
applicable_scope: string
|
||||
remarks: string
|
||||
is_favorited: boolean
|
||||
}
|
||||
|
||||
/** FAQ 分页结果。 */
|
||||
export interface FaqPage {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: Faq[]
|
||||
}
|
||||
|
||||
/** FAQ 列表查询参数。 */
|
||||
export interface FaqListParams {
|
||||
page?: number
|
||||
page_size?: number
|
||||
scope?: FaqScope
|
||||
keyword?: string
|
||||
category_id?: number
|
||||
status?: FaqStatus
|
||||
priority?: FaqPriority
|
||||
problem_type?: string
|
||||
}
|
||||
|
||||
/** FAQ 创建和编辑字段。 */
|
||||
export interface FaqFormData {
|
||||
question: string
|
||||
answer: string
|
||||
priority: FaqPriority
|
||||
category_id: number
|
||||
sub_category: string
|
||||
problem_type: string
|
||||
solution: string
|
||||
process_steps: string
|
||||
prerequisites: string
|
||||
keywords: string
|
||||
tags: string
|
||||
detection_point_ids: string
|
||||
applicable_scope: string
|
||||
remarks: string
|
||||
}
|
||||
|
||||
/** FAQ 编辑请求。 */
|
||||
export interface UpdateFaqData extends FaqFormData {
|
||||
id: number
|
||||
}
|
||||
|
||||
/** FAQ 状态筛选项。 */
|
||||
export const faqStatusOptions: Array<{ label: string; value: FaqStatus }> = [
|
||||
{ label: '草稿', value: 'draft' },
|
||||
{ label: '待审核', value: 'published' },
|
||||
{ label: '已审核', value: 'reviewed' },
|
||||
{ label: '已拒绝', value: 'rejected' },
|
||||
]
|
||||
|
||||
/** FAQ 优先级筛选项。 */
|
||||
export const faqPriorityOptions: Array<{ label: string; value: FaqPriority }> = [
|
||||
{ label: '低', value: 'low' },
|
||||
{ label: '中', value: 'medium' },
|
||||
{ label: '高', value: 'high' },
|
||||
]
|
||||
|
||||
/** 常用问题类型;接口仍允许自由字符串。 */
|
||||
export const faqProblemTypeOptions = [
|
||||
{ label: '故障', value: '故障' },
|
||||
{ label: '咨询', value: '咨询' },
|
||||
{ label: '请求', value: '请求' },
|
||||
{ label: '其他', value: '其他' },
|
||||
]
|
||||
|
||||
const faqStatusMeta: Record<FaqStatus, { text: string; color: string }> = {
|
||||
draft: { text: '草稿', color: 'gray' },
|
||||
published: { text: '待审核', color: 'orange' },
|
||||
reviewed: { text: '已审核', color: 'green' },
|
||||
rejected: { text: '已拒绝', color: 'red' },
|
||||
}
|
||||
|
||||
const faqPriorityMeta: Record<FaqPriority, { text: string; color: string }> = {
|
||||
low: { text: '低', color: 'gray' },
|
||||
medium: { text: '中', color: 'blue' },
|
||||
high: { text: '高', color: 'orange' },
|
||||
}
|
||||
|
||||
/** 获取 FAQ 状态文案。 */
|
||||
export const getFaqStatusText = (status: FaqStatus | string) => faqStatusMeta[status as FaqStatus]?.text || status || '-'
|
||||
|
||||
/** 获取 FAQ 状态标签颜色。 */
|
||||
export const getFaqStatusColor = (status: FaqStatus | string) => faqStatusMeta[status as FaqStatus]?.color || 'gray'
|
||||
|
||||
/** 获取 FAQ 优先级文案。 */
|
||||
export const getFaqPriorityText = (priority: FaqPriority | string) => faqPriorityMeta[priority as FaqPriority]?.text || priority || '-'
|
||||
|
||||
/** 获取 FAQ 优先级标签颜色。 */
|
||||
export const getFaqPriorityColor = (priority: FaqPriority | string) => faqPriorityMeta[priority as FaqPriority]?.color || 'gray'
|
||||
|
||||
/** 获取 FAQ 列表。 */
|
||||
export const fetchFaqList = (params: FaqListParams) =>
|
||||
request.get<KbReply<FaqPage>>('/Kb/v1/faq/list', {
|
||||
params,
|
||||
})
|
||||
|
||||
/** 获取 FAQ 详情。 */
|
||||
export const fetchFaqDetail = (id: number) => request.get<KbReply<Faq>>(`/Kb/v1/faq/${id}`)
|
||||
|
||||
/** 创建 FAQ 草稿。 */
|
||||
export const createFaq = (data: FaqFormData) => request.post<KbReply<Faq>>('/Kb/v1/faq/create', data)
|
||||
|
||||
/** 更新 FAQ。 */
|
||||
export const updateFaq = (data: UpdateFaqData) => request.post<KbReply<Faq>>('/Kb/v1/faq/update', data)
|
||||
|
||||
/** 提交 FAQ 审核。 */
|
||||
export const publishFaq = (id: number) => request.post<KbReply<string>>('/Kb/v1/faq/publish', { id })
|
||||
|
||||
/** 删除 FAQ 并移入回收站。 */
|
||||
export const deleteFaq = (id: number) => request.delete<KbReply<string>>(`/Kb/v1/faq/${id}`)
|
||||
|
||||
/** 收藏 FAQ。 */
|
||||
export const favoriteFaq = (id: number) =>
|
||||
request.post<KbReply<unknown>>('/Kb/v1/favorite/collect', {
|
||||
resource_type: 'faq',
|
||||
resource_id: id,
|
||||
})
|
||||
|
||||
/** 取消收藏 FAQ。 */
|
||||
export const unfavoriteFaq = (id: number) =>
|
||||
request.post<KbReply<string>>('/Kb/v1/favorite/uncollect', {
|
||||
resource_type: 'faq',
|
||||
resource_id: id,
|
||||
})
|
||||
@@ -1,86 +1,49 @@
|
||||
import { request } from '@/api/request';
|
||||
import { request } from '@/api/request'
|
||||
import type { Document } from './document'
|
||||
import type { Faq } from './faq'
|
||||
import type { KbReply } from './types'
|
||||
|
||||
/** 资源类型 */
|
||||
export type ResourceType = 'document' | 'faq';
|
||||
export type ResourceType = 'document' | 'faq'
|
||||
|
||||
/** 收藏记录接口 */
|
||||
/** 收藏记录。 */
|
||||
export interface Favorite {
|
||||
id: number;
|
||||
created_at: string;
|
||||
resource_type: ResourceType;
|
||||
resource_id: number;
|
||||
resource_name: string;
|
||||
remarks: string;
|
||||
is_deleted: boolean;
|
||||
resource_data?: any;
|
||||
id: number
|
||||
created_at: string
|
||||
resource_type: ResourceType
|
||||
resource_id: number
|
||||
resource_name: string
|
||||
remarks: string
|
||||
is_deleted: boolean
|
||||
resource_data?: Document | Faq
|
||||
}
|
||||
|
||||
/** 收藏列表响应 */
|
||||
export interface FavoriteListResponse {
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
data: Favorite[];
|
||||
export interface FavoritePage {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: Favorite[]
|
||||
}
|
||||
|
||||
/** 获取收藏列表参数 */
|
||||
export interface FetchFavoriteListParams {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
resource_type?: ResourceType;
|
||||
page?: number
|
||||
page_size?: number
|
||||
resource_type?: ResourceType
|
||||
}
|
||||
|
||||
/** 收藏请求参数 */
|
||||
export interface CollectParams {
|
||||
resource_type: ResourceType;
|
||||
resource_id: number;
|
||||
remarks?: string;
|
||||
resource_type: ResourceType
|
||||
resource_id: number
|
||||
remarks?: string
|
||||
}
|
||||
|
||||
/** 取消收藏参数 */
|
||||
export interface UncollectParams {
|
||||
resource_type: ResourceType;
|
||||
resource_id: number;
|
||||
}
|
||||
export type UncollectParams = Omit<CollectParams, 'remarks'>
|
||||
|
||||
/** API响应包装类型 */
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number;
|
||||
message: string;
|
||||
data: T;
|
||||
}
|
||||
/** 获取收藏列表。 */
|
||||
export const fetchFavoriteList = (params: FetchFavoriteListParams = {}) =>
|
||||
request.get<KbReply<FavoritePage>>('/Kb/v1/favorite/list', { params })
|
||||
|
||||
/**
|
||||
* 获取收藏列表
|
||||
*/
|
||||
export async function fetchFavoriteList(
|
||||
params: FetchFavoriteListParams = {}
|
||||
): Promise<ApiResponse<FavoriteListResponse>> {
|
||||
return request.get<ApiResponse<FavoriteListResponse>>('/Kb/v1/favorite/list', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
/** 收藏资源。 */
|
||||
export const collectResource = (data: CollectParams) => request.post<KbReply<Favorite>>('/Kb/v1/favorite/collect', data)
|
||||
|
||||
/**
|
||||
* 收藏资源
|
||||
*/
|
||||
export async function collectResource(
|
||||
data: CollectParams
|
||||
): Promise<ApiResponse<Favorite>> {
|
||||
return request.post<ApiResponse<Favorite>>('/Kb/v1/favorite/collect', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消收藏
|
||||
*/
|
||||
export async function uncollectResource(
|
||||
data: UncollectParams
|
||||
): Promise<ApiResponse<string>> {
|
||||
return request.post<ApiResponse<string>>('/Kb/v1/favorite/uncollect', data);
|
||||
}
|
||||
|
||||
/** 资源类型选项 */
|
||||
export const resourceTypeOptions = [
|
||||
{ label: '文档', value: 'document' },
|
||||
{ label: 'FAQ', value: 'faq' },
|
||||
];
|
||||
/** 取消收藏。 */
|
||||
export const uncollectResource = (data: UncollectParams) => request.post<KbReply<string>>('/Kb/v1/favorite/uncollect', data)
|
||||
|
||||
68
src/api/kb/knowledge.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { request } from '@/api/request'
|
||||
|
||||
export interface DetectionPoint {
|
||||
id: number
|
||||
resource_category: string
|
||||
metric_code: string
|
||||
alert_rule_id: number
|
||||
fault_type: string
|
||||
knowledge_type: 'document' | 'faq'
|
||||
knowledge_id: number
|
||||
knowledge_title: string
|
||||
enabled: boolean
|
||||
remarks: string
|
||||
}
|
||||
|
||||
export interface KnowledgeRecommendation {
|
||||
knowledge_type: 'document' | 'faq'
|
||||
knowledge_id: number
|
||||
title: string
|
||||
status: string
|
||||
resource_category: string
|
||||
metric_code: string
|
||||
alert_rule_id: number
|
||||
fault_type: string
|
||||
detection_point_id: number
|
||||
score: number
|
||||
reason: string
|
||||
}
|
||||
|
||||
export interface IncidentKnowledgeRelation {
|
||||
id: number
|
||||
incident_id: number
|
||||
ticket_id: number
|
||||
knowledge_type: 'document' | 'faq'
|
||||
knowledge_id: number
|
||||
knowledge_title: string
|
||||
relation_type: string
|
||||
source: string
|
||||
score: number
|
||||
reason: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export const fetchKnowledgeRecommendations = (params: {
|
||||
resource_category?: string
|
||||
metric_code?: string
|
||||
alert_rule_id?: number
|
||||
fault_type?: string
|
||||
limit?: number
|
||||
}) => request.get('/Kb/v1/knowledge/recommend', { params })
|
||||
|
||||
export const fetchIncidentKnowledge = (incidentId: number) => request.get(`/Kb/v1/knowledge/incidents/${incidentId}/relations`)
|
||||
|
||||
export const fetchTicketKnowledge = (ticketId: number) => request.get('/Kb/v1/knowledge/relations', { params: { ticket_id: ticketId } })
|
||||
|
||||
export const relateIncidentKnowledge = (data: {
|
||||
incident_id?: number
|
||||
ticket_id?: number
|
||||
knowledge_type: 'document' | 'faq'
|
||||
knowledge_id: number
|
||||
knowledge_title?: string
|
||||
relation_type?: string
|
||||
source?: string
|
||||
score?: number
|
||||
reason?: string
|
||||
}) => request.post('/Kb/v1/knowledge/relations', data)
|
||||
|
||||
export const createPostmortemDraft = (data: Record<string, any>) => request.post('/Kb/v1/knowledge/postmortem/draft', data)
|
||||
@@ -1,173 +1,71 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
import type { Document } from './document'
|
||||
import type { Faq } from './faq'
|
||||
import type { KbReply } from './types'
|
||||
|
||||
export type ReviewStatsResourceType = "all" | "document" | "faq";
|
||||
export type ReviewResourceType = 'all' | 'document' | 'faq'
|
||||
|
||||
/** 审核统计接口返回的 data 字段 */
|
||||
export interface ReviewStatsPayload {
|
||||
need_my_review_document?: number;
|
||||
need_my_review_faq?: number;
|
||||
need_my_review_total?: number;
|
||||
need_my_review_unreviewed_document?: number;
|
||||
need_my_review_unreviewed_faq?: number;
|
||||
need_my_review_unreviewed_total?: number;
|
||||
}
|
||||
|
||||
/** 文档资源类型 */
|
||||
export interface DocumentResource {
|
||||
id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
doc_no: string;
|
||||
title: string;
|
||||
description: string;
|
||||
content: string;
|
||||
type: string;
|
||||
status: string;
|
||||
category_id: number;
|
||||
sub_category: string;
|
||||
author_id: number;
|
||||
author_name: string;
|
||||
reviewer_id: number;
|
||||
reviewer_name: string;
|
||||
reviewed_at: string | null;
|
||||
published_at: string | null;
|
||||
publisher_id: number;
|
||||
view_count: number;
|
||||
like_count: number;
|
||||
comment_count: number;
|
||||
download_count: number;
|
||||
version: string;
|
||||
version_notes: string;
|
||||
tags: string;
|
||||
attachments: string | null;
|
||||
related_docs: string | null;
|
||||
metadata: string | null;
|
||||
keywords: string;
|
||||
remarks: string;
|
||||
}
|
||||
|
||||
/** FAQ资源类型 */
|
||||
export interface FaqResource {
|
||||
id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
faq_no: string;
|
||||
question: string;
|
||||
answer: string;
|
||||
status: string;
|
||||
priority: string;
|
||||
category_id: number;
|
||||
sub_category: string;
|
||||
problem_type: string;
|
||||
solution: string;
|
||||
process_steps: string;
|
||||
prerequisites: string;
|
||||
author_id: number;
|
||||
author_name: string;
|
||||
reviewer_id: number;
|
||||
reviewer_name: string;
|
||||
reviewed_at: string | null;
|
||||
published_at: string | null;
|
||||
view_count: number;
|
||||
use_count: number;
|
||||
helpful_count: number;
|
||||
useless_count: number;
|
||||
tags: string;
|
||||
related_faqs: string | null;
|
||||
related_docs: string | null;
|
||||
related_links: string | null;
|
||||
attachments: string | null;
|
||||
keywords: string;
|
||||
applicable_scope: string;
|
||||
remarks: string;
|
||||
}
|
||||
|
||||
/** 审核列表项(resource_type 为 all 时) */
|
||||
/** 统一审核列表项。 */
|
||||
export interface ReviewListItem {
|
||||
type: "document" | "faq";
|
||||
resource: DocumentResource | FaqResource;
|
||||
type: 'document' | 'faq'
|
||||
resource: Document | Faq
|
||||
}
|
||||
|
||||
/** 分页响应类型 */
|
||||
export interface PaginatedResponse<T> {
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
data: T[];
|
||||
/** 审核分页结果。 */
|
||||
export interface ReviewPage {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: ReviewListItem[]
|
||||
}
|
||||
|
||||
/** API响应包装类型 */
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number;
|
||||
message: string;
|
||||
data: T;
|
||||
/** 当前审核人的待审数量。 */
|
||||
export interface ReviewStats {
|
||||
need_my_review_document: number
|
||||
need_my_review_faq: number
|
||||
need_my_review_total: number
|
||||
need_my_review_unreviewed_document: number
|
||||
need_my_review_unreviewed_faq: number
|
||||
need_my_review_unreviewed_total: number
|
||||
}
|
||||
|
||||
/** 获取审核列表参数 */
|
||||
/** 审核列表参数。 */
|
||||
export interface FetchReviewListParams {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
resource_type?: ReviewStatsResourceType;
|
||||
page?: number
|
||||
page_size?: number
|
||||
resource_type?: ReviewResourceType
|
||||
}
|
||||
|
||||
/** 审核通过参数 */
|
||||
export interface ApproveParams {
|
||||
resource_type: "document" | "faq";
|
||||
id: number;
|
||||
resource_type: 'document' | 'faq'
|
||||
id: number
|
||||
}
|
||||
|
||||
/** 审核拒绝参数 */
|
||||
export interface RejectParams {
|
||||
resource_type: "document" | "faq";
|
||||
id: number;
|
||||
reason?: string;
|
||||
export interface RejectParams extends ApproveParams {
|
||||
reason: string
|
||||
}
|
||||
|
||||
/** 按当前登录用户统计需要本人审核的数量(不含本人为作者的稿件) */
|
||||
export const fetchReviewStats = (params?: { resource_type?: ReviewStatsResourceType }) =>
|
||||
request.get("/Kb/v1/review/stats", params ? { params } : undefined);
|
||||
/** 获取当前用户可审核的待审资源。 */
|
||||
export const fetchReviewList = (params: FetchReviewListParams) => request.get<KbReply<ReviewPage>>('/Kb/v1/review/list', { params })
|
||||
|
||||
/** 获取待审核列表 */
|
||||
export const fetchReviewList = (params?: FetchReviewListParams) =>
|
||||
request.get<ApiResponse<PaginatedResponse<ReviewListItem | DocumentResource | FaqResource>>>("/Kb/v1/review/list", { params });
|
||||
/** 获取当前审核人的待审统计。 */
|
||||
export const fetchReviewStats = (params: { resource_type?: ReviewResourceType } = {}) =>
|
||||
request.get<KbReply<ReviewStats>>('/Kb/v1/review/stats', { params })
|
||||
|
||||
/** 审核通过 */
|
||||
export const approveReview = (data: ApproveParams) =>
|
||||
request.post<ApiResponse<string>>("/Kb/v1/review/approve", data);
|
||||
/** 审核通过。 */
|
||||
export const approveReview = (data: ApproveParams) => request.post<KbReply<string>>('/Kb/v1/review/approve', data)
|
||||
|
||||
/** 审核拒绝 */
|
||||
export const rejectReview = (data: RejectParams) =>
|
||||
request.post<ApiResponse<string>>("/Kb/v1/review/reject", data);
|
||||
/** 审核拒绝。 */
|
||||
export const rejectReview = (data: RejectParams) => request.post<KbReply<string>>('/Kb/v1/review/reject', data)
|
||||
|
||||
/** 获取文档详情 */
|
||||
export const fetchDocumentDetail = (id: number) =>
|
||||
request.get<ApiResponse<DocumentResource>>(`/Kb/v1/document/${id}`);
|
||||
|
||||
/** 获取FAQ详情 */
|
||||
export const fetchFaqDetail = (id: number) =>
|
||||
request.get<ApiResponse<FaqResource>>(`/Kb/v1/faq/${id}`);
|
||||
|
||||
/** 资源类型选项 */
|
||||
export const resourceTypeOptions = [
|
||||
export const resourceTypeOptions: Array<{ label: string; value: ReviewResourceType }> = [
|
||||
{ label: '全部', value: 'all' },
|
||||
{ label: '文档', value: 'document' },
|
||||
{ label: 'FAQ', value: 'faq' },
|
||||
];
|
||||
]
|
||||
|
||||
/** 获取资源类型文本 */
|
||||
export const getResourceTypeText = (type: string): string => {
|
||||
const typeMap: Record<string, string> = {
|
||||
document: '文档',
|
||||
faq: 'FAQ',
|
||||
};
|
||||
return typeMap[type] || type;
|
||||
};
|
||||
/** 获取审核资源类型文案。 */
|
||||
export const getResourceTypeText = (type: string) => ({ document: '文档', faq: 'FAQ' })[type] || type
|
||||
|
||||
/** 获取资源类型颜色 */
|
||||
export const getResourceTypeColor = (type: string): string => {
|
||||
const colorMap: Record<string, string> = {
|
||||
document: 'arcoblue',
|
||||
faq: 'green',
|
||||
};
|
||||
return colorMap[type] || 'gray';
|
||||
};
|
||||
/** 获取审核资源类型颜色。 */
|
||||
export const getResourceTypeColor = (type: string) => ({ document: 'arcoblue', faq: 'green' })[type] || 'gray'
|
||||
|
||||
@@ -1,88 +1,53 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
import type { KbReply } from './types'
|
||||
|
||||
/** API响应包装类型 */
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number;
|
||||
message: string;
|
||||
data: T;
|
||||
}
|
||||
export type TrashResourceType = 'document' | 'faq'
|
||||
|
||||
/** 分页响应类型 */
|
||||
export interface PaginatedResponse<T> {
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
data: T[];
|
||||
}
|
||||
|
||||
/** 回收站记录 */
|
||||
/** 回收站记录。 */
|
||||
export interface TrashRecord {
|
||||
id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
resource_type: 'document' | 'faq';
|
||||
resource_id: number;
|
||||
resource_name: string;
|
||||
deleted_by: number;
|
||||
deleted_name: string;
|
||||
deleted_time: string;
|
||||
delete_reason: string;
|
||||
original_data: string;
|
||||
remarks: string;
|
||||
id: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
resource_type: TrashResourceType
|
||||
resource_id: number
|
||||
resource_name: string
|
||||
deleted_by: number
|
||||
deleted_name: string
|
||||
deleted_time: string
|
||||
delete_reason: string
|
||||
original_data: string
|
||||
remarks: string
|
||||
}
|
||||
|
||||
export interface TrashPage {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: TrashRecord[]
|
||||
}
|
||||
|
||||
/** 获取回收站列表参数 */
|
||||
export interface FetchTrashListParams {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
resource_type?: 'document' | 'faq';
|
||||
page?: number
|
||||
page_size?: number
|
||||
resource_type?: TrashResourceType
|
||||
}
|
||||
|
||||
/** 恢复资源请求参数 */
|
||||
export interface RestoreTrashParams {
|
||||
id: number;
|
||||
}
|
||||
|
||||
/** 彻底删除请求参数 */
|
||||
export interface DeleteTrashParams {
|
||||
id: number;
|
||||
}
|
||||
|
||||
/** 资源类型选项 */
|
||||
export const resourceTypeOptions = [
|
||||
export const resourceTypeOptions: Array<{ label: string; value: TrashResourceType }> = [
|
||||
{ label: '文档', value: 'document' },
|
||||
{ label: '常见问题', value: 'faq' },
|
||||
];
|
||||
{ label: 'FAQ', value: 'faq' },
|
||||
]
|
||||
|
||||
/** 获取资源类型文本 */
|
||||
export const getResourceTypeText = (type: string): string => {
|
||||
const typeMap: Record<string, string> = {
|
||||
document: '文档',
|
||||
faq: '常见问题',
|
||||
};
|
||||
return typeMap[type] || type;
|
||||
};
|
||||
/** 获取回收站资源类型文案。 */
|
||||
export const getResourceTypeText = (type: string) => ({ document: '文档', faq: 'FAQ' })[type] || type
|
||||
|
||||
/** 获取资源类型颜色 */
|
||||
export const getResourceTypeColor = (type: string): string => {
|
||||
const colorMap: Record<string, string> = {
|
||||
document: 'blue',
|
||||
faq: 'green',
|
||||
};
|
||||
return colorMap[type] || 'gray';
|
||||
};
|
||||
/** 获取回收站资源类型颜色。 */
|
||||
export const getResourceTypeColor = (type: string) => ({ document: 'blue', faq: 'green' })[type] || 'gray'
|
||||
|
||||
/** 获取回收站列表 */
|
||||
export const fetchTrashList = (params?: FetchTrashListParams) => {
|
||||
return request.get<ApiResponse<PaginatedResponse<TrashRecord>>>("/Kb/v1/trash/list", { params });
|
||||
};
|
||||
/** 获取回收站列表。 */
|
||||
export const fetchTrashList = (params: FetchTrashListParams) => request.get<KbReply<TrashPage>>('/Kb/v1/trash/list', { params })
|
||||
|
||||
/** 恢复资源 */
|
||||
export const restoreTrash = (data: RestoreTrashParams) => {
|
||||
return request.post<ApiResponse<string>>("/Kb/v1/trash/restore", data);
|
||||
};
|
||||
/** 恢复资源。 */
|
||||
export const restoreTrash = (id: number) => request.post<KbReply<string>>('/Kb/v1/trash/restore', { id })
|
||||
|
||||
/** 彻底删除 */
|
||||
export const deleteTrash = (data: DeleteTrashParams) => {
|
||||
return request.post<ApiResponse<string>>("/Kb/v1/trash/delete", data);
|
||||
};
|
||||
/** 彻底删除资源。 */
|
||||
export const deleteTrash = (id: number) => request.post<KbReply<string>>('/Kb/v1/trash/delete', { id })
|
||||
|
||||
7
src/api/kb/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/** 知识库服务统一响应。 */
|
||||
export interface KbReply<T> {
|
||||
code: number
|
||||
message: string
|
||||
details: T
|
||||
timeseq: number
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { request } from '@/api/request'
|
||||
|
||||
export interface MessageRecord {
|
||||
id: number
|
||||
@@ -10,19 +11,93 @@ export interface MessageRecord {
|
||||
time: string
|
||||
status: 0 | 1
|
||||
messageType?: number
|
||||
deliveryStatus?: string
|
||||
channelType?: string
|
||||
attemptCount?: number
|
||||
lastError?: string
|
||||
incidentId?: number
|
||||
alertRecordId?: number
|
||||
nextRetryAt?: string
|
||||
occurrenceCount?: number
|
||||
firstOccurredAt?: string
|
||||
lastOccurredAt?: string
|
||||
lastDeliveryId?: number
|
||||
}
|
||||
export type MessageListType = MessageRecord[]
|
||||
|
||||
export function queryMessageList() {
|
||||
return axios.post<MessageListType>('/api/message/list')
|
||||
interface ApiResponse<T> {
|
||||
code?: number
|
||||
message?: string
|
||||
data?: T
|
||||
details?: T
|
||||
}
|
||||
|
||||
/** 通知投递历史 */
|
||||
export interface NotificationDeliveryRecord {
|
||||
id: number
|
||||
incident_id: number
|
||||
alert_record_id: number
|
||||
channel_id: number
|
||||
channel_type: string
|
||||
target: string
|
||||
subject: string
|
||||
content: string
|
||||
status: string
|
||||
attempt_count: number
|
||||
next_retry_at?: string
|
||||
last_error?: string
|
||||
trace_id?: string
|
||||
delivered_at?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
/** 投递历史查询参数 */
|
||||
export interface NotificationDeliveryQuery {
|
||||
page?: number
|
||||
page_size?: number
|
||||
keyword?: string
|
||||
incident_id?: number
|
||||
status?: string
|
||||
channel_type?: string
|
||||
}
|
||||
|
||||
/** 分页结果 */
|
||||
export interface PageResult<T> {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: T[]
|
||||
}
|
||||
|
||||
function unwrapData<T>(response: ApiResponse<T> | T): T {
|
||||
const wrapped = response as ApiResponse<T>
|
||||
return (wrapped.details ?? wrapped.data ?? response) as T
|
||||
}
|
||||
|
||||
/** 查询站内消息列表 */
|
||||
export async function queryMessageList() {
|
||||
const response = await request.get<ApiResponse<MessageListType>>('/Alert/v1/message/list')
|
||||
return { data: unwrapData<MessageListType>(response) || [] }
|
||||
}
|
||||
|
||||
interface MessageStatus {
|
||||
ids: number[]
|
||||
}
|
||||
|
||||
/** 标记站内消息已读 */
|
||||
export function setMessageStatus(data: MessageStatus) {
|
||||
return axios.post<MessageListType>('/api/message/read', data)
|
||||
return request.post<ApiResponse<boolean>>('/Alert/v1/message/read', data)
|
||||
}
|
||||
|
||||
/** 查询通知投递历史 */
|
||||
export function queryNotificationDeliveryHistory(params?: NotificationDeliveryQuery) {
|
||||
return request.get<ApiResponse<PageResult<NotificationDeliveryRecord>>>('/Alert/v1/notification/deliveries', { params: params || {} })
|
||||
}
|
||||
|
||||
/** 人工补发通知 */
|
||||
export function resendNotificationDelivery(id: number) {
|
||||
return request.post<ApiResponse<{ delivery_id: number; status: string }>>(`/Alert/v1/notification/deliveries/${id}/resend`)
|
||||
}
|
||||
|
||||
export interface ChatRecord {
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 批次列表 */
|
||||
export const fetchLoanBatch = (data: { page: number, size: number }) => request.post("/factor/v1/fetch/loan_batch", data);
|
||||
export const fetchLoanBatch = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/loan_batch', data)
|
||||
|
||||
/** 上报列表 */
|
||||
export const fetchTransferWatch = (data: { page: number, size: number }) => request.post("/factor/v1/fetch/transfer_watch", data);
|
||||
export const fetchTransferWatch = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/transfer_watch', data)
|
||||
|
||||
/** 回盘列表 */
|
||||
export const fetchTransferDown = (data: { page: number, size: number }) => request.post("/factor/v1/fetch/transfer_down", data);
|
||||
export const fetchTransferDown = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/transfer_down', data)
|
||||
|
||||
/** 放款数据列表 */
|
||||
export const fetchDataFile = (data: { page: number, size: number }) => request.post("/factor/v1/fetch/data_file", data);
|
||||
export const fetchDataFile = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/data_file', data)
|
||||
|
||||
/** 回盘数据列表 */
|
||||
export const fetchDataReply = (data: { page: number, size: number }) => request.post("/factor/v1/fetch/data_reply", data);
|
||||
export const fetchDataReply = (data: { page: number; size: number }) => request.post('/factor/v1/fetch/data_reply', data)
|
||||
|
||||
/** 贷款支付数据列表 */
|
||||
export const fetchLoanPayment = (data: { page: number, size: number, status?: number }) => request.post("/factor/v1/fetch/loan_payment", data);
|
||||
export const fetchLoanPayment = (data: { page: number; size: number; status?: number }) =>
|
||||
request.post('/factor/v1/fetch/loan_payment', data)
|
||||
|
||||
/** 获取日报数据 */
|
||||
export const fetchOverviewReports = (data: { page: number, size: number }) => request.post("/factor/v1/reports/overview", data);
|
||||
export const fetchOverviewReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/overview', data)
|
||||
|
||||
/** 获取日报数据 */
|
||||
export const fetchDailyReports = (data: { page: number, size: number }) => request.post("/factor/v1/reports/days", data);
|
||||
export const fetchDailyReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/days', data)
|
||||
|
||||
/** 获取周报数据 */
|
||||
export const fetchWeeklyReports = (data: { page: number, size: number }) => request.post("/factor/v1/reports/weeks", data);
|
||||
export const fetchWeeklyReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/weeks', data)
|
||||
|
||||
/** 获取月报数据 */
|
||||
export const fetchMonthlyReports = (data: { page: number, size: number }) => request.post("/factor/v1/reports/months", data);
|
||||
|
||||
export const fetchMonthlyReports = (data: { page: number; size: number }) => request.post('/factor/v1/reports/months', data)
|
||||
|
||||
/** 获取批次详情 */
|
||||
export const getLoanBatchDetail = (data: { batch_id: number }) => request.post(`/factor/v1/get/batch`,data);
|
||||
export const getLoanBatchDetail = (data: { batch_id: number }) => request.post(`/factor/v1/get/batch`, data)
|
||||
|
||||
@@ -1,43 +1,44 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
export interface MenuItem {
|
||||
id?: number;
|
||||
identity?: string;
|
||||
code?: string;
|
||||
description?: string;
|
||||
menu_icon?: string;
|
||||
menu_path?: string;
|
||||
parent_id?: number | null;
|
||||
title?: string;
|
||||
title_en?: string;
|
||||
type?: number;
|
||||
sort_key?: number;
|
||||
order?: number; // 排序字段(用于本地排序)
|
||||
app_id?: number;
|
||||
created_at?: string;
|
||||
children?: MenuItem[];
|
||||
is_web_page?: boolean; // 是否为网页
|
||||
web_url?: string; // 嵌入的网页URL
|
||||
component?: string; // 路由文件地址
|
||||
is_new_tab?: boolean; // 是否在新窗口打开
|
||||
is_full?: boolean; // 单独的页面,不包含菜单
|
||||
hide_menu?: boolean; // 隐藏菜单栏的菜单
|
||||
id?: number
|
||||
identity?: string
|
||||
code?: string
|
||||
description?: string
|
||||
menu_icon?: string
|
||||
menu_path?: string
|
||||
parent_id?: number | null
|
||||
title?: string
|
||||
title_en?: string
|
||||
type?: number
|
||||
sort_key?: number
|
||||
order?: number // 排序字段(用于本地排序)
|
||||
app_id?: number
|
||||
created_at?: string
|
||||
children?: MenuItem[]
|
||||
is_web_page?: boolean // 是否为网页
|
||||
web_url?: string // 嵌入的网页URL
|
||||
component?: string // 路由文件地址
|
||||
is_new_tab?: boolean // 是否在新窗口打开
|
||||
is_full?: boolean // 单独的页面,不包含菜单
|
||||
hide_menu?: boolean // 隐藏菜单栏的菜单
|
||||
}
|
||||
|
||||
/** 获取菜单 */
|
||||
export const fetchMenu = (data: { page: number, size: number }) => request.post("/rbac2/v1/pmn/fetch", data, { needWorkspace: true });
|
||||
export const fetchMenu = (data: { page: number; size: number }) => request.post('/rbac2/v1/pmn/fetch', data, { needWorkspace: true })
|
||||
/** 创建菜单 */
|
||||
export const createMenu = (data: MenuItem) => request.post("/rbac2/v1/pmn/create", data, { needWorkspace: true });
|
||||
export const createMenu = (data: MenuItem) => request.post('/rbac2/v1/pmn/create', data, { needWorkspace: true })
|
||||
/** 修改菜单 */
|
||||
export const modifyMenu = (data: MenuItem) => request.post("/rbac2/v1/pmn/modify", data, { needWorkspace: true });
|
||||
export const modifyMenu = (data: MenuItem) => request.post('/rbac2/v1/pmn/modify', data, { needWorkspace: true })
|
||||
/** 删除菜单 */
|
||||
export const deleteMenu = (data: { id: MenuItem['id'] }) => request.post("/rbac2/v1/pmn/del", data, { needWorkspace: true });
|
||||
export const deleteMenu = (data: { id: MenuItem['id'] }) => request.post('/rbac2/v1/pmn/del', data, { needWorkspace: true })
|
||||
/** 更新菜单排序 */
|
||||
export const updateMenuOrder = (data: { pmn_id: number, sort_key: number }[]) =>
|
||||
request.post("/rbac2/v1/pmn/sort", data);
|
||||
export const updateMenuOrder = (data: { pmn_id: number; sort_key: number }[]) => request.post('/rbac2/v1/pmn/sort', data)
|
||||
|
||||
/** 用户-给指定用户设置权限 */
|
||||
export const userPmn = (data: { code: string; list: { id: number, pmn_id: number }[] }) => request.post("/rbac2/v1/pmn/user_pmn", data, { needWorkspace: true });
|
||||
export const userPmn = (data: { code: string; list: { id: number; pmn_id: number }[] }) =>
|
||||
request.post('/rbac2/v1/pmn/user_pmn', data, { needWorkspace: true })
|
||||
|
||||
/** 用户-给指定用户设置权限 */
|
||||
export const userSetPmn = (data: { list: { id: number, pmn_id: number }[] }) => request.post("/rbac2/v1/pmn/user/set_pmn", data, { needWorkspace: true });
|
||||
export const userSetPmn = (data: { list: { id: number; pmn_id: number }[] }) =>
|
||||
request.post('/rbac2/v1/pmn/user/set_pmn', data, { needWorkspace: true })
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
import { request } from "@/api/request";
|
||||
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 获取报表 */
|
||||
export const fetchReports = (data: { page: number, size: number, keyword?: string }) => request.get("/api/v1/report/basics", { params: data });
|
||||
export const fetchReports = (data: { page: number; size: number; keyword?: string }) =>
|
||||
request.get('/api/v1/report/basics', { params: data })
|
||||
|
||||
/** 创建报表任务 */
|
||||
export const fetchReportNewTask = (keyName:string,data: any) => request.post("/api/v1/report/task/new/"+keyName, data);
|
||||
export const fetchReportNewTask = (keyName: string, data: any) => request.post('/api/v1/report/task/new/' + keyName, data)
|
||||
|
||||
/** 获取报表基础信息详情 */
|
||||
export const fetchReportBasicInfo = (id: string) => request.get(`/api/v1/report/basics/${id}`);
|
||||
export const fetchReportBasicInfo = (id: string) => request.get(`/api/v1/report/basics/${id}`)
|
||||
|
||||
/** 获取指定报表的调度列表 */
|
||||
export const fetchReportSchedules = (report_basic_id: string) => request.get(`/api/v1/report/schedules/${report_basic_id}`);
|
||||
export const fetchReportSchedules = (report_basic_id: string) => request.get(`/api/v1/report/schedules/${report_basic_id}`)
|
||||
|
||||
/** 批量创建报表调度 */
|
||||
export const fetchReportSchedulesBatch = (data: any) => request.post("/api/v1/report/schedules/batch", data);
|
||||
export const fetchReportSchedulesBatch = (data: any) => request.post('/api/v1/report/schedules/batch', data)
|
||||
|
||||
/** 获取指定报表的历史记录列表 */
|
||||
export const fetchReportHistories = (report_basic_id: string) => request.get(`/api/v1/report/histories/${report_basic_id}?status=2`);
|
||||
export const fetchReportHistories = (report_basic_id: string) => request.get(`/api/v1/report/histories/${report_basic_id}?status=2`)
|
||||
|
||||
/** 获取报表历史记录列表 */
|
||||
export const fetchReportHistoriesList = (data: { page: number, size: number, keyword?: string }) => request.get("/api/v1/report/histories", { params: data });
|
||||
export const fetchReportHistoriesList = (data: { page: number; size: number; keyword?: string }) =>
|
||||
request.get('/api/v1/report/histories', { params: data })
|
||||
|
||||
/** 获取邮件推送记录列表 */
|
||||
export enum PushStatus {
|
||||
/** 发送成功 */
|
||||
Success = 1,
|
||||
/** 发送失败 */
|
||||
Failed = 2
|
||||
Failed = 2,
|
||||
}
|
||||
export const fetchReportPushesList = (data: { page: number, size: number, keyword?: string, status?: PushStatus }) => request.get("/api/v1/report/pushes", { params: data });
|
||||
export const fetchReportPushesList = (data: { page: number; size: number; keyword?: string; status?: PushStatus }) =>
|
||||
request.get('/api/v1/report/pushes', { params: data })
|
||||
|
||||
/** 重新发送邮件 */
|
||||
export const fetchReportPushesResend = (id: number) => request.post(`/api/v1/report/pushes/${id}`);
|
||||
export const fetchReportPushesResend = (id: number) => request.post(`/api/v1/report/pushes/${id}`)
|
||||
|
||||
@@ -1,49 +1,52 @@
|
||||
import { request } from "@/api/request";
|
||||
import { LoginRequest, UserItem } from "../types";
|
||||
import { request } from '@/api/request'
|
||||
import { LoginRequest, UserItem } from '../types'
|
||||
|
||||
/** 登录 */
|
||||
export const login = (data: LoginRequest) => request.post("/rbac2/v1/login", data);
|
||||
export const login = (data: LoginRequest) => request.post('/rbac2/v1/login', data)
|
||||
/** 登出 */
|
||||
export const logout = () => request.post("/rbac2/v1/logout");
|
||||
export const logout = () => request.post('/rbac2/v1/logout')
|
||||
/** 获取菜单列表 */
|
||||
export const getMenuList = () => request.post("/rbac2/v1/user/menu");
|
||||
export const getMenuList = () => request.post('/rbac2/v1/user/menu')
|
||||
/** 创建用户 */
|
||||
export const createUser = (data: UserItem) => request.post("/rbac2/v1/user/create", data, { needWorkspace: true });
|
||||
export const createUser = (data: UserItem) => request.post('/rbac2/v1/user/create', data, { needWorkspace: true })
|
||||
/** 获取用户详情 */
|
||||
export const getUserDetail = (data: UserItem) => request.post("/rbac2/v1/user/detail", data);
|
||||
export const getUserDetail = (data: UserItem) => request.post('/rbac2/v1/user/detail', data)
|
||||
/** 获取用户列表 */
|
||||
export const fetchUserList = (data: { page: number, size: number, keyword?: string }) => request.post("/rbac2/v1/user/fetch", data);
|
||||
export const fetchUserList = (data: { page: number; size: number; keyword?: string }) => request.post('/rbac2/v1/user/fetch', data)
|
||||
/** 修改用户 */
|
||||
export const modifyUser = (data: UserItem) => request.post("/rbac2/v1/user/modify", data);
|
||||
export const modifyUser = (data: UserItem) => request.post('/rbac2/v1/user/modify', data)
|
||||
/** 删除用户 */
|
||||
export const deleteUser = (data: { id: UserItem['id'] }) => request.post("/rbac2/v1/user/del", data);
|
||||
export const deleteUser = (data: { id: UserItem['id'] }) => request.post('/rbac2/v1/user/del', data)
|
||||
/** 获取所有权限【树形】 */
|
||||
export const getUserPmnTree = (data: { id: UserItem['id'], workspace: string }) => request.post("/rbac2/v1/user/pmn_tree", data);
|
||||
export const getUserPmnTree = (data: { id: UserItem['id']; workspace: string }) => request.post('/rbac2/v1/user/pmn_tree', data)
|
||||
|
||||
/** 用户-获取所有权限【平面】 */
|
||||
export const userPmn = (data: { id: UserItem['id'], workspace: string }) => request.post("/rbac2/v1/user/pmn", data, { needWorkspace: true });
|
||||
export const userPmn = (data: { id: UserItem['id']; workspace: string }) =>
|
||||
request.post('/rbac2/v1/user/pmn', data, { needWorkspace: true })
|
||||
/** 用户-给指定用户设置权限 */
|
||||
export const userSetPmn = (data: { list: { id: number, pmn_id: number }[] }) => request.post("/rbac2/v1/user/set_pmn", data, { needWorkspace: true });
|
||||
export const userSetPmn = (data: { list: { id: number; pmn_id: number }[] }) =>
|
||||
request.post('/rbac2/v1/user/set_pmn', data, { needWorkspace: true })
|
||||
|
||||
/** 用户-给指定用户编辑权限 */
|
||||
export const userModifyPmn = (data: { id: UserItem['id'], list: number[] }) => request.post("/rbac2/v1/user/modify_pmn", data, { needWorkspace: true });
|
||||
export const userModifyPmn = (data: { id: UserItem['id']; list: number[] }) =>
|
||||
request.post('/rbac2/v1/user/modify_pmn', data, { needWorkspace: true })
|
||||
|
||||
/** 重置密码(短信) */
|
||||
export const resetUserPassword = (data: {
|
||||
/** 账号 */
|
||||
account: string;
|
||||
account: string
|
||||
/** 验证码 */
|
||||
code: string;
|
||||
code: string
|
||||
/** 密码 */
|
||||
password: string;
|
||||
password: string
|
||||
/** 手机号 */
|
||||
phone: string;
|
||||
}) => request.post("/rbac2/v1/reset", data);
|
||||
phone: string
|
||||
}) => request.post('/rbac2/v1/reset', data)
|
||||
|
||||
/** 管理员重置用户密码 */
|
||||
export const adminResetUserPassword = (data: {
|
||||
/** 用户ID */
|
||||
id: number;
|
||||
id: number
|
||||
/** 新密码 */
|
||||
password: string;
|
||||
}) => request.post("/rbac2/v1/user/reset_password", data);
|
||||
password: string
|
||||
}) => request.post('/rbac2/v1/user/reset_password', data)
|
||||
|
||||
17
src/api/ops/alertEvent.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { request } from '@/api/request'
|
||||
|
||||
export const fetchAlertEvents = (data: {
|
||||
page?: number
|
||||
page_size?: number
|
||||
alert_record_id?: number
|
||||
event_type?: string
|
||||
source?: string
|
||||
severity?: string
|
||||
start_time?: string
|
||||
end_time?: string
|
||||
keyword?: string
|
||||
sort?: string
|
||||
order?: string
|
||||
}) => request.get('/Alert/v1/event/list', { params: data })
|
||||
|
||||
export const fetchAlertEventDetail = (id: number) => request.get(`/Alert/v1/event/get/${id}`)
|
||||
@@ -1,56 +1,53 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 获取 告警记录列表 */
|
||||
export const fetchHistories = (data: {
|
||||
page?: number,
|
||||
page_size?: number,
|
||||
size?: number,
|
||||
policy_id?: number,
|
||||
rule_id?: number,
|
||||
status?: string,
|
||||
severity_id?: number,
|
||||
starts_at?: string,
|
||||
ends_at?: string,
|
||||
export const fetchHistories = (data: {
|
||||
page?: number
|
||||
page_size?: number
|
||||
size?: number
|
||||
policy_id?: number
|
||||
rule_id?: number
|
||||
status?: string
|
||||
severity_id?: number
|
||||
starts_at?: string
|
||||
ends_at?: string
|
||||
keyword?: string
|
||||
}) => {
|
||||
// 兼容 size 参数,转换为 page_size
|
||||
const params: any = { ...data };
|
||||
const params: any = { ...data }
|
||||
if (params.size !== undefined && params.page_size === undefined) {
|
||||
params.page_size = params.size;
|
||||
delete params.size;
|
||||
params.page_size = params.size
|
||||
delete params.size
|
||||
}
|
||||
return request.get("/Alert/v1/record/list", { params });
|
||||
};
|
||||
return request.get('/Alert/v1/record/list', { params })
|
||||
}
|
||||
|
||||
/** 获取 告警记录详情 */
|
||||
export const fetchHistoryDetail = (id: number) => request.get(`/Alert/v1/record/get/${id}`);
|
||||
export const fetchHistoryDetail = (id: number) => request.get(`/Alert/v1/record/get/${id}`)
|
||||
|
||||
/** 获取 告警统计 */
|
||||
export const fetchAlertStatistics = (data: {
|
||||
policy_id?: number,
|
||||
starts_at?: string,
|
||||
ends_at?: string
|
||||
}) => request.get("/Alert/v1/record/statistics", { params: data });
|
||||
export const fetchAlertStatistics = (data: { policy_id?: number; starts_at?: string; ends_at?: string }) =>
|
||||
request.get('/Alert/v1/record/statistics', { params: data })
|
||||
|
||||
/** 获取 告警计数 */
|
||||
export const fetchAlertCount = () => request.get("/Alert/v1/record/count");
|
||||
export const fetchAlertCount = () => request.get('/Alert/v1/record/count')
|
||||
|
||||
/** 获取 告警处理记录列表 */
|
||||
export const fetchAlertProcessList = (data: {
|
||||
alert_record_id?: number,
|
||||
action?: string,
|
||||
page?: number,
|
||||
page_size?: number,
|
||||
keyword?: string,
|
||||
sort?: string,
|
||||
alert_record_id?: number
|
||||
action?: string
|
||||
page?: number
|
||||
page_size?: number
|
||||
keyword?: string
|
||||
sort?: string
|
||||
order?: string
|
||||
}) => request.get("/Alert/v1/process/list", { params: data });
|
||||
}) => request.get('/Alert/v1/process/list', { params: data })
|
||||
|
||||
/** 获取 告警趋势 */
|
||||
export const fetchAlertTrend = (data: {
|
||||
granularity?: string, // day / month
|
||||
start_time?: string,
|
||||
end_time?: string,
|
||||
policy_id?: number,
|
||||
granularity?: string // day / month
|
||||
start_time?: string
|
||||
end_time?: string
|
||||
policy_id?: number
|
||||
severity_id?: number
|
||||
}) => request.get("/Alert/v1/record/trend", { params: data });
|
||||
}) => request.get('/Alert/v1/record/trend', { params: data })
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 获取告警级别列表(分页) */
|
||||
export const fetchAlertLevelList = (data?: {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
keyword?: string;
|
||||
enabled?: string;
|
||||
}) => {
|
||||
return request.get("/Alert/v1/severity/list", { params: data || {} });
|
||||
};
|
||||
export const fetchAlertLevelList = (data?: { page?: number; page_size?: number; keyword?: string; enabled?: string }) => {
|
||||
return request.get('/Alert/v1/severity/list', { params: data || {} })
|
||||
}
|
||||
|
||||
/** 获取告警级别下拉选项(不分页),默认仅返回 enabled=true */
|
||||
export const fetchAlertLevelOptions = (data?: {
|
||||
keyword?: string;
|
||||
enabled?: 'true' | 'false';
|
||||
}) => {
|
||||
return request.get("/Alert/v1/severity/options", {
|
||||
export const fetchAlertLevelOptions = (data?: { keyword?: string; enabled?: 'true' | 'false' }) => {
|
||||
return request.get('/Alert/v1/severity/options', {
|
||||
params: {
|
||||
keyword: data?.keyword || undefined,
|
||||
enabled: data?.enabled ?? 'true',
|
||||
@@ -25,39 +17,39 @@ export const fetchAlertLevelOptions = (data?: {
|
||||
|
||||
/** 获取告警级别详情 */
|
||||
export const fetchAlertLevelDetail = (id: number) => {
|
||||
return request.get(`/Alert/v1/severity/get/${id}`);
|
||||
};
|
||||
return request.get(`/Alert/v1/severity/get/${id}`)
|
||||
}
|
||||
|
||||
/** 创建告警级别 */
|
||||
export const createAlertLevel = (data: {
|
||||
name: string;
|
||||
code: string;
|
||||
description?: string;
|
||||
color: string;
|
||||
icon?: string;
|
||||
priority?: number;
|
||||
enabled?: boolean;
|
||||
config?: string;
|
||||
name: string
|
||||
code: string
|
||||
description?: string
|
||||
color: string
|
||||
icon?: string
|
||||
priority?: number
|
||||
enabled?: boolean
|
||||
config?: string
|
||||
}) => {
|
||||
return request.post("/Alert/v1/severity/create", data);
|
||||
};
|
||||
return request.post('/Alert/v1/severity/create', data)
|
||||
}
|
||||
|
||||
/** 更新告警级别 */
|
||||
export const updateAlertLevel = (data: {
|
||||
id: number;
|
||||
name?: string;
|
||||
code?: string;
|
||||
description?: string;
|
||||
color?: string;
|
||||
icon?: string;
|
||||
priority?: number;
|
||||
enabled?: boolean;
|
||||
config?: string;
|
||||
id: number
|
||||
name?: string
|
||||
code?: string
|
||||
description?: string
|
||||
color?: string
|
||||
icon?: string
|
||||
priority?: number
|
||||
enabled?: boolean
|
||||
config?: string
|
||||
}) => {
|
||||
return request.post("/Alert/v1/severity/update", data);
|
||||
};
|
||||
return request.post('/Alert/v1/severity/update', data)
|
||||
}
|
||||
|
||||
/** 删除告警级别 */
|
||||
export const deleteAlertLevel = (id: number) => {
|
||||
return request.delete(`/Alert/v1/severity/delete/${id}`);
|
||||
};
|
||||
return request.delete(`/Alert/v1/severity/delete/${id}`)
|
||||
}
|
||||
|
||||
@@ -68,10 +68,11 @@ export const createRule = (data: {
|
||||
severity_id: number
|
||||
enabled?: boolean
|
||||
metric_name?: string
|
||||
query_expr?: string
|
||||
data_source?: string
|
||||
threshold?: number
|
||||
compare_op?: string
|
||||
duration?: number
|
||||
eval_interval?: number
|
||||
baseline_config?: string
|
||||
labels?: string
|
||||
annotations?: string
|
||||
@@ -86,10 +87,11 @@ export const updateRule = (data: {
|
||||
severity_id?: number
|
||||
enabled?: boolean
|
||||
metric_name?: string
|
||||
query_expr?: string
|
||||
data_source?: string
|
||||
threshold?: number
|
||||
compare_op?: string
|
||||
duration?: number
|
||||
eval_interval?: number
|
||||
baseline_config?: string
|
||||
labels?: string
|
||||
annotations?: string
|
||||
|
||||
@@ -1,49 +1,53 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 获取 当前告警记录列表 */
|
||||
export const fetchAlertRecords = (data: {
|
||||
page?: number,
|
||||
page_size?: number,
|
||||
policy_id?: number,
|
||||
rule_id?: number,
|
||||
status?: string,
|
||||
severity_id?: number,
|
||||
start_time?: string,
|
||||
end_time?: string,
|
||||
export const fetchAlertRecords = (data: {
|
||||
page?: number
|
||||
page_size?: number
|
||||
policy_id?: number
|
||||
rule_id?: number
|
||||
status?: string
|
||||
severity_id?: number
|
||||
start_time?: string
|
||||
end_time?: string
|
||||
keyword?: string
|
||||
sort?: string
|
||||
order?: string
|
||||
binding_id?: number
|
||||
resource_category?: string
|
||||
server_identity?: string
|
||||
ip?: string
|
||||
}) => {
|
||||
return request.get("/Alert/v1/record/list", { params: data });
|
||||
};
|
||||
return request.get('/Alert/v1/record/list', { params: data })
|
||||
}
|
||||
|
||||
/** 获取 告警记录详情 */
|
||||
export const fetchAlertRecordDetail = (id: number) => request.get(`/Alert/v1/record/get/${id}`);
|
||||
export const fetchAlertRecordDetail = (id: number) => request.get(`/Alert/v1/record/get/${id}`)
|
||||
|
||||
/** 创建处理记录(执行确认/解决/屏蔽等操作) */
|
||||
export const createAlertProcess = (data: {
|
||||
alert_record_id: number;
|
||||
action: string; // ack / resolve / silence / comment / assign / escalate / close
|
||||
operator: string;
|
||||
operator_id?: string;
|
||||
comment?: string;
|
||||
assign_to?: string;
|
||||
assign_to_id?: string;
|
||||
silence_until?: string;
|
||||
silence_reason?: string;
|
||||
escalate_level?: string;
|
||||
escalate_to?: string;
|
||||
root_cause?: string;
|
||||
solution?: string;
|
||||
alert_record_id: number
|
||||
action: string // ack / resolve / silence / comment / assign / escalate / close
|
||||
comment?: string
|
||||
assign_to?: string
|
||||
assign_to_id?: string
|
||||
silence_until?: string
|
||||
silence_reason?: string
|
||||
escalate_level?: string
|
||||
escalate_to?: string
|
||||
root_cause?: string
|
||||
solution?: string
|
||||
// 按后端约定:metadata 为 JSON 字符串,例如 "{}"
|
||||
metadata?: string;
|
||||
}) => request.post("/Alert/v1/process/create", data);
|
||||
metadata?: string
|
||||
}) => request.post('/Alert/v1/process/create', data)
|
||||
|
||||
/** 获取 告警处理记录列表 */
|
||||
export const fetchAlertProcessList = (data: {
|
||||
alert_record_id?: number,
|
||||
action?: string,
|
||||
page?: number,
|
||||
page_size?: number,
|
||||
keyword?: string,
|
||||
sort?: string,
|
||||
alert_record_id?: number
|
||||
action?: string
|
||||
page?: number
|
||||
page_size?: number
|
||||
keyword?: string
|
||||
sort?: string
|
||||
order?: string
|
||||
}) => request.get("/Alert/v1/process/list", { params: data });
|
||||
}) => request.get('/Alert/v1/process/list', { params: data })
|
||||
|
||||
@@ -20,12 +20,13 @@ export interface AlertRule {
|
||||
name: string
|
||||
data_source: string
|
||||
metric_name: string
|
||||
rule_type: 'static' | 'dynamic' | 'promql'
|
||||
rule_type: 'static' | 'dynamic'
|
||||
compare_op: '>' | '>=' | '<' | '<=' | '==' | '!='
|
||||
threshold: string | number
|
||||
duration: number
|
||||
eval_interval: number
|
||||
severity_code: string
|
||||
baseline_config?: string
|
||||
labels?: Record<string, string>
|
||||
annotations?: Record<string, string>
|
||||
}
|
||||
@@ -105,12 +106,11 @@ export const TEMPLATE_CATEGORIES = [
|
||||
// 数据源选项
|
||||
export const DATA_SOURCES = [
|
||||
{ value: 'dc-host', label: '主机/操作系统指标' },
|
||||
{ value: 'dc-hardware', label: '服务器硬件指标' },
|
||||
{ value: 'dc-network', label: '网络设备指标' },
|
||||
{ value: 'dc-database', label: '数据库指标' },
|
||||
{ value: 'dc-middleware', label: '中间件指标' },
|
||||
{ value: 'dc-virtualization', label: '虚拟化指标' },
|
||||
{ value: 'dc-env', label: '动力/环境/安防指标' },
|
||||
{ value: 'dc-security', label: '安全设备指标' },
|
||||
{ value: 'dc-storage', label: '存储设备指标' },
|
||||
{ value: 'dc-room-device', label: '机房设备指标' },
|
||||
]
|
||||
|
||||
// 比较运算符选项
|
||||
@@ -127,19 +127,12 @@ export const COMPARE_OPERATORS = [
|
||||
export const RULE_TYPES = [
|
||||
{ value: 'static', label: '静态阈值' },
|
||||
{ value: 'dynamic', label: '动态阈值' },
|
||||
{ value: 'promql', label: 'PromQL 表达式' },
|
||||
]
|
||||
|
||||
// ==================== 告警模板接口 ====================
|
||||
|
||||
/** 获取告警模板列表 */
|
||||
export const fetchTemplateList = (params?: {
|
||||
page?: number
|
||||
page_size?: number
|
||||
name?: string
|
||||
category?: string
|
||||
enabled?: boolean
|
||||
}) => {
|
||||
export const fetchTemplateList = (params?: { page?: number; page_size?: number; name?: string; category?: string; enabled?: boolean }) => {
|
||||
return request.get('/Alert/v1/template/list', { params })
|
||||
}
|
||||
|
||||
@@ -195,10 +188,7 @@ export const fetchSeverityList = () => {
|
||||
}
|
||||
|
||||
/** 获取告警级别下拉选项(不分页),支持 keyword 模糊搜索与 enabled=true 过滤 */
|
||||
export const fetchSeverityOptions = (params?: {
|
||||
keyword?: string
|
||||
enabled?: 'true' | 'false'
|
||||
}) => {
|
||||
export const fetchSeverityOptions = (params?: { keyword?: string; enabled?: 'true' | 'false' }) => {
|
||||
return request.get('/Alert/v1/severity/options', {
|
||||
params: {
|
||||
keyword: params?.keyword || undefined,
|
||||
@@ -215,11 +205,6 @@ export const fetchSeverityByCode = (code: string) => {
|
||||
// ==================== 指标元数据接口 ====================
|
||||
|
||||
/** 获取指标元数据 */
|
||||
export const fetchMetricsMeta = (params: {
|
||||
data_source: string
|
||||
server_identity?: string
|
||||
keyword?: string
|
||||
limit?: number
|
||||
}) => {
|
||||
export const fetchMetricsMeta = (params: { data_source: string; server_identity?: string; keyword?: string; limit?: number }) => {
|
||||
return request.get('/DC-Control/v1/services/metrics/meta', { params })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,13 +42,6 @@ export interface AssetListParams {
|
||||
page_size?: number
|
||||
keyword?: string
|
||||
status?: string
|
||||
category_id?: number
|
||||
supplier_id?: number
|
||||
datacenter_id?: number
|
||||
floor_id?: number
|
||||
room_id?: number
|
||||
rack_id?: number
|
||||
department?: string
|
||||
sort?: string
|
||||
order?: string
|
||||
}
|
||||
@@ -62,10 +55,11 @@ export interface AssetForm {
|
||||
model?: string
|
||||
manufacturer?: string
|
||||
serial_number?: string
|
||||
source_address?: string
|
||||
purchase_date?: string
|
||||
original_value?: number
|
||||
supplier_id?: number
|
||||
warranty_period?: string
|
||||
warranty_period?: number
|
||||
warranty_expiry?: string
|
||||
department?: string
|
||||
user?: string
|
||||
@@ -74,9 +68,6 @@ export interface AssetForm {
|
||||
datacenter_id?: number
|
||||
floor_id?: number
|
||||
room_id?: number
|
||||
rack_id?: number
|
||||
unit_start?: number
|
||||
unit_end?: number
|
||||
qr_code?: string
|
||||
rfid_tag?: string
|
||||
asset_tag?: string
|
||||
@@ -105,6 +96,11 @@ export const createAsset = (data: AssetForm) => {
|
||||
return request.post('/Assets/v1/asset/create', data)
|
||||
}
|
||||
|
||||
/** 批量导入资产 */
|
||||
export const bulkImportAssets = (data: { dry_run?: boolean; items: any[] }) => {
|
||||
return request.post('/Assets/v1/asset/bulk_import', data)
|
||||
}
|
||||
|
||||
/** 更新资产 */
|
||||
export const updateAsset = (data: AssetForm) => {
|
||||
return request.put('/Assets/v1/asset/update', data)
|
||||
@@ -132,17 +128,24 @@ export const fetchSupplierOptions = () => {
|
||||
return request.get('/Assets/v1/supplier/all')
|
||||
}
|
||||
|
||||
/** 获取数据中心列表(下拉) */
|
||||
export const fetchDatacenterOptions = () => {
|
||||
return request.get('/Assets/v1/datacenter/list')
|
||||
/** 绑定资产和监控资源 */
|
||||
export const linkAssetResource = (data: {
|
||||
asset_id: number
|
||||
resource_uid: string
|
||||
display_name?: string
|
||||
business_system_id?: number
|
||||
health_status?: string
|
||||
alert_status?: string
|
||||
}) => {
|
||||
return request.post('/Assets/v1/asset/resource/link', data)
|
||||
}
|
||||
|
||||
/** 根据数据中心获取楼层列表 */
|
||||
export const fetchFloorOptions = (datacenterId: number) => {
|
||||
return request.get(`/Assets/v1/datacenter/${datacenterId}`)
|
||||
/** 查询资产绑定的监控资源 */
|
||||
export const fetchAssetResourceBindings = (assetId: number) => {
|
||||
return request.get(`/Assets/v1/asset/resource/${assetId}`)
|
||||
}
|
||||
|
||||
/** 获取机柜列表(下拉) */
|
||||
export const fetchRackOptions = (params?: { datacenter_id?: number; floor_id?: number }) => {
|
||||
return request.post('/Assets/v1/rack/list', params || {})
|
||||
/** 解除资产和监控资源绑定 */
|
||||
export const unlinkAssetResource = (assetId: number, resourceUid: string) => {
|
||||
return request.delete(`/Assets/v1/asset/resource/${assetId}`, { params: { resource_uid: resourceUid } })
|
||||
}
|
||||
|
||||
87
src/api/ops/automation.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { request } from '@/api/request'
|
||||
|
||||
export interface AutomationScript {
|
||||
id: number
|
||||
name: string
|
||||
resource_category: string
|
||||
command_template: string
|
||||
approval_level: string
|
||||
rollback_command?: string
|
||||
rollback_required: boolean
|
||||
description?: string
|
||||
status: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface AutomationExecution {
|
||||
id: number
|
||||
script_id: number
|
||||
mode: string
|
||||
status: string
|
||||
resource_uid: string
|
||||
rendered_command: string
|
||||
incident_id?: number
|
||||
ticket_id?: number
|
||||
approval_level: string
|
||||
approved_by?: string
|
||||
approved_at?: string
|
||||
operator?: string
|
||||
started_at?: string
|
||||
finished_at?: string
|
||||
timeout_sec?: number
|
||||
stdout?: string
|
||||
stderr?: string
|
||||
exit_code?: number
|
||||
error?: string
|
||||
audit_trail?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface AutomationRunRequest {
|
||||
resource_uid: string
|
||||
incident_id?: number
|
||||
ticket_id?: number
|
||||
operator?: string
|
||||
approver?: string
|
||||
approved?: boolean
|
||||
mode?: 'execute' | 'rollback'
|
||||
variables?: Record<string, string>
|
||||
}
|
||||
|
||||
export interface PageResponse<T> {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: T[]
|
||||
}
|
||||
|
||||
export const fetchAutomationScripts = (params?: Record<string, any>) =>
|
||||
request.get<{ details: PageResponse<AutomationScript> }>('/DC-Control/v1/automation/scripts', { params })
|
||||
|
||||
export const createAutomationScript = (data: Partial<AutomationScript>) =>
|
||||
request.post<{ details: AutomationScript }>('/DC-Control/v1/automation/scripts', data)
|
||||
|
||||
export const updateAutomationScript = (id: number, data: Partial<AutomationScript>) =>
|
||||
request.put(`/DC-Control/v1/automation/scripts/${id}`, data)
|
||||
|
||||
export const deleteAutomationScript = (id: number) => request.delete(`/DC-Control/v1/automation/scripts/${id}`)
|
||||
|
||||
export const dryRunAutomationScript = (id: number, data: AutomationRunRequest) =>
|
||||
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/dry-run`, data)
|
||||
|
||||
export const requestAutomationExecution = (id: number, data: AutomationRunRequest) =>
|
||||
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/executions`, data)
|
||||
|
||||
export const executeAutomationScript = (id: number, data: AutomationRunRequest) =>
|
||||
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/execute`, data)
|
||||
|
||||
export const rollbackAutomationScript = (id: number, data: AutomationRunRequest) =>
|
||||
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/scripts/${id}/rollback`, data)
|
||||
|
||||
export const fetchAutomationExecutions = (params?: Record<string, any>) =>
|
||||
request.get<{ details: PageResponse<AutomationExecution> }>('/DC-Control/v1/automation/executions', { params })
|
||||
|
||||
export const approveAutomationExecution = (id: number, data: { approver: string; operator?: string }) =>
|
||||
request.post<{ details: AutomationExecution }>(`/DC-Control/v1/automation/executions/${id}/approve`, data)
|
||||
104
src/api/ops/bigScreen.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { request } from '@/api/request'
|
||||
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number
|
||||
data?: T
|
||||
details?: T
|
||||
message?: string
|
||||
}
|
||||
|
||||
export interface BigScreen {
|
||||
id: number
|
||||
name: string
|
||||
description?: string
|
||||
thumbnail?: string
|
||||
group_id?: number
|
||||
goview_project_id?: string
|
||||
width: number
|
||||
height: number
|
||||
status: number
|
||||
publish_status: 'draft' | 'published' | 'offline' | string
|
||||
is_public?: boolean
|
||||
creator_name?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface BigScreenGroup {
|
||||
id: number
|
||||
name: string
|
||||
description?: string
|
||||
sort_order: number
|
||||
status: number
|
||||
}
|
||||
|
||||
export interface BigScreenPublish {
|
||||
id: number
|
||||
screen_id: number
|
||||
goview_project_id: string
|
||||
version: string
|
||||
publish_type: number
|
||||
status: number
|
||||
publisher_name?: string
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface BigScreenCarousel {
|
||||
id: number
|
||||
name: string
|
||||
screen_ids: Record<string, any>
|
||||
interval_seconds: number
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export interface BigScreenSnapshot {
|
||||
id: number
|
||||
screen_id: number
|
||||
publish_id?: number
|
||||
file_name: string
|
||||
file_path: string
|
||||
file_size: number
|
||||
checksum?: string
|
||||
exporter_name?: string
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
export interface PageResult<T> {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: T[]
|
||||
}
|
||||
|
||||
export const fetchBigScreens = (params?: { page?: number; page_size?: number; keyword?: string }) =>
|
||||
request.get<ApiResponse<PageResult<BigScreen>>>('/Mgt/v1/screen', { params })
|
||||
|
||||
export const createBigScreen = (data: Partial<BigScreen>) =>
|
||||
request.post<ApiResponse<BigScreen>>('/Mgt/v1/screen', data)
|
||||
|
||||
export const updateBigScreen = (id: number, data: Partial<BigScreen>) =>
|
||||
request.put<ApiResponse<BigScreen>>(`/Mgt/v1/screen/${id}`, data)
|
||||
|
||||
export const publishBigScreen = (data: { screen_id: number; publish_type: 1 | 2; change_log?: string }) =>
|
||||
request.post<ApiResponse<BigScreenPublish>>('/Mgt/v1/publish', data)
|
||||
|
||||
export const fetchBigScreenPublishes = (params: { screen_id: number; page?: number; page_size?: number }) =>
|
||||
request.get<ApiResponse<PageResult<BigScreenPublish>>>('/Mgt/v1/publish', { params })
|
||||
|
||||
export const fetchBigScreenGroups = () =>
|
||||
request.get<ApiResponse<BigScreenGroup[]>>('/Mgt/v1/big-screen/groups')
|
||||
|
||||
export const createBigScreenGroup = (data: Partial<BigScreenGroup>) =>
|
||||
request.post<ApiResponse<BigScreenGroup>>('/Mgt/v1/big-screen/groups', data)
|
||||
|
||||
export const fetchBigScreenCarousels = () =>
|
||||
request.get<ApiResponse<BigScreenCarousel[]>>('/Mgt/v1/big-screen/carousels')
|
||||
|
||||
export const createBigScreenCarousel = (data: Partial<BigScreenCarousel>) =>
|
||||
request.post<ApiResponse<BigScreenCarousel>>('/Mgt/v1/big-screen/carousels', data)
|
||||
|
||||
export const fetchBigScreenSnapshots = (params?: { screen_id?: number }) =>
|
||||
request.get<ApiResponse<BigScreenSnapshot[]>>('/Mgt/v1/big-screen/snapshots', { params })
|
||||
|
||||
export const createBigScreenSnapshot = (data: Partial<BigScreenSnapshot>) =>
|
||||
request.post<ApiResponse<BigScreenSnapshot>>('/Mgt/v1/big-screen/snapshots', data)
|
||||
237
src/api/ops/businessSystem.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 业务系统基础信息 */
|
||||
export interface BusinessSystemItem {
|
||||
id: number
|
||||
code: string
|
||||
name: string
|
||||
system_type: string
|
||||
owner_user_id?: number
|
||||
department_id?: number
|
||||
description?: string
|
||||
status: string
|
||||
is_builtin: boolean
|
||||
health_score?: number
|
||||
health_level?: string
|
||||
resource_count?: number
|
||||
active_incident_count?: number
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
/** 分页响应 */
|
||||
export interface PageResult<T> {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: T[]
|
||||
}
|
||||
|
||||
/** 业务系统列表查询参数 */
|
||||
export interface BusinessSystemListParams {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
status?: string
|
||||
}
|
||||
|
||||
/** 健康分扣分明细 */
|
||||
export interface BusinessHealthFactor {
|
||||
key: string
|
||||
label: string
|
||||
score_delta: number
|
||||
status: string
|
||||
description: string
|
||||
}
|
||||
|
||||
/** 业务健康摘要 */
|
||||
export interface BusinessHealth {
|
||||
business_system_id: number
|
||||
health: {
|
||||
score: number
|
||||
level: string
|
||||
deductions: Record<string, number>
|
||||
}
|
||||
signal_counts: {
|
||||
resources: number
|
||||
url_probes: number
|
||||
active_incidents: number
|
||||
sla_status: string
|
||||
}
|
||||
}
|
||||
|
||||
/** 业务系统资源成员 */
|
||||
export interface BusinessResourceMember {
|
||||
id: number
|
||||
resource_uid: string
|
||||
resource_id?: number
|
||||
role: string
|
||||
criticality: string
|
||||
weight: number
|
||||
description?: string
|
||||
}
|
||||
|
||||
/** 业务拓扑资源 */
|
||||
export interface BusinessTopologyResource {
|
||||
id: number
|
||||
resource_uid: string
|
||||
resource_category: string
|
||||
service_identity: string
|
||||
display_name: string
|
||||
description?: string
|
||||
status: string
|
||||
business_system_id?: number
|
||||
owner_user_id?: number
|
||||
department_id?: number
|
||||
asset_id?: number
|
||||
tags?: string
|
||||
source_service?: string
|
||||
source_table?: string
|
||||
source_id?: number
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
/** 业务拓扑节点 */
|
||||
export interface BusinessTopologyNode {
|
||||
id?: number
|
||||
node_id: string
|
||||
resource_uid: string
|
||||
label: string
|
||||
type: string
|
||||
status: string
|
||||
}
|
||||
|
||||
/** 业务拓扑边 */
|
||||
export interface BusinessTopologyEdge {
|
||||
id?: number
|
||||
source_node_id: string
|
||||
target_node_id: string
|
||||
topology_id?: number
|
||||
}
|
||||
|
||||
/** 业务系统依赖关系 */
|
||||
export interface BusinessDependency {
|
||||
id: number
|
||||
business_system_id: number
|
||||
depends_on_business_system_id: number
|
||||
dependency_type: string
|
||||
criticality: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
/** 业务拓扑 */
|
||||
export interface BusinessTopology {
|
||||
business_system_id: number
|
||||
resources: BusinessTopologyResource[] | null
|
||||
dependencies: BusinessDependency[] | null
|
||||
nodes: BusinessTopologyNode[] | null
|
||||
links: BusinessTopologyEdge[] | null
|
||||
}
|
||||
|
||||
/** 业务时间线项 */
|
||||
export interface BusinessTimelineItem {
|
||||
source: 'raw_event' | 'alert' | 'incident' | 'ticket' | 'note' | 'document'
|
||||
source_id: string
|
||||
occurred_at: string
|
||||
title: string
|
||||
message: string
|
||||
severity?: string
|
||||
status?: string
|
||||
metadata?: Record<string, any>
|
||||
}
|
||||
|
||||
/** 业务笔记 */
|
||||
export interface BusinessNote {
|
||||
id: number
|
||||
business_system_id: number
|
||||
title?: string
|
||||
content: string
|
||||
author_user_id?: number
|
||||
author_name?: string
|
||||
visibility: string
|
||||
occurred_at: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
/** 关联知识或文档 */
|
||||
export interface BusinessDocumentLink {
|
||||
id: number
|
||||
business_system_id: number
|
||||
title: string
|
||||
url: string
|
||||
link_type: string
|
||||
description?: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
/** 列表响应 */
|
||||
export interface ListResult<T> {
|
||||
list: T[] | null
|
||||
count: number
|
||||
}
|
||||
|
||||
/** 获取业务系统列表 */
|
||||
export const fetchBusinessSystems = (params?: BusinessSystemListParams) =>
|
||||
request.get<{ code?: number; details?: PageResult<BusinessSystemItem>; message?: string }>('/DC-Control/v1/business-systems', { params })
|
||||
|
||||
/** 获取业务系统详情 */
|
||||
export const fetchBusinessSystemDetail = (id: number) =>
|
||||
request.get<{ code?: number; details?: BusinessSystemItem; message?: string }>(`/DC-Control/v1/business-systems/${id}`)
|
||||
|
||||
/** 获取业务健康摘要 */
|
||||
export const fetchBusinessHealth = (id: number) =>
|
||||
request.get<{ code?: number; details?: BusinessHealth; message?: string }>(`/DC-Control/v1/business-systems/${id}/health`)
|
||||
|
||||
/** 获取业务资源成员 */
|
||||
export const fetchBusinessMembers = (id: number) =>
|
||||
request.get<{ code?: number; details?: ListResult<BusinessResourceMember>; message?: string }>(`/DC-Control/v1/business-systems/${id}/resources`)
|
||||
|
||||
export interface BusinessResourceMemberPayload {
|
||||
resource_uid?: string
|
||||
resource_id?: number
|
||||
role?: string
|
||||
criticality?: string
|
||||
weight?: number
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const createBusinessMember = (id: number, data: BusinessResourceMemberPayload) =>
|
||||
request.post<{ code?: number; details?: BusinessResourceMember; message?: string }>(`/DC-Control/v1/business-systems/${id}/resources`, data)
|
||||
|
||||
export const deleteBusinessMember = (id: number, memberId: number) =>
|
||||
request.delete<{ code?: number; details?: { message: string }; message?: string }>(`/DC-Control/v1/business-systems/${id}/resources/${memberId}`)
|
||||
|
||||
/** 获取业务拓扑 */
|
||||
export const fetchBusinessTopology = (id: number) =>
|
||||
request.get<{ code?: number; details?: BusinessTopology; message?: string }>(`/DC-Control/v1/business-systems/${id}/topology`)
|
||||
|
||||
/** 获取业务系统依赖 */
|
||||
export const fetchBusinessDependencies = (id: number) =>
|
||||
request.get<{ code?: number; details?: ListResult<BusinessDependency>; message?: string }>(`/DC-Control/v1/business-systems/${id}/dependencies`)
|
||||
|
||||
/** 创建业务系统依赖 */
|
||||
export const createBusinessDependency = (id: number, data: Partial<BusinessDependency>) =>
|
||||
request.post<{ code?: number; details?: BusinessDependency; message?: string }>(`/DC-Control/v1/business-systems/${id}/dependencies`, data)
|
||||
|
||||
/** 获取业务时间线 */
|
||||
export const fetchBusinessTimeline = (id: number, params?: { limit?: number }) =>
|
||||
request.get<{ code?: number; details?: ListResult<BusinessTimelineItem>; message?: string }>(`/DC-Control/v1/business-systems/${id}/timeline`, {
|
||||
params,
|
||||
})
|
||||
|
||||
/** 获取业务笔记 */
|
||||
export const fetchBusinessNotes = (id: number) =>
|
||||
request.get<{ code?: number; details?: ListResult<BusinessNote>; message?: string }>(`/DC-Control/v1/business-systems/${id}/notes`)
|
||||
|
||||
/** 创建业务笔记 */
|
||||
export const createBusinessNote = (id: number, data: { title: string; content: string }) =>
|
||||
request.post<{ code?: number; details?: BusinessNote; message?: string }>(`/DC-Control/v1/business-systems/${id}/notes`, data)
|
||||
|
||||
/** 获取业务文档链接 */
|
||||
export const fetchBusinessDocumentLinks = (id: number) =>
|
||||
request.get<{ code?: number; details?: ListResult<BusinessDocumentLink>; message?: string }>(`/DC-Control/v1/business-systems/${id}/documents`)
|
||||
|
||||
/** 新增业务文档链接 */
|
||||
export const createBusinessDocumentLink = (id: number, data: Partial<BusinessDocumentLink>) =>
|
||||
request.post<{ code?: number; details?: BusinessDocumentLink; message?: string }>(`/DC-Control/v1/business-systems/${id}/documents`, data)
|
||||
@@ -152,22 +152,19 @@ export interface MetricMetaQueryParams {
|
||||
* 获取数据库服务列表
|
||||
* @param params 查询参数
|
||||
*/
|
||||
export const fetchDatabaseList = (params: DatabaseQueryParams) =>
|
||||
request.get<DatabaseListResponse>('/DC-Control/v1/database', { params })
|
||||
export const fetchDatabaseList = (params: DatabaseQueryParams) => request.get<DatabaseListResponse>('/DC-Control/v1/database', { params })
|
||||
|
||||
/**
|
||||
* 获取数据库服务详情
|
||||
* @param id 服务ID
|
||||
*/
|
||||
export const fetchDatabaseDetail = (id: number) =>
|
||||
request.get<DatabaseService>(`/DC-Control/v1/database/${id}`)
|
||||
export const fetchDatabaseDetail = (id: number) => request.get<DatabaseService>(`/DC-Control/v1/database/${id}`)
|
||||
|
||||
/**
|
||||
* 创建数据库服务
|
||||
* @param data 创建参数
|
||||
*/
|
||||
export const createDatabase = (data: CreateDatabaseParams) =>
|
||||
request.post<{ message: string; id: number }>('/DC-Control/v1/database', data)
|
||||
export const createDatabase = (data: CreateDatabaseParams) => request.post<{ message: string; id: number }>('/DC-Control/v1/database', data)
|
||||
|
||||
/**
|
||||
* 更新数据库服务
|
||||
@@ -181,8 +178,7 @@ export const updateDatabase = (id: number, data: UpdateDatabaseParams) =>
|
||||
* 删除数据库服务(软删除)
|
||||
* @param id 服务ID
|
||||
*/
|
||||
export const deleteDatabase = (id: number) =>
|
||||
request.delete<{ message: string }>(`/DC-Control/v1/database/${id}`)
|
||||
export const deleteDatabase = (id: number) => request.delete<{ message: string }>(`/DC-Control/v1/database/${id}`)
|
||||
|
||||
/**
|
||||
* 按服务主键采集指标
|
||||
@@ -196,4 +192,4 @@ export const collectDatabaseMetrics = (data: CollectMetricsParams) =>
|
||||
* @param params 查询参数
|
||||
*/
|
||||
export const fetchMetricMeta = (params: MetricMetaQueryParams) =>
|
||||
request.get<MetricMetaResponse>('/DC-Control/v1/services/metrics/meta', { params })
|
||||
request.get<MetricMetaResponse>('/DC-Control/v1/services/metrics/meta', { params })
|
||||
|
||||
@@ -1,41 +1,46 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 获取所有已启用数据中心(下拉,不分页) */
|
||||
export const fetchDatacenterAll = (params?: { keyword?: string }) => {
|
||||
return request.get("/Assets/v1/datacenter/all", { params });
|
||||
};
|
||||
return request.get('/Assets/v1/datacenter/all', { params })
|
||||
}
|
||||
|
||||
/** 获取数据中心列表(分页) */
|
||||
export const fetchDatacenterList = (data?: {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
keyword?: string;
|
||||
province_id?: number;
|
||||
city_id?: number;
|
||||
status?: string;
|
||||
page?: number
|
||||
page_size?: number
|
||||
keyword?: string
|
||||
province_id?: number
|
||||
city_id?: number
|
||||
status?: string
|
||||
}) => {
|
||||
return request.post("/Assets/v1/datacenter/list", data || {});
|
||||
};
|
||||
return request.post('/Assets/v1/datacenter/list', data || {})
|
||||
}
|
||||
|
||||
/** 获取数据中心详情 */
|
||||
export const fetchDatacenterDetail = (id: number) => {
|
||||
return request.get(`/Assets/v1/datacenter/detail/${id}`);
|
||||
};
|
||||
return request.get(`/Assets/v1/datacenter/detail/${id}`)
|
||||
}
|
||||
|
||||
/** 创建数据中心 */
|
||||
export const createDatacenter = (data: any) => {
|
||||
return request.post("/Assets/v1/datacenter/create", data);
|
||||
};
|
||||
return request.post('/Assets/v1/datacenter/create', data)
|
||||
}
|
||||
|
||||
/** 批量导入数据中心 */
|
||||
export const bulkImportDatacenters = (data: { dry_run?: boolean; items: any[] }) => {
|
||||
return request.post('/Assets/v1/datacenter/bulk_import', data)
|
||||
}
|
||||
|
||||
/** 更新数据中心 */
|
||||
export const updateDatacenter = (data: any) => {
|
||||
return request.put("/Assets/v1/datacenter/update", data);
|
||||
};
|
||||
return request.put('/Assets/v1/datacenter/update', data)
|
||||
}
|
||||
|
||||
/** 删除数据中心 */
|
||||
export const deleteDatacenter = (id: number) => {
|
||||
return request.delete(`/Assets/v1/datacenter/delete/${id}`);
|
||||
};
|
||||
return request.delete(`/Assets/v1/datacenter/delete/${id}`)
|
||||
}
|
||||
|
||||
/** 获取省份列表(用于下拉选择) */
|
||||
export const fetchProvinceList = (params?: { keyword?: string }) => {
|
||||
@@ -49,10 +54,10 @@ export const fetchCityList = (provinceId: number, params?: { keyword?: string })
|
||||
|
||||
/** 根据城市获取数据中心列表 */
|
||||
export const fetchDatacenterByCity = (cityId: number) => {
|
||||
return request.get(`/Assets/v1/datacenter/city/${cityId}`);
|
||||
};
|
||||
return request.get(`/Assets/v1/datacenter/city/${cityId}`)
|
||||
}
|
||||
|
||||
/** 获取数据中心树形结构 */
|
||||
export const fetchDatacenterTree = () => {
|
||||
return request.get("/Assets/v1/datacenter/tree");
|
||||
};
|
||||
return request.get('/Assets/v1/datacenter/tree')
|
||||
}
|
||||
|
||||
@@ -1,42 +1,247 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 许可证配置(与 DC-Control `LicenceConfig` / 接口 `data` 一致;字段按实际响应可能部分缺失) */
|
||||
export interface LicenceConfig {
|
||||
title?: string
|
||||
version?: string
|
||||
company_name?: string
|
||||
create_time?: string
|
||||
expire_time?: string
|
||||
machine_code?: string
|
||||
max_database?: number
|
||||
max_middleware?: number
|
||||
max_pc?: number
|
||||
max_server?: number
|
||||
max_client?: number
|
||||
max_user?: number
|
||||
max_role?: number
|
||||
max_permission?: number
|
||||
max_menu?: number
|
||||
export interface LicenceQuotas {
|
||||
max_database: number
|
||||
max_middleware: number
|
||||
max_network_device: number
|
||||
max_security: number
|
||||
max_storage: number
|
||||
max_pc: number
|
||||
max_server: number
|
||||
max_user: number
|
||||
max_role: number
|
||||
max_permission: number
|
||||
max_menu: number
|
||||
}
|
||||
|
||||
export interface LicenceInfo {
|
||||
id: string
|
||||
platform_name: string
|
||||
workspace: string
|
||||
issued_on: string
|
||||
valid_from: string
|
||||
expires_on: string
|
||||
quotas: LicenceQuotas
|
||||
}
|
||||
|
||||
/** 获取 采集器 */
|
||||
export const fetchCollectors = (data: { page: number, size: number, keyword?: string }) => request.get("/DC-Control/v1/collectors", { params: data });
|
||||
export const fetchCollectors = (data: { page: number; size: number; keyword?: string }) =>
|
||||
request.get('/DC-Control/v1/collectors', { params: data })
|
||||
|
||||
/** 新增 采集器 */
|
||||
export const createCollector = (data: any) => request.post("/DC-Control/v1/collectors", data);
|
||||
export const createCollector = (data: any) => request.post('/DC-Control/v1/collectors', data)
|
||||
|
||||
/** 删除 采集器 */
|
||||
export const deleteCollector = (id: number) => request.delete(`/DC-Control/v1/collectors/${id}`);
|
||||
export const deleteCollector = (id: number) => request.delete(`/DC-Control/v1/collectors/${id}`)
|
||||
|
||||
/** 获取 采集器详情 */
|
||||
export const fetchCollectorDetail = (id: number) => request.get(`/DC-Control/v1/collectors/${id}`);
|
||||
export const fetchCollectorDetail = (id: number) => request.get(`/DC-Control/v1/collectors/${id}`)
|
||||
|
||||
/** 更新 采集器 */
|
||||
export const updateCollector = (data: any) => request.put(`/DC-Control/v1/collectors/${data.id}`, data);
|
||||
export const updateCollector = (data: any) => request.put(`/DC-Control/v1/collectors/${data.id}`, data)
|
||||
|
||||
/** 获取 采集器统计数据 */
|
||||
export const fetchCollectorStatistics = () => request.get("/DC-Control/v1/statistics");
|
||||
export const fetchCollectorStatistics = () => request.get('/DC-Control/v1/statistics')
|
||||
|
||||
/** 获取 许可证信息 */
|
||||
export const fetchLicenseInfo = () =>
|
||||
request.get<{ code?: number; data?: LicenceConfig; message?: string }>("/DC-Control/v1/license");
|
||||
request.get<{ code: number; details: LicenceInfo; message: string; timeseq: number }>('/DC-Control/v1/license')
|
||||
|
||||
export interface PageResult<T> {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: T[]
|
||||
}
|
||||
|
||||
export interface OptionItem {
|
||||
id?: number
|
||||
label: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface ControlResource {
|
||||
id: number
|
||||
resource_uid: string
|
||||
resource_category: string
|
||||
service_identity: string
|
||||
display_name: string
|
||||
description?: string
|
||||
status: string
|
||||
business_system_id?: number
|
||||
owner_user_id?: number
|
||||
department_id?: number
|
||||
asset_id?: number
|
||||
datacenter_id?: number
|
||||
room_id?: number
|
||||
rack_id?: number
|
||||
unit_start?: number
|
||||
unit_end?: number
|
||||
location_ref?: string
|
||||
tags?: string
|
||||
source_service?: string
|
||||
source_table?: string
|
||||
source_id?: number
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface ControlResourcePayload {
|
||||
resource_category?: string
|
||||
service_identity?: string
|
||||
display_name?: string
|
||||
description?: string
|
||||
status?: string
|
||||
business_system_id?: number | null
|
||||
owner_user_id?: number | null
|
||||
department_id?: number | null
|
||||
asset_id?: number | null
|
||||
datacenter_id?: number | null
|
||||
room_id?: number | null
|
||||
rack_id?: number | null
|
||||
unit_start?: number | null
|
||||
unit_end?: number | null
|
||||
location_ref?: string | null
|
||||
tags?: string
|
||||
}
|
||||
|
||||
export interface ControlResourceType {
|
||||
id: number
|
||||
resource_category: string
|
||||
display_name: string
|
||||
metric_template?: string
|
||||
supported_collect_method?: string
|
||||
description?: string
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export interface ControlMetricDefinition {
|
||||
id: number
|
||||
metric_code: string
|
||||
metric_name: string
|
||||
resource_category: string
|
||||
unit?: string
|
||||
threshold_suggestion?: string
|
||||
collect_method?: string
|
||||
description?: string
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export interface ControlMetricSeries {
|
||||
id: number
|
||||
resource_uid: string
|
||||
metric_code: string
|
||||
collection_task_id?: string
|
||||
storage_driver: string
|
||||
database_name?: string
|
||||
table_name?: string
|
||||
series_key?: string
|
||||
retention_policy?: string
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
export interface ControlBusinessSystem {
|
||||
id: number
|
||||
code: string
|
||||
name: string
|
||||
system_type: string
|
||||
owner_user_id?: number
|
||||
department_id?: number
|
||||
description?: string
|
||||
status: string
|
||||
is_builtin: boolean
|
||||
}
|
||||
|
||||
export interface ControlCollectionStatus {
|
||||
id: number
|
||||
resource_uid: string
|
||||
resource_category: string
|
||||
service_identity: string
|
||||
collect_method: string
|
||||
schedule_interval: number
|
||||
retry_policy?: string
|
||||
last_status: string
|
||||
last_error?: string
|
||||
last_sample_time?: string
|
||||
trace_id?: string
|
||||
source_service?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface ResourceListParams {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
resource_category?: string
|
||||
business_system_id?: number
|
||||
}
|
||||
|
||||
export interface MetricSeriesListParams {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
resource_uid?: string
|
||||
}
|
||||
|
||||
export const fetchControlResources = (params?: ResourceListParams) =>
|
||||
request.get<{ code?: number; details?: PageResult<ControlResource>; message?: string }>('/DC-Control/v1/resources', { params })
|
||||
|
||||
export const fetchControlResourceOptions = (params?: { resource_category?: string }) =>
|
||||
request.get<{ code?: number; details?: { list: OptionItem[]; count: number }; message?: string }>('/DC-Control/v1/resources/options', {
|
||||
params,
|
||||
})
|
||||
|
||||
export const createControlResource = (data: ControlResourcePayload) =>
|
||||
request.post<{ code?: number; details?: ControlResource; message?: string }>('/DC-Control/v1/resources', data)
|
||||
|
||||
export const updateControlResource = (id: number, data: ControlResourcePayload) =>
|
||||
request.put<{ code?: number; details?: ControlResource; message?: string }>(`/DC-Control/v1/resources/${id}`, data)
|
||||
|
||||
export const deleteControlResource = (id: number) =>
|
||||
request.delete<{ code?: number; details?: { message: string }; message?: string }>(`/DC-Control/v1/resources/${id}`)
|
||||
|
||||
export const backfillControlResources = () =>
|
||||
request.post<{ code?: number; details?: { message: string }; message?: string }>('/DC-Control/v1/resources/backfill')
|
||||
|
||||
export const fetchControlResourceTypes = (params?: { page?: number; size?: number; keyword?: string }) =>
|
||||
request.get<{ code?: number; details?: PageResult<ControlResourceType>; message?: string }>('/DC-Control/v1/resource-types', { params })
|
||||
|
||||
export const fetchControlResourceTypeOptions = () =>
|
||||
request.get<{ code?: number; details?: { list: OptionItem[]; count: number }; message?: string }>('/DC-Control/v1/resource-types/options')
|
||||
|
||||
export const fetchControlMetricDefinitions = (params?: { page?: number; size?: number; keyword?: string; resource_category?: string }) =>
|
||||
request.get<{ code?: number; details?: PageResult<ControlMetricDefinition>; message?: string }>('/DC-Control/v1/metric-definitions', {
|
||||
params,
|
||||
})
|
||||
|
||||
export const fetchControlMetricDefinitionOptions = (params?: { resource_category?: string }) =>
|
||||
request.get<{ code?: number; details?: { list: OptionItem[]; count: number }; message?: string }>(
|
||||
'/DC-Control/v1/metric-definitions/options',
|
||||
{ params }
|
||||
)
|
||||
|
||||
export const fetchControlMetricSeries = (params?: MetricSeriesListParams) =>
|
||||
request.get<{ code?: number; details?: PageResult<ControlMetricSeries>; message?: string }>('/DC-Control/v1/metric-series', { params })
|
||||
|
||||
export const fetchControlBusinessSystems = (params?: { page?: number; size?: number; keyword?: string; status?: string }) =>
|
||||
request.get<{ code?: number; details?: PageResult<ControlBusinessSystem>; message?: string }>('/DC-Control/v1/business-systems', {
|
||||
params,
|
||||
})
|
||||
|
||||
export const fetchControlBusinessSystemOptions = () =>
|
||||
request.get<{ code?: number; details?: { list: OptionItem[]; count: number }; message?: string }>(
|
||||
'/DC-Control/v1/business-systems/options'
|
||||
)
|
||||
|
||||
export const fetchCollectionStatus = (params?: {
|
||||
page?: number
|
||||
size?: number
|
||||
keyword?: string
|
||||
resource_category?: string
|
||||
resource_uid?: string
|
||||
status?: string
|
||||
}) =>
|
||||
request.get<{ code?: number; details?: PageResult<ControlCollectionStatus>; message?: string }>('/DC-Control/v1/collection/status', {
|
||||
params,
|
||||
})
|
||||
|
||||
@@ -1,91 +1,89 @@
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 与后端 discovery/summary 对齐 */
|
||||
export interface DiscoverySummary {
|
||||
device_total_current: number
|
||||
online_current: number
|
||||
offline_current: number
|
||||
other_status_current: number
|
||||
primary_scan_ids: number[]
|
||||
last_run?: DiscoveryScanRun | null
|
||||
}
|
||||
|
||||
export interface DiscoveryScanRun {
|
||||
id: number
|
||||
scan_id: number
|
||||
run_type: string
|
||||
status: string
|
||||
started_at: string
|
||||
finished_at?: string | null
|
||||
device_total: number
|
||||
online_count: number
|
||||
offline_count: number
|
||||
new_count: number
|
||||
error_message?: string
|
||||
trigger_by: string
|
||||
}
|
||||
|
||||
export interface DiscoveryDeviceRow {
|
||||
id: number
|
||||
ip_address: string
|
||||
scan_id?: number
|
||||
run_id?: number
|
||||
status: string
|
||||
mac_address?: string
|
||||
hostname?: string
|
||||
device_type?: string
|
||||
manufacturer?: string
|
||||
discovery_methods?: string
|
||||
last_seen_time?: string
|
||||
last_scan_time?: string
|
||||
first_seen_time?: string
|
||||
}
|
||||
|
||||
export interface DiscoveryDevicesResponse {
|
||||
scope: string
|
||||
scan_id?: number
|
||||
primary_scan_ids?: number[]
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: DiscoveryDeviceRow[]
|
||||
}
|
||||
|
||||
export interface DiscoveryScanRunsResponse {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: DiscoveryScanRun[]
|
||||
}
|
||||
|
||||
export interface DiscoveryConfig {
|
||||
id: number
|
||||
primary_scan_ids: number[]
|
||||
primary_scan_ids_raw?: string
|
||||
}
|
||||
|
||||
export const fetchDiscoverySummary = () =>
|
||||
request.get<{ code: number; details?: DiscoverySummary }>('/DC-Control/v1/discovery/summary')
|
||||
|
||||
export const fetchDiscoveryDevices = (params?: {
|
||||
scope?: 'current' | 'raw'
|
||||
scan_id?: number
|
||||
page?: number
|
||||
size?: number
|
||||
status?: string
|
||||
keyword?: string
|
||||
}) =>
|
||||
request.get<{ code: number; details?: DiscoveryDevicesResponse }>('/DC-Control/v1/discovery/devices', {
|
||||
params,
|
||||
})
|
||||
|
||||
export const fetchDiscoveryScanRuns = (params?: { scan_id?: number; page?: number; size?: number }) =>
|
||||
request.get<{ code: number; details?: DiscoveryScanRunsResponse }>('/DC-Control/v1/discovery/scan-runs', {
|
||||
params,
|
||||
})
|
||||
|
||||
export const fetchDiscoveryConfig = () =>
|
||||
request.get<{ code: number; details?: DiscoveryConfig }>('/DC-Control/v1/discovery/config')
|
||||
|
||||
export const updateDiscoveryConfig = (data: { primary_scan_ids: number[] }) =>
|
||||
request.put<{ code: number; details?: DiscoveryConfig }>('/DC-Control/v1/discovery/config', data)
|
||||
import { request } from '@/api/request'
|
||||
|
||||
/** 与后端 discovery/summary 对齐 */
|
||||
export interface DiscoverySummary {
|
||||
device_total_current: number
|
||||
online_current: number
|
||||
offline_current: number
|
||||
other_status_current: number
|
||||
primary_scan_ids: number[]
|
||||
last_run?: DiscoveryScanRun | null
|
||||
}
|
||||
|
||||
export interface DiscoveryScanRun {
|
||||
id: number
|
||||
scan_id: number
|
||||
run_type: string
|
||||
status: string
|
||||
started_at: string
|
||||
finished_at?: string | null
|
||||
device_total: number
|
||||
online_count: number
|
||||
offline_count: number
|
||||
new_count: number
|
||||
error_message?: string
|
||||
trigger_by: string
|
||||
}
|
||||
|
||||
export interface DiscoveryDeviceRow {
|
||||
id: number
|
||||
ip_address: string
|
||||
scan_id?: number
|
||||
run_id?: number
|
||||
status: string
|
||||
mac_address?: string
|
||||
hostname?: string
|
||||
device_type?: string
|
||||
manufacturer?: string
|
||||
discovery_methods?: string
|
||||
last_seen_time?: string
|
||||
last_scan_time?: string
|
||||
first_seen_time?: string
|
||||
}
|
||||
|
||||
export interface DiscoveryDevicesResponse {
|
||||
scope: string
|
||||
scan_id?: number
|
||||
primary_scan_ids?: number[]
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: DiscoveryDeviceRow[]
|
||||
}
|
||||
|
||||
export interface DiscoveryScanRunsResponse {
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
data: DiscoveryScanRun[]
|
||||
}
|
||||
|
||||
export interface DiscoveryConfig {
|
||||
id: number
|
||||
primary_scan_ids: number[]
|
||||
primary_scan_ids_raw?: string
|
||||
}
|
||||
|
||||
export const fetchDiscoverySummary = () => request.get<{ code: number; details?: DiscoverySummary }>('/DC-Control/v1/discovery/summary')
|
||||
|
||||
export const fetchDiscoveryDevices = (params?: {
|
||||
scope?: 'current' | 'raw'
|
||||
scan_id?: number
|
||||
page?: number
|
||||
size?: number
|
||||
status?: string
|
||||
keyword?: string
|
||||
}) =>
|
||||
request.get<{ code: number; details?: DiscoveryDevicesResponse }>('/DC-Control/v1/discovery/devices', {
|
||||
params,
|
||||
})
|
||||
|
||||
export const fetchDiscoveryScanRuns = (params?: { scan_id?: number; page?: number; size?: number }) =>
|
||||
request.get<{ code: number; details?: DiscoveryScanRunsResponse }>('/DC-Control/v1/discovery/scan-runs', {
|
||||
params,
|
||||
})
|
||||
|
||||
export const fetchDiscoveryConfig = () => request.get<{ code: number; details?: DiscoveryConfig }>('/DC-Control/v1/discovery/config')
|
||||
|
||||
export const updateDiscoveryConfig = (data: { primary_scan_ids: number[] }) =>
|
||||
request.put<{ code: number; details?: DiscoveryConfig }>('/DC-Control/v1/discovery/config', data)
|
||||
|
||||
@@ -15,7 +15,12 @@ function normalizeTicketListStatusParam(params: Record<string, any>) {
|
||||
delete params.status
|
||||
return
|
||||
}
|
||||
arr = s.includes(',') ? s.split(',').map((x) => x.trim()).filter(Boolean) : [s]
|
||||
arr = s.includes(',')
|
||||
? s
|
||||
.split(',')
|
||||
.map((x) => x.trim())
|
||||
.filter(Boolean)
|
||||
: [s]
|
||||
}
|
||||
if (arr.length === 0) delete params.status
|
||||
else params.status = arr
|
||||
@@ -62,6 +67,9 @@ export const fetchFeedbackTickets = (data?: {
|
||||
creator_id?: number
|
||||
assignee_id?: number
|
||||
category_id?: number
|
||||
incident_id?: number
|
||||
resource_uid?: string
|
||||
business_system_id?: number
|
||||
keyword?: string
|
||||
/** 格式 YYYY-MM-DD HH:MM:SS */
|
||||
start_time?: string
|
||||
@@ -88,55 +96,60 @@ export const fetchFeedbackTickets = (data?: {
|
||||
}
|
||||
|
||||
/** 创建 工单 */
|
||||
export const createFeedbackTicket = (data: any) => request.post("/Feedback/v1/tickets", data);
|
||||
export const createFeedbackTicket = (data: any) => request.post('/Feedback/v1/tickets', data)
|
||||
|
||||
/** 更新 工单 */
|
||||
export const updateFeedbackTicket = (id: number, data: any) => request.put(`/Feedback/v1/tickets/${id}`, data);
|
||||
export const updateFeedbackTicket = (id: number, data: any) => request.put(`/Feedback/v1/tickets/${id}`, data)
|
||||
|
||||
/** 删除 工单 */
|
||||
export const deleteFeedbackTicket = (id: number) => request.delete(`/Feedback/v1/tickets/${id}`);
|
||||
export const deleteFeedbackTicket = (id: number) => request.delete(`/Feedback/v1/tickets/${id}`)
|
||||
|
||||
/** 获取 工单详情 */
|
||||
export const fetchFeedbackTicketDetail = (id: number) => request.get(`/Feedback/v1/tickets/${id}`);
|
||||
export const fetchFeedbackTicketDetail = (id: number) => request.get(`/Feedback/v1/tickets/${id}`)
|
||||
|
||||
/** 根据工单编号获取详情 */
|
||||
export const fetchFeedbackTicketByNo = (no: string) => request.get(`/Feedback/v1/tickets/no/${no}`);
|
||||
export const fetchFeedbackTicketByNo = (no: string) => request.get(`/Feedback/v1/tickets/no/${no}`)
|
||||
|
||||
/** 接单 */
|
||||
export const acceptFeedbackTicket = (id: number) => request.post(`/Feedback/v1/tickets/${id}/accept`);
|
||||
export const acceptFeedbackTicket = (id: number) => request.post(`/Feedback/v1/tickets/${id}/accept`)
|
||||
|
||||
/** 转交 */
|
||||
export const transferFeedbackTicket = (id: number, data: { assignee_id: number, assignee_name: string, reason?: string }) => request.post(`/Feedback/v1/tickets/${id}/transfer`, data);
|
||||
export const transferFeedbackTicket = (id: number, data: { assignee_id: number; assignee_name: string; reason?: string }) =>
|
||||
request.post(`/Feedback/v1/tickets/${id}/transfer`, data)
|
||||
|
||||
/** 撤回 */
|
||||
export const cancelFeedbackTicket = (id: number) => request.post(`/Feedback/v1/tickets/${id}/cancel`);
|
||||
export const cancelFeedbackTicket = (id: number) => request.post(`/Feedback/v1/tickets/${id}/cancel`)
|
||||
|
||||
/** 挂起 */
|
||||
export const suspendFeedbackTicket = (id: number, data: { content: string }) => request.post(`/Feedback/v1/tickets/${id}/suspend`, data);
|
||||
export const suspendFeedbackTicket = (id: number, data: { content: string }) => request.post(`/Feedback/v1/tickets/${id}/suspend`, data)
|
||||
|
||||
/** 重启 */
|
||||
export const resumeFeedbackTicket = (id: number) => request.post(`/Feedback/v1/tickets/${id}/resume`);
|
||||
export const resumeFeedbackTicket = (id: number) => request.post(`/Feedback/v1/tickets/${id}/resume`)
|
||||
|
||||
/** 解决 */
|
||||
export const resolveFeedbackTicket = (id: number, data: { content: string }) => request.post(`/Feedback/v1/tickets/${id}/resolve`, data);
|
||||
export const resolveFeedbackTicket = (id: number, data: { content: string }) => request.post(`/Feedback/v1/tickets/${id}/resolve`, data)
|
||||
|
||||
/** 关闭 */
|
||||
export const closeFeedbackTicket = (id: number, data: { remarks?: string }) => request.post(`/Feedback/v1/tickets/${id}/close`, data);
|
||||
export const closeFeedbackTicket = (id: number, data: { remarks?: string }) => request.post(`/Feedback/v1/tickets/${id}/close`, data)
|
||||
|
||||
/** 添加评论 */
|
||||
export const commentFeedbackTicket = (id: number, data: { content: string }) => request.post(`/Feedback/v1/tickets/${id}/comment`, data);
|
||||
export const commentFeedbackTicket = (id: number, data: { content: string }) => request.post(`/Feedback/v1/tickets/${id}/comment`, data)
|
||||
|
||||
/** 获取操作日志 */
|
||||
export const fetchFeedbackTicketLogs = (id: number) => request.get(`/Feedback/v1/tickets/${id}/logs`);
|
||||
export const fetchFeedbackTicketLogs = (id: number) => request.get(`/Feedback/v1/tickets/${id}/logs`)
|
||||
|
||||
/** 获取关联关系 */
|
||||
export const fetchFeedbackTicketRelations = (id: number) => request.get(`/Feedback/v1/tickets/${id}/relations`);
|
||||
export const fetchFeedbackTicketRelations = (id: number) => request.get(`/Feedback/v1/tickets/${id}/relations`)
|
||||
|
||||
/** 创建关联 */
|
||||
export const createFeedbackTicketRelation = (id: number, data: { target_ticket_id: number, relation_type: string, description?: string }) => request.post(`/Feedback/v1/tickets/${id}/relations`, data);
|
||||
export const createFeedbackTicketRelation = (id: number, data: { target_ticket_id: number; relation_type: string; description?: string }) =>
|
||||
request.post(`/Feedback/v1/tickets/${id}/relations`, data)
|
||||
|
||||
/** 删除关联 */
|
||||
export const deleteFeedbackTicketRelation = (relationId: number) => request.delete(`/Feedback/v1/tickets/relations/${relationId}`);
|
||||
export const deleteFeedbackTicketRelation = (relationId: number) => request.delete(`/Feedback/v1/tickets/relations/${relationId}`)
|
||||
|
||||
/** 获取 工单统计数据 */
|
||||
export const fetchFeedbackTicketStatistics = () => request.get("/Feedback/v1/tickets/statistics");
|
||||
export const fetchFeedbackTicketStatistics = () => request.get('/Feedback/v1/tickets/statistics')
|
||||
|
||||
/** 获取 工单 SLA/SLO 统计数据 */
|
||||
export const fetchFeedbackTicketSLAStatistics = () => request.get('/Feedback/v1/tickets/sla/statistics')
|
||||
|
||||
@@ -1,48 +1,60 @@
|
||||
import { request } from "@/api/request";
|
||||
import { request } from '@/api/request'
|
||||
|
||||
export interface Floor {
|
||||
id?: number
|
||||
name?: string
|
||||
code?: string
|
||||
datacenter_id?: number
|
||||
floor_number?: number
|
||||
status?: string
|
||||
area?: number
|
||||
height?: number
|
||||
load_bearing?: number
|
||||
enabled?: boolean
|
||||
layout_plan?: string
|
||||
layout_plan_file_id?: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export type SaveFloorPayload = Omit<Floor, 'layout_plan'>
|
||||
|
||||
interface ApiResponse<T> {
|
||||
code: number
|
||||
message: string
|
||||
details: T
|
||||
}
|
||||
|
||||
/** 获取楼层列表(分页) */
|
||||
export const fetchFloorList = (data?: {
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
keyword?: string;
|
||||
datacenter_id?: number;
|
||||
status?: string;
|
||||
}) => {
|
||||
return request.post("/Assets/v1/floor/list", data || {});
|
||||
};
|
||||
export const fetchFloorList = (data?: { page?: number; page_size?: number; keyword?: string; datacenter_id?: number; status?: string }) => {
|
||||
return request.post('/Assets/v1/floor/list', data || {})
|
||||
}
|
||||
|
||||
/** 获取楼层详情 */
|
||||
export const fetchFloorDetail = (id: number) => {
|
||||
return request.get(`/Assets/v1/floor/detail/${id}`);
|
||||
};
|
||||
return request.get(`/Assets/v1/floor/detail/${id}`)
|
||||
}
|
||||
|
||||
/** 根据数据中心获取楼层列表(下拉,不分页) */
|
||||
export const fetchFloorListByDatacenter = (
|
||||
datacenterId: number,
|
||||
params?: { name?: string }
|
||||
) => {
|
||||
return request.get(`/Assets/v1/floor/datacenter/${datacenterId}`, { params });
|
||||
};
|
||||
export const fetchFloorListByDatacenter = (datacenterId: number, params?: { name?: string }) => {
|
||||
return request.get(`/Assets/v1/floor/datacenter/${datacenterId}`, { params })
|
||||
}
|
||||
|
||||
/** 创建楼层 */
|
||||
export const createFloor = (data: any) => {
|
||||
return request.post("/Assets/v1/floor/create", data);
|
||||
};
|
||||
export const createFloor = (data: SaveFloorPayload) => {
|
||||
return request.post<ApiResponse<Floor>>('/Assets/v1/floor/create', data)
|
||||
}
|
||||
|
||||
/** 更新楼层 */
|
||||
export const updateFloor = (data: any) => {
|
||||
return request.put("/Assets/v1/floor/update", data);
|
||||
};
|
||||
export const updateFloor = (data: SaveFloorPayload) => {
|
||||
return request.put<ApiResponse<Floor>>('/Assets/v1/floor/update', data)
|
||||
}
|
||||
|
||||
/** 删除楼层 */
|
||||
export const deleteFloor = (id: number) => {
|
||||
return request.delete(`/Assets/v1/floor/delete/${id}`);
|
||||
};
|
||||
return request.delete(`/Assets/v1/floor/delete/${id}`)
|
||||
}
|
||||
|
||||
/** 获取数据中心列表(用于下拉选择) */
|
||||
export const fetchDatacenterList = (params?: { keyword?: string; name?: string }) => {
|
||||
const normalizedParams = params?.keyword
|
||||
? { ...params, name: params.name ?? params.keyword }
|
||||
: params
|
||||
return request.get("/Assets/v1/datacenter/all", { params: normalizedParams });
|
||||
};
|
||||
export const fetchDatacenterList = (params?: { keyword?: string }) => {
|
||||
return request.get('/Assets/v1/datacenter/all', { params })
|
||||
}
|
||||
|
||||