Compare commits

..

No commits in common. "master" and "v2025.12" have entirely different histories.

5276 changed files with 27377 additions and 609423 deletions

View File

@ -1,3 +0,0 @@
{
"singleQuote": true
}

View File

@ -1,7 +0,0 @@
---
'@vben/styles': patch
'@vben-core/form-ui': patch
'@vben/web-naive': patch
---
feat(@core/form-ui): 新增 useVbenForm 数组编辑器 VbenFormFieldArray

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

View File

@ -6,10 +6,10 @@ runs:
using: 'composite'
steps:
- name: Install pnpm
uses: pnpm/action-setup@v6
uses: pnpm/action-setup@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: 'pnpm'

View File

@ -30,7 +30,7 @@ jobs:
- windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0

View File

@ -25,7 +25,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0

View File

@ -28,12 +28,12 @@ jobs:
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v6
uses: pnpm/action-setup@v4
with:
run_install: false
@ -67,7 +67,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -90,7 +90,7 @@ jobs:
- windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0

View File

@ -57,11 +57,11 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@ -89,6 +89,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v3
with:
category: '/language:${{matrix.language}}'

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -30,7 +30,7 @@ jobs:
run: pnpm build:play
- name: Sync Playground files
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }}
@ -43,7 +43,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -54,7 +54,7 @@ jobs:
run: pnpm build:docs
- name: Sync Docs files
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }}
@ -67,7 +67,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -85,7 +85,7 @@ jobs:
run: pnpm run build:antd
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }}
@ -98,7 +98,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -116,7 +116,7 @@ jobs:
run: pnpm run build:ele
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }}
@ -129,7 +129,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
@ -147,7 +147,7 @@ jobs:
run: pnpm run build:naive
- name: Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
with:
server: ${{ secrets.PRO_FTP_HOST }}
username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }}

View File

@ -20,6 +20,6 @@ jobs:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v7
- uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -19,7 +19,7 @@ jobs:
steps:
# 关闭未活动的 Issues
- name: Close Inactive Issues
uses: actions/stale@v10
uses: actions/stale@v9
with:
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
stale-issue-label: needs-reproduction # Label that flags an issue as stale.

View File

@ -18,7 +18,7 @@ jobs:
steps:
- name: remove enhancement pending
if: github.event.label.name == 'enhancement'
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
token: ${{ secrets.GITHUB_TOKEN }}
@ -27,7 +27,7 @@ jobs:
- name: remove bug pending
if: github.event.label.name == 'bug'
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
token: ${{ secrets.GITHUB_TOKEN }}
@ -36,7 +36,7 @@ jobs:
- name: needs reproduction
if: github.event.label.name == 'needs reproduction'
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
uses: actions-cool/issues-helper@v3
with:
actions: 'create-comment, remove-labels'
token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -14,7 +14,7 @@ jobs:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v6
- uses: dessant/lock-threads@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: '14'

View File

@ -3,48 +3,78 @@ name: Create Release Tag
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to create (e.g. v1.2.3)'
required: true
type: string
- 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10
env:
HUSKY: '0'
permissions:
pull-requests: write
contents: write
jobs:
release:
build:
name: Create Release
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20]
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Extract version
# - name: Checkout code
# uses: actions/checkout@v4
# with:
# fetch-depth: 0
# - name: Install pnpm
# uses: pnpm/action-setup@v4
# - name: Use Node.js ${{ matrix.node-version }}
# uses: actions/setup-node@v4
# with:
# node-version: ${{ matrix.node-version }}
# cache: "pnpm"
# - name: Install dependencies
# run: pnpm install --frozen-lockfile
# - name: Test and Build
# run: |
# pnpm run test
# pnpm run build
- name: version
id: version
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
raw_tag="${{ inputs.tag }}"
else
raw_tag="${GITHUB_REF_NAME}"
fi
# Normalize: ensure v prefix
tag="${raw_tag}"
[[ "${tag:0:1}" != "v" ]] && tag="v${tag}"
version="${tag#v}"
major="${version%%.*}"
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"
echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "major=${major}" >> "${GITHUB_OUTPUT}"
tag=${GITHUB_REF/refs\/tags\//}
version=${tag#v}
major=${version%%.*}
echo "tag=${tag}" >> $GITHUB_OUTPUT
echo "version=${version}" >> $GITHUB_OUTPUT
echo "major=${major}" >> $GITHUB_OUTPUT
- uses: release-drafter/release-drafter@v7
- uses: release-drafter/release-drafter@v6
with:
version: ${{ steps.version.outputs.version }}
publish: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# - name: force update major tag
# run: |
# git tag v${{ steps.version.outputs.major }} ${{ steps.version.outputs.tag }} -f
# git push origin refs/tags/v${{ steps.version.outputs.major }} -f
# - name: Create Release for Tag
# id: release_tag
# uses: ncipollo/release-action@v1
# with:
# token: ${{ secrets.GITHUB_TOKEN }}
# generateReleaseNotes: "true"
# body: |
# > Please refer to [CHANGELOG.md](https://github.com/vbenjs/vue-vben-admin/blob/main/CHANGELOG.md) for details.

View File

@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v6
uses: amannn/action-semantic-pull-request@v5
with:
wip: true
subjectPattern: ^(?![A-Z]).+$

View File

@ -9,7 +9,7 @@ jobs:
if: github.repository == 'vbenjs/vue-vben-admin'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'

15
.gitignore vendored
View File

@ -22,8 +22,7 @@ yarn.lock
package-lock.json
.VSCodeCounter
**/backend-mock/data
.omx
.pnpm-store
# local env files
.env.local
.env.*.local
@ -51,15 +50,3 @@ vite.config.ts.*
*.sw?
.history
.cursor
# AI
.agent
.agents
.claude
.codex
skills-lock.json
.atomcode
datalog
# Playwright CLI 录制产物(本地调试,不入库)
.playwright-cli

View File

@ -1 +1 @@
24.16.0
22.1.0

12
.npmrc
View File

@ -1 +1,13 @@
registry=https://registry.npmmirror.com
public-hoist-pattern[]=lefthook
public-hoist-pattern[]=eslint
public-hoist-pattern[]=prettier
public-hoist-pattern[]=prettier-plugin-tailwindcss
public-hoist-pattern[]=stylelint
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=@commitlint/*
public-hoist-pattern[]=czg
strict-peer-dependencies=false
auto-install-peers=true
dedupe-peer-dependents=true

18
.prettierignore Normal file
View File

@ -0,0 +1,18 @@
dist
dev-dist
.local
.output.js
node_modules
.nvmrc
coverage
CODEOWNERS
.nitro
.output
**/*.svg
**/*.sh
public
.npmrc
*-lock.yaml

1
.prettierrc.mjs Normal file
View File

@ -0,0 +1 @@
export { default } from '@vben/prettier-config';

View File

@ -2,7 +2,3 @@ dist
public
__tests__
coverage
.codex
.claude
.agent
.agents

View File

@ -2,18 +2,14 @@
"recommendations": [
// Vue 3
"Vue.volar",
// eslint VS Code
// ESLint JavaScript VS Code
"dbaeumer.vscode-eslint",
// oxlint VS Code
"oxc.oxc-vscode",
// Visual Studio Code Stylelint
"stylelint.vscode-stylelint",
// 使 oxfmt
"oxc.oxc-vscode",
// 使 Prettier
"esbenp.prettier-vscode",
// dotenv
"mikestead.dotenv",
// YAML ESLint pnpm-workspace.yaml
"redhat.vscode-yaml",
//
"streetsidesoftware.code-spell-checker",
// Tailwind CSS VS Code

9
.vscode/launch.json vendored
View File

@ -2,15 +2,6 @@
"$schema": "https://json.schemastore.org/launchsettings.json",
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"name": "vben admin antd dev",
"request": "launch",
"url": "http://localhost:5999",
"env": { "NODE_ENV": "development" },
"sourceMaps": true,
"webRoot": "${workspaceFolder}/apps/web-antdv-next"
},
{
"type": "chrome",
"name": "vben admin antd dev",

59
.vscode/settings.json vendored
View File

@ -1,6 +1,5 @@
{
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/theme.css",
"tailwindCSS.lint.suggestCanonicalClasses": "ignore",
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts",
// workbench
"workbench.list.smoothScrolling": true,
"workbench.startupEditor": "newUntitledFile",
@ -32,51 +31,39 @@
"editor.autoClosingOvertype": "always",
"editor.autoClosingQuotes": "beforeWhitespace",
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
"editor.quickSuggestions": {
"strings": "on"
},
// lint && format
"oxc.enable": true,
"oxc.typeAware": false,
"oxc.configPath": "oxlint.config.ts",
"oxc.fmt.configPath": "oxfmt.config.ts",
"eslint.useFlatConfig": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.oxc": "explicit",
"source.fixAll.stylelint": "explicit",
"source.organizeImports": "never"
},
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[html]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// extensions
"extensions.ignoreRecommendations": true,
@ -92,7 +79,6 @@
"files.insertFinalNewline": true,
"files.simpleDialog.enable": true,
"files.associations": {
"*.css": "tailwindcss",
"*.ejs": "html",
"*.art": "html",
"**/tsconfig.json": "jsonc",
@ -132,7 +118,7 @@
// search
"search.searchEditor.singleClickBehaviour": "peekDefinition",
"search.followSymlinks": false,
// 使
// 使/
"search.exclude": {
"**/node_modules": true,
"**/*.log": true,
@ -173,7 +159,7 @@
"emmet.triggerExpansionOnTab": false,
"errorLens.enabledDiagnosticLevels": ["warning", "error"],
"errorLens.excludeBySource": ["cSpell", "Grammarly"],
"errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"],
"stylelint.enable": true,
"stylelint.packageManager": "pnpm",
@ -181,10 +167,9 @@
"stylelint.customSyntax": "postcss-html",
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
"js/ts.tsdk.path": "node_modules/typescript/lib",
"js/ts.inlayHints.enumMemberValues.enabled": true,
"js/ts.preferences.preferTypeOnlyAutoImports": true,
"js/ts.preferences.includePackageJsonAutoImports": "on",
"typescript.inlayHints.enumMemberValues.enabled": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"typescript.preferences.includePackageJsonAutoImports": "on",
"eslint.validate": [
"javascript",
@ -196,8 +181,7 @@
"markdown",
"json",
"jsonc",
"json5",
"yaml"
"json5"
],
"tailwindCSS.experimental.classRegex": [
@ -208,7 +192,7 @@
"*": false
},
"cssVariables.lookupFiles": ["packages/@core/base/design/src/**/*.css"],
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"],
"i18n-ally.localesPaths": [
"packages/locales/src/langs",
@ -233,9 +217,12 @@
"*.env": "$(capture).env.*",
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
"oxlint.config.ts": ".eslintignore,.stylelintignore,.commitlintrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml,oxfmt.config.*,eslint.config.*"
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml",
"tailwind.config.mjs": "postcss.*"
},
"commentTranslate.hover.enabled": false,
"commentTranslate.multiLineMerge": true,
"vue.server.hybridMode": true
"vue.server.hybridMode": true,
"typescript.tsdk": "node_modules/typescript/lib",
"oxc.enable": false
}

252
README.md
View File

@ -9,7 +9,7 @@
## 🐶 新手必读
- nodejs >= v22.18.0推荐v24 && pnpm >= 11.0.0(强制使用 pnpm
- nodejs > 20.12.0 && pnpm > 10.22.0 (强制使用pnpm)
- 演示地址【Vue3 + element-plus】<http://dashboard-vue3.yudao.iocoder.cn>
- 演示地址【Vue3 + vben5(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
- 演示地址【Vue2 + element-ui】<http://dashboard.yudao.iocoder.cn>
@ -20,12 +20,12 @@
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
- 采用最新 [vue-vben-admin](https://github.com/vbenjs/vue-vben-admin) v5.7.0 实现
- 采用最新 [vue-vben-admin](https://github.com/vbenjs/vue-vben-admin) v5 实现
- 支持 [Ant Design Vue](https://www.antdv.com/) | [Element Plus](https://element-plus.org/zh-CN/) | [Naive UI](https://www.naiveui.com/) | [TDesign](https://tdesign.tencent.com/) 多种免费开源的中后台模版,具备如下特性:
![首页](.gitee/image/demo/vben.png)
- **最新技术栈**:使用 Vue3、Vite8 等前端前沿技术开发
- **最新技术栈**:使用 Vue3、Vite6 等前端前沿技术开发
- **TypeScript**: 应用程序级 JavaScript 的语言
- **主题**: 提供多套主题色彩,可配置自定义主题
- **国际化**:内置完善的国际化方案
@ -33,7 +33,7 @@
- **组件**:二次封装了多个常用的组件
- **示例**:内置丰富的示例
## [外包项目请联系【非项目需求请勿扫码,非客服,不解答项目问题】](https://www.shuduokeji.com?yudao)
## [外包项目请联系【非项目需求请勿扫码,非客服,不解答项目问题】](https://www.shuduokeji.com)
![alt 软件定制开发 数舵科技](.gitee/image/wx-xingyu.png)
@ -41,26 +41,26 @@
| 框架 | 说明 | 版本 |
| --- | --- | --- |
| [Vue](https://staging-cn.vuejs.org/) | vue框架 | 3.5.35 |
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 8.0.10 |
| [Vue](https://staging-cn.vuejs.org/) | vue框架 | 3.5.24 |
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 7.2.2 |
| [Ant Design Vue](https://www.antdv.com/) | Ant Design Vue | 4.2.6 |
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.14.1 |
| [Naive UI](https://www.naiveui.com/) | Naive UI | 2.44.1 |
| [TDesign](https://tdesign.tencent.com/) | TDesign | 1.20.0 |
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 超集 | 6.0.3 |
| [pinia](https://pinia.vuejs.org/) | Vue 存储库替代 vuex5 | 3.0.4 |
| [vueuse](https://vueuse.org/) | 常用工具集 | 14.3.0 |
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 11.4.4 |
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 5.1.0 |
| [Tailwind CSS](https://tailwindcss.com/) | 原子 CSS | 4.3.0 |
| [Iconify](https://iconify.design/) | 图标组件 | 5.0.1 |
| [Iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.481 |
| [TinyMCE](https://www.tiny.cloud/) | 富文本编辑器 | 7.3.0 |
| [Echarts](https://echarts.apache.org/) | 图表库 | 6.1.0 |
| [axios](https://axios-http.com/) | http客户端 | 1.16.1 |
| [dayjs](https://day.js.org/) | 日期处理库 | 1.11.21 |
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.10.2 |
| [Naive UI](https://www.naiveui.com/) | Naive UI | 2.42.0 |
| [TDesign](https://tdesign.tencent.com/) | TDesign | 1.17.1 |
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 超集 | 5.9.3 |
| [pinia](https://pinia.vuejs.org/) | Vue 存储库替代 vuex5 | 3.0.3 |
| [vueuse](https://vueuse.org/) | 常用工具集 | 13.4.0 |
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 11.1.7 |
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.5.1 |
| [Tailwind CSS](https://tailwindcss.com/) | 原子 CSS | 3.4.18 |
| [Iconify](https://iconify.design/) | 图标组件 | 5.0.0 |
| [Iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.406 |
| [TinyMCE](https://www.tiny.cloud/) | 富文本编辑器 | 6.1.0 |
| [Echarts](https://echarts.apache.org/) | 图表库 | 6.0.0 |
| [axios](https://axios-http.com/) | http客户端 | 1.10.0 |
| [dayjs](https://day.js.org/) | 日期处理库 | 1.11.13 |
| [vee-validate](https://vee-validate.logaretm.com/) | 表单验证 | 4.15.1 |
| [zod](https://zod.dev/) | 数据验证 | 3.25.76 |
| [zod](https://zod.dev/) | 数据验证 | 3.25.67 |
## 🔥 后端架构
@ -84,31 +84,31 @@
- 通用模块(必选):系统功能、基础设施
- 通用模块(可选):工作流程、支付系统、数据报表、会员中心
- 业务系统(按需):Mall 电子商城、OA 办公自动化、ERP 企业资源计划系统、WMS 仓库管理系统、CRM 客户关系管理、CMS 内容管理系统、MES 执行制造系统、AI 大模型平台、IoT 物联网系统、IM 即时通讯系统、Mobile 手机移动端、Report 数据大屏
- 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号、AI 大模型
### 系统功能
| | 功能 | 描述 |
| --- | --- | --- |
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
| | 岗位管理 | 配置系统用户所属担任职务 |
| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 |
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 |
| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 |
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
| | 通知公告 | 系统通知公告信息发布维护 |
| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
| | 功能 | 描述 |
|----|-------|---------------------------------|
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
| | 岗位管理 | 配置系统用户所属担任职务 |
| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 |
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 |
| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 |
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
| | 通知公告 | 系统通知公告信息发布维护 |
| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
![功能图](/.gitee/image/common/system-feature.png)
@ -126,32 +126,32 @@
>
> 前者支持轻量配置简单流程,后者实现复杂场景深度编排
| 功能列表 | 功能描述 | 是否完成 |
| --- | --- | --- |
| SIMPLE 设计器 | 仿钉钉/飞书设计器支持拖拽搭建表单流程10 分钟快速完成审批流程配置 | ✅ |
| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ |
| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ |
| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ |
| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ |
| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ |
| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ |
| 转办 | A 转给其 B 审批B 审批后,进入下一节点 | ✅ |
| 委派 | A 转给其 B 审批B 审批后,转给 AA 继续审批后进入下一节点 | ✅ |
| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ |
| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ |
| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ |
| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ |
| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ |
| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ |
| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ |
| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ |
| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ |
| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ |
| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ |
| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ |
| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ |
| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ |
| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ |
| 功能列表 | 功能描述 | 是否完成 |
|------------|-------------------------------------------------------------------------------------|------|
| SIMPLE 设计器 | 仿钉钉/飞书设计器支持拖拽搭建表单流程10 分钟快速完成审批流程配置 | ✅ |
| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ |
| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ |
| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ |
| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ |
| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ |
| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ |
| 转办 | A 转给其 B 审批B 审批后,进入下一节点 | ✅ |
| 委派 | A 转给其 B 审批B 审批后,转给 AA 继续审批后进入下一节点 | ✅ |
| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ |
| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ |
| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ |
| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ |
| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ |
| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ |
| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ |
| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ |
| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ |
| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ |
| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ |
| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ |
| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ |
| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ |
| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ |
### 支付系统
@ -165,26 +165,26 @@
### 基础设施
| | 功能 | 描述 |
| --- | --- | --- |
| 🚀 | 代码生成 | 前后端代码的生成Java、Vue、SQL、单元测试支持 CRUD 下载 |
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
| 🚀 | 文件服务 | 支持将文件存储到 S3MinIO、阿里云、腾讯云、七牛云、本地、FTP、数据库等 |
| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 |
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
| | MySQL 监控 | 监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈 |
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
| 🚀 | 消息队列 | 基于 Redis 实现消息队列Stream 提供集群消费Pub/Sub 提供广播消费 |
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
| | 功能 | 描述 |
|----|-----------|----------------------------------------------|
| 🚀 | 代码生成 | 前后端代码的生成Java、Vue、SQL、单元测试支持 CRUD 下载 |
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
| 🚀 | 文件服务 | 支持将文件存储到 S3MinIO、阿里云、腾讯云、七牛云、本地、FTP、数据库等 |
| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 |
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
| | MySQL 监控 | 监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈 |
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
| 🚀 | 消息队列 | 基于 Redis 实现消息队列Stream 提供集群消费Pub/Sub 提供广播消费 |
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
![功能图](/.gitee/image/common/infra-feature.png)
@ -197,19 +197,19 @@
### 微信公众号
| | 功能 | 描述 |
| --- | --- | --- |
| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 |
| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 |
| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 |
| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 |
| 🚀 | 模版消息 | 配置和发送模版消息,用于向粉丝推送通知类消息 |
| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 |
| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 |
| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 |
| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 |
| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 |
| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 |
| | 功能 | 描述 |
|----|--------|-------------------------------|
| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 |
| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 |
| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 |
| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 |
| 🚀 | 模版消息 | 配置和发送模版消息,用于向粉丝推送通知类消息 |
| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 |
| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 |
| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 |
| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 |
| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 |
| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 |
### 商城系统
@ -219,44 +219,18 @@
![功能图](/.gitee/image/common/mall-preview.png)
### 会员中心
| | 功能 | 描述 |
| --- | --- | --- |
| 🚀 | 会员管理 | 会员是 C 端的消费者,该功能用于会员的搜索与管理 |
| 🚀 | 会员标签 | 对会员的标签进行创建、查询、修改、删除等操作 |
| 🚀 | 会员等级 | 对会员的等级、成长值进行管理,可用于订单折扣等会员权益 |
| 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 |
| 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 |
### ERP 系统
演示地址:<https://doc.iocoder.cn/erp-preview/>
![功能图](/.gitee/image/common/erp-feature.png)
### WMS 系统
演示地址:<https://doc.iocoder.cn/wms-preview/>
![功能图](/.gitee/image/common/wms-feature.png)
![预览图](/.gitee/image/common/wms-preview.png)
### CRM 系统
演示地址:<https://doc.iocoder.cn/crm-preview/>
![功能图](/.gitee/image/common/crm-feature.png)
### MES 系统
演示地址:<https://doc.iocoder.cn/mes-preview/>
![功能图](/.gitee/image/common/mes-feature.png)
![功能图](/.gitee/image/common/mes-preview.png)
### AI 大模型
演示地址:<https://doc.iocoder.cn/ai-preview/>
@ -264,23 +238,3 @@
![功能图](/.gitee/image/common/ai-feature.png)
![功能图](/.gitee/image/common/ai-preview.gif)
### IoT 物联网
演示地址:<https://doc.iocoder.cn/iot/build>
![功能图](/.gitee/image/common/iot-feature.png)
![预览图](/.gitee/image/common/iot-preview.png)
### IM 即时通讯
演示地址Vue3 + Vben5<http://dashboard-vben.yudao.iocoder.cn>
使用文档:<https://doc.iocoder.cn/im-preview/>
![功能图](/.gitee/image/common/im-feature.png)
| 聊天界面 | 聊天管理 |
| --- | --- |
| ![聊天界面](/.gitee/image/common/im-preview-home.png) | ![聊天管理](/.gitee/image/common/im-preview-manager.png) |

View File

@ -33,6 +33,3 @@ VITE_APP_API_ENCRYPT_REQUEST_KEY = 52549111389893486934626385991395
VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883
# VITE_APP_API_ENCRYPT_REQUEST_KEY = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB
# VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ==
# 百度地图
VITE_BAIDU_MAP_KEY=Y2aJXiswwPxy6mwFs1z9c7U5gwX9WfUN

View File

@ -21,6 +21,3 @@ VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip
VITE_ARCHIVER=true
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=true

View File

@ -12,15 +12,16 @@
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
<title>%VITE_APP_TITLE%</title>
<title><%= VITE_APP_TITLE %></title>
<link rel="icon" href="/favicon.ico" />
<script>
var HM_ID = '<%= VITE_APP_BAIDU_CODE %>';
var HM_ID = '<%= VITE_APP_BAIDU_CODE %>'
if (HM_ID) {
var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script');
hm.src = 'https://hm.baidu.com/hm.js?' + HM_ID;
hm.src =
'https://hm.baidu.com/hm.js?' + HM_ID;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();

View File

@ -1,6 +1,6 @@
{
"name": "@vben/web-antd",
"version": "5.7.0",
"version": "5.5.9",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
@ -54,14 +54,12 @@
"camunda-bpmn-moddle": "catalog:",
"cropperjs": "catalog:",
"dayjs": "catalog:",
"dhtmlx-gantt": "catalog:",
"diagram-js": "catalog:",
"fast-xml-parser": "catalog:",
"highlight.js": "catalog:",
"pinia": "catalog:",
"steady-xml": "catalog:",
"tinymce": "catalog:",
"tyme4ts": "catalog:",
"video.js": "catalog:",
"vue": "catalog:",
"vue-dompurify-html": "catalog:",

View File

@ -0,0 +1 @@
export { default } from '@vben/tailwind-config/postcss';

View File

@ -2537,12 +2537,12 @@ interface EditorSelection {
normalize: () => Range;
selectorChanged: (selector: string, callback: (active: boolean, args: {
node: Node;
selector: string;
selector: String;
parents: Node[];
}) => void) => EditorSelection;
selectorChangedWithUnbind: (selector: string, callback: (active: boolean, args: {
node: Node;
selector: string;
selector: String;
parents: Node[];
}) => void) => {
unbind: () => void;
@ -3217,9 +3217,9 @@ interface Tools {
<T, R>(arr: ArrayLike<T> | null | undefined, cb: ArrayCallback<T, R>): R[];
<T, R>(obj: Record<string, T> | null | undefined, cb: ObjCallback<T, R>): R[];
};
extend: (obj: object, ext: object, ...objs: object[]) => any;
extend: (obj: Object, ext: Object, ...objs: Object[]) => any;
walk: <T extends Record<string, any>>(obj: T, f: WalkCallback<T>, n?: keyof T, scope?: any) => void;
resolve: (path: string, o?: object) => any;
resolve: (path: string, o?: Object) => any;
explode: (s: string | string[], d?: string | RegExp) => string[];
_addCacheSuffix: (url: string) => string;
}

View File

@ -3,82 +3,36 @@
* vben-formvben-modalvben-drawer 使,
*/
/* eslint-disable vue/one-component-per-file */
import type {
AutoCompleteProps,
ButtonProps,
CascaderProps,
CheckboxGroupProps,
CheckboxProps,
DatePickerProps,
DividerProps,
InputNumberProps,
InputProps,
MentionsProps,
RadioGroupProps,
RadioProps,
RateProps,
SelectProps,
SpaceProps,
SwitchProps,
TextAreaProps,
TimePickerProps,
TreeSelectProps,
UploadChangeParam,
UploadFile,
UploadProps,
} from 'ant-design-vue';
import type { RangePickerProps } from 'ant-design-vue/es/date-picker';
import type { Component, Ref } from 'vue';
import type {
ApiComponentSharedProps,
BaseFormComponentType,
IconPickerProps,
} from '@vben/common-ui';
import type { Sortable } from '@vben/hooks';
import type { BaseFormComponentType } from '@vben/common-ui';
import type { Recordable } from '@vben/types';
import {
computed,
defineAsyncComponent,
defineComponent,
h,
nextTick,
onMounted,
onUnmounted,
ref,
render,
unref,
watch,
} from 'vue';
import {
ApiComponent,
globalShareState,
IconPicker,
VCropper,
} from '@vben/common-ui';
import { useSortable } from '@vben/hooks';
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { isEmpty } from '@vben/utils';
import { message, Modal, notification } from 'ant-design-vue';
import { notification } from 'ant-design-vue';
import { Tinymce as RichTextarea } from '#/components/tinymce';
import { FileUpload, ImageUpload } from '#/components/upload';
type AdapterUploadProps = UploadProps & {
aspectRatio?: string;
crop?: boolean;
draggable?: boolean;
handleChange?: (event: UploadChangeParam) => void;
maxSize?: number;
onDragSort?: (oldIndex: number, newIndex: number) => void;
onHandleChange?: (event: UploadChangeParam) => void;
};
const AutoComplete = defineAsyncComponent(
() => import('ant-design-vue/es/auto-complete'),
@ -136,8 +90,8 @@ const PreviewGroup = defineAsyncComponent(() =>
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
);
const withDefaultPlaceholder = (
component: Component,
const withDefaultPlaceholder = <T extends Component>(
component: T,
type: 'input' | 'select',
componentProps: Recordable<any> = {},
) => {
@ -170,109 +124,172 @@ const withDefaultPlaceholder = (
});
};
const IMAGE_EXTENSIONS = new Set([
'bmp',
'gif',
'jpeg',
'jpg',
'png',
'svg',
'webp',
]);
const withPreviewUpload = () => {
return defineComponent({
name: Upload.name,
emits: ['change', 'update:modelValue'],
setup: (
props: any,
{ attrs, slots, emit }: { attrs: any; emit: any; slots: any },
) => {
const previewVisible = ref<boolean>(false);
/**
*
*/
function isImageFile(file: UploadFile): boolean {
if (file.url) {
try {
const pathname = new URL(file.url, 'http://localhost').pathname;
const ext = pathname.split('.').pop()?.toLowerCase();
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
} catch {
const ext = file.url?.split('.').pop()?.toLowerCase();
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
const placeholder = attrs?.placeholder || $t(`ui.placeholder.upload`);
const listType = attrs?.listType || attrs?.['list-type'] || 'text';
const fileList = ref<UploadProps['fileList']>(
attrs?.fileList || attrs?.['file-list'] || [],
);
const handleChange = async (event: UploadChangeParam) => {
fileList.value = event.fileList;
emit('change', event);
emit(
'update:modelValue',
event.fileList?.length ? fileList.value : undefined,
);
};
const handlePreview = async (file: UploadFile) => {
previewVisible.value = true;
await previewImage(file, previewVisible, fileList);
};
const renderUploadButton = (): any => {
const isDisabled = attrs.disabled;
// 如果禁用,不渲染上传按钮
if (isDisabled) {
return null;
}
// 否则渲染默认上传按钮
return isEmpty(slots)
? createDefaultSlotsWithUpload(listType, placeholder)
: slots;
};
// 可以监听到表单API设置的值
watch(
() => attrs.modelValue,
(res) => {
fileList.value = res;
},
);
return () =>
h(
Upload,
{
...props,
...attrs,
fileList: fileList.value,
onChange: handleChange,
onPreview: handlePreview,
},
renderUploadButton(),
);
},
});
};
const createDefaultSlotsWithUpload = (
listType: string,
placeholder: string,
) => {
switch (listType) {
case 'picture-card': {
return {
default: () => placeholder,
};
}
default: {
return {
default: () =>
h(
Button,
{
icon: h(IconifyIcon, {
icon: 'ant-design:upload-outlined',
class: 'mb-1 size-4',
}),
},
() => placeholder,
),
};
}
}
if (!file.type) {
const ext = file.name?.split('.').pop()?.toLowerCase();
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
}
return file.type.startsWith('image/');
}
};
/**
*
*/
function createDefaultUploadSlots(listType: string, placeholder: string) {
if (listType === 'picture-card') {
return { default: () => placeholder };
}
return {
default: () =>
h(
Button,
{
icon: h(IconifyIcon, {
icon: 'ant-design:upload-outlined',
class: 'mb-1 size-4',
}),
},
() => placeholder,
),
};
}
/**
* Base64
*/
function getBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.addEventListener('load', () => resolve(reader.result as string));
reader.addEventListener('error', reject);
});
}
/**
*
*/
async function previewImage(
const previewImage = async (
file: UploadFile,
visible: Ref<boolean>,
fileList: Ref<UploadProps['fileList']>,
) {
// 非图片文件直接打开链接
) => {
// 检查是否为图片文件的辅助函数
const isImageFile = (file: UploadFile): boolean => {
const imageExtensions = new Set([
'bmp',
'gif',
'jpeg',
'jpg',
'png',
'webp',
]);
if (file.url) {
const ext = file.url?.split('.').pop()?.toLowerCase();
return ext ? imageExtensions.has(ext) : false;
}
if (!file.type) {
const ext = file.name?.split('.').pop()?.toLowerCase();
return ext ? imageExtensions.has(ext) : false;
}
return file.type.startsWith('image/');
};
// 如果当前文件不是图片,直接打开
if (!isImageFile(file)) {
const url = file.url || file.preview;
if (url) {
window.open(url, '_blank');
if (file.url) {
window.open(file.url, '_blank');
} else if (file.preview) {
window.open(file.preview, '_blank');
} else {
message.error($t('ui.formRules.previewWarning'));
console.warn('无法打开文件没有可用的URL或预览地址');
}
return;
}
// 对于图片文件,继续使用预览组
const [ImageComponent, PreviewGroupComponent] = await Promise.all([
Image,
PreviewGroup,
]);
// 过滤图片文件并生成预览
const imageFiles = (unref(fileList) || []).filter((f) => isImageFile(f));
const getBase64 = (file: File) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.addEventListener('load', () => resolve(reader.result));
reader.addEventListener('error', (error) => reject(error));
});
};
// 从fileList中过滤出所有图片文件
const imageFiles = (unref(fileList) || []).filter((element) =>
isImageFile(element),
);
// 为所有没有预览地址的图片生成预览
for (const imgFile of imageFiles) {
if (!imgFile.url && !imgFile.preview && imgFile.originFileObj) {
imgFile.preview = await getBase64(imgFile.originFileObj);
imgFile.preview = (await getBase64(imgFile.originFileObj)) as string;
}
}
const container = document.createElement('div');
const container: HTMLElement | null = document.createElement('div');
document.body.append(container);
let isUnmounted = false;
const currentIndex = imageFiles.findIndex((f) => f.uid === file.uid);
// 用于追踪组件是否已卸载
let isUnmounted = false;
const PreviewWrapper = {
setup() {
@ -284,10 +301,12 @@ async function previewImage(
class: 'hidden',
preview: {
visible: visible.value,
current: currentIndex,
// 设置初始显示的图片索引
current: imageFiles.findIndex((f) => f.uid === file.uid),
onVisibleChange: (value: boolean) => {
visible.value = value;
if (!value) {
// 延迟清理,确保动画完成
setTimeout(() => {
if (!isUnmounted && container) {
isUnmounted = true;
@ -300,6 +319,7 @@ async function previewImage(
},
},
() =>
// 渲染所有图片文件
imageFiles.map((imgFile) =>
h(ImageComponent, {
key: imgFile.uid,
@ -312,292 +332,6 @@ async function previewImage(
};
render(h(PreviewWrapper), container);
}
/**
*
*/
function cropImage(file: File, aspectRatio: string | undefined) {
return new Promise<Blob | string | undefined>((resolve, reject) => {
const container = document.createElement('div');
document.body.append(container);
let isUnmounted = false;
let objectUrl: null | string = null;
const open = ref<boolean>(true);
const cropperRef = ref<InstanceType<typeof VCropper> | null>(null);
const closeModal = () => {
open.value = false;
setTimeout(() => {
if (!isUnmounted && container) {
if (objectUrl) {
URL.revokeObjectURL(objectUrl);
}
isUnmounted = true;
render(null, container);
container.remove();
}
}, 300);
};
const CropperWrapper = {
setup() {
return () => {
if (isUnmounted) return null;
if (!objectUrl) {
objectUrl = URL.createObjectURL(file);
}
return h(
Modal,
{
open: open.value,
title: h('div', {}, [
$t('ui.crop.title'),
h(
'span',
{
class: `${aspectRatio ? '' : 'hidden'} ml-2 text-sm text-gray-400 font-normal`,
},
$t('ui.crop.titleTip', [aspectRatio]),
),
]),
centered: true,
width: 548,
keyboard: false,
maskClosable: false,
closable: false,
cancelText: $t('common.cancel'),
okText: $t('ui.crop.confirm'),
destroyOnClose: true,
onOk: async () => {
const cropper = cropperRef.value;
if (!cropper) {
reject(new Error('Cropper not found'));
closeModal();
return;
}
try {
const dataUrl = await cropper.getCropImage();
if (dataUrl) {
resolve(dataUrl);
} else {
reject(new Error($t('ui.crop.errorTip')));
}
} catch {
reject(new Error($t('ui.crop.errorTip')));
} finally {
closeModal();
}
},
onCancel() {
resolve('');
closeModal();
},
},
() =>
h(VCropper, {
ref: (ref: any) => (cropperRef.value = ref),
img: objectUrl as string,
aspectRatio,
}),
);
};
},
};
render(h(CropperWrapper), container);
});
}
/**
*
*/
const withPreviewUpload = () => {
return defineComponent({
name: Upload.name,
emits: ['update:modelValue'],
setup(
props: any,
{ attrs, slots, emit }: { attrs: any; emit: any; slots: any },
) {
const previewVisible = ref<boolean>(false);
const placeholder = attrs?.placeholder || $t('ui.placeholder.upload');
const listType = attrs?.listType || attrs?.['list-type'] || 'text';
const fileList = ref<UploadProps['fileList']>(
attrs?.fileList || attrs?.['file-list'] || [],
);
const maxSize = computed(() => attrs?.maxSize ?? attrs?.['max-size']);
const aspectRatio = computed(
() => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
);
const handleBeforeUpload = async (
file: UploadFile,
originFileList: Array<File>,
) => {
// 文件大小限制
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
file.status = 'removed';
return false;
}
// 图片裁剪处理
if (
attrs.crop &&
!attrs.multiple &&
originFileList[0] &&
isImageFile(file)
) {
file.status = 'removed';
const blob = await cropImage(originFileList[0], aspectRatio.value);
if (!blob) {
throw new Error($t('ui.crop.errorTip'));
}
return blob;
}
return attrs.beforeUpload?.(file) ?? true;
};
const handleChange = (event: UploadChangeParam) => {
try {
attrs.handleChange?.(event);
attrs.onHandleChange?.(event);
} catch (error) {
console.error(error);
}
fileList.value = event.fileList.filter(
(file) => file.status !== 'removed',
);
emit(
'update:modelValue',
event.fileList?.length ? fileList.value : undefined,
);
};
const handlePreview = async (file: UploadFile) => {
previewVisible.value = true;
await previewImage(file, previewVisible, fileList);
};
const renderUploadButton = () => {
if (attrs.disabled) return null;
return isEmpty(slots)
? createDefaultUploadSlots(listType, placeholder)
: slots;
};
// 拖拽排序
const draggable = computed(
() => (attrs.draggable ?? false) && !attrs.disabled,
);
const uploadId = `upload-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
const sortableInstance = ref<null | Sortable>(null);
const styleId = `upload-drag-style-${uploadId}`;
function injectDragStyle() {
if (!document.querySelector(`[id="${styleId}"]`)) {
const style = document.createElement('style');
style.id = styleId;
style.textContent = `
[data-upload-id="${uploadId}"] .ant-upload-list-item { cursor: move; }
[data-upload-id="${uploadId}"] .ant-upload-list-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
`;
document.head.append(style);
}
}
function removeDragStyle() {
document.querySelector(`[id="${styleId}"]`)?.remove();
}
async function initSortable(retryCount = 0) {
if (!draggable.value) return;
injectDragStyle();
await nextTick();
await new Promise((resolve) => setTimeout(resolve, 100));
const container = document.querySelector(
`[data-upload-id="${uploadId}"] .ant-upload-list`,
) as HTMLElement;
if (!container) {
if (retryCount < 5) {
setTimeout(() => initSortable(retryCount + 1), 200);
}
return;
}
const { initializeSortable } = useSortable(container, {
animation: 300,
delay: 400,
delayOnTouchOnly: true,
filter:
'.ant-upload-select, .ant-upload-list-item-error, .ant-upload-list-item-uploading',
onEnd: (evt) => {
const { oldIndex, newIndex } = evt;
if (
oldIndex === undefined ||
newIndex === undefined ||
oldIndex === newIndex
) {
return;
}
const list = [...(fileList.value || [])];
const [movedItem] = list.splice(oldIndex, 1);
if (movedItem) {
list.splice(newIndex, 0, movedItem);
fileList.value = list;
}
attrs.onDragSort?.(oldIndex, newIndex);
emit('update:modelValue', fileList.value);
},
});
sortableInstance.value = await initializeSortable();
}
// 监听表单值变化
watch(
() => attrs.modelValue,
(res) => {
fileList.value = res;
},
);
onMounted(initSortable);
onUnmounted(() => {
sortableInstance.value?.destroy();
removeDragStyle();
});
return () =>
h(
'div',
{ 'data-upload-id': uploadId, class: 'w-full' },
h(
Upload,
{
...props,
...attrs,
fileList: fileList.value,
beforeUpload: handleBeforeUpload,
onChange: handleChange,
onPreview: handlePreview,
},
renderUploadButton() as any,
),
);
},
});
};
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
@ -635,45 +369,11 @@ export type ComponentType =
| 'Upload'
| BaseFormComponentType;
/**
* {@link ComponentType} 便 Schema `component` + `componentProps`
*/
export interface ComponentPropsMap {
ApiCascader: ApiComponentSharedProps & CascaderProps;
ApiSelect: ApiComponentSharedProps & SelectProps;
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
AutoComplete: AutoCompleteProps;
Cascader: CascaderProps;
Checkbox: CheckboxProps;
CheckboxGroup: CheckboxGroupProps;
DatePicker: DatePickerProps;
DefaultButton: ButtonProps;
Divider: DividerProps;
IconPicker: IconPickerProps;
Input: InputProps;
InputNumber: InputNumberProps;
InputPassword: InputProps;
Mentions: MentionsProps;
PrimaryButton: ButtonProps;
Radio: RadioProps;
RadioGroup: RadioGroupProps;
RangePicker: RangePickerProps;
Rate: RateProps;
Select: SelectProps;
Space: SpaceProps;
Switch: SwitchProps;
Textarea: TextAreaProps;
TimePicker: TimePickerProps;
TreeSelect: TreeSelectProps;
Upload: AdapterUploadProps;
}
async function initComponentAdapter() {
const components: Partial<Record<ComponentType, Component>> = {
// 如果你的组件体积比较大,可以使用异步加载
// Button: () =>
// import('xxx').then((res) => res.Button),
ApiCascader: withDefaultPlaceholder(ApiComponent, 'select', {
component: Cascader,
fieldNames: { label: 'label', value: 'value', children: 'children' },
@ -681,20 +381,34 @@ async function initComponentAdapter() {
modelPropName: 'value',
visibleEvent: 'onVisibleChange',
}),
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: Select,
loadingSlot: 'suffixIcon',
modelPropName: 'value',
visibleEvent: 'onVisibleChange',
}),
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon',
modelPropName: 'value',
optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange',
}),
ApiSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiSelect',
},
'select',
{
component: Select,
loadingSlot: 'suffixIcon',
visibleEvent: 'onDropdownVisibleChange',
modelPropName: 'value',
},
),
ApiTreeSelect: withDefaultPlaceholder(
{
...ApiComponent,
name: 'ApiTreeSelect',
},
'select',
{
component: TreeSelect,
fieldNames: { label: 'label', value: 'value', children: 'children' },
loadingSlot: 'suffixIcon',
modelPropName: 'value',
optionsPropName: 'treeData',
visibleEvent: 'onVisibleChange',
},
),
AutoComplete,
Cascader,
Checkbox,
@ -711,9 +425,7 @@ async function initComponentAdapter() {
modelValueProp: 'value',
}),
Input: withDefaultPlaceholder(Input, 'input'),
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
style: { width: '100%' },
}),
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
Mentions: withDefaultPlaceholder(Mentions, 'input'),
// 自定义主要按钮

View File

@ -1,9 +1,9 @@
import type {
VbenFormProps as FormProps,
VbenFormSchema as FormSchema,
VbenFormProps,
} from '@vben/common-ui';
import type { ComponentPropsMap, ComponentType } from './component';
import type { ComponentType } from './component';
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
import { $t } from '@vben/locales';
@ -61,10 +61,9 @@ async function initSetupVbenForm() {
});
}
const useVbenForm = useForm<ComponentType, ComponentPropsMap>;
const useVbenForm = useForm<ComponentType>;
export { initSetupVbenForm, useVbenForm, z };
export type VbenFormApi = ReturnType<typeof useVbenForm>[1]; // add by 芋艿:用于 data.ts 表单 schema 内调用 setFieldValue
export type VbenFormSchema = FormSchema<ComponentType, ComponentPropsMap>;
export type VbenFormProps = FormProps<ComponentType, ComponentPropsMap>;
export type VbenFormSchema = FormSchema<ComponentType>;
export type { VbenFormProps };

View File

@ -1,8 +1,6 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { Recordable } from '@vben/types';
import type { ComponentPropsMap, ComponentType } from './component';
import { h } from 'vue';
import { IconifyIcon } from '@vben/icons';
@ -12,7 +10,7 @@ import {
AsyncVxeTable,
createRequiredValidation,
setupVbenVxeTable,
useVbenVxeGrid as useGrid,
useVbenVxeGrid,
} from '@vben/plugins/vxe-table';
import {
erpCountInputFormatter,
@ -201,7 +199,7 @@ setupVbenVxeTable({
vxeUI.renderer.add('CellOperation', {
renderTableDefault({ attrs, options, props }, { column, row }) {
const defaultProps = { size: 'small', type: 'link', ...props };
let align: string;
let align = 'end';
switch (column.align) {
case 'center': {
align = 'center';
@ -365,13 +363,10 @@ setupVbenVxeTable({
useVbenForm,
});
export { createRequiredValidation };
export { createRequiredValidation, useVbenVxeGrid };
export const [VxeTable, VxeColumn] = [AsyncVxeTable, AsyncVxeColumn];
export * from '#/components/table-action';
export const useVbenVxeGrid = <T extends Record<string, any>>(
...rest: Parameters<typeof useGrid<T, ComponentType, ComponentPropsMap>>
) => useGrid<T, ComponentType, ComponentPropsMap>(...rest);
export type * from '@vben/plugins/vxe-table';

View File

@ -21,6 +21,11 @@ export async function createLeave(data: BpmOALeaveApi.Leave) {
return requestClient.post('/bpm/oa/leave/create', data);
}
/** 更新请假申请 */
export async function updateLeave(data: BpmOALeaveApi.Leave) {
return requestClient.post('/bpm/oa/leave/update', data);
}
/** 获得请假申请 */
export async function getLeave(id: number) {
return requestClient.get<BpmOALeaveApi.Leave>(`/bpm/oa/leave/get?id=${id}`);

View File

@ -16,10 +16,10 @@ export namespace CrmCustomerLimitConfigApi {
/** 客户限制配置类型 */
export enum LimitConfType {
/** 拥有客户数限制 */
CUSTOMER_QUANTITY_LIMIT = 1,
/** 锁定客户数限制 */
CUSTOMER_LOCK_LIMIT = 2,
/** 拥有客户数限制 */
CUSTOMER_QUANTITY_LIMIT = 1,
}
/** 查询客户限制配置列表 */

View File

@ -35,11 +35,11 @@ export namespace CrmPermissionApi {
* CRM
*/
export enum BizTypeEnum {
CRM_CLUE = 1, // 线索
CRM_CUSTOMER = 2, // 客户
CRM_CONTACT = 3, // 联系人
CRM_BUSINESS = 4, // 商机
CRM_CLUE = 1, // 线索
CRM_CONTACT = 3, // 联系人
CRM_CONTRACT = 5, // 合同
CRM_CUSTOMER = 2, // 客户
CRM_PRODUCT = 6, // 产品
CRM_RECEIVABLE = 7, // 回款
CRM_RECEIVABLE_PLAN = 8, // 回款计划

View File

@ -29,10 +29,6 @@ export namespace CrmReceivablePlanApi {
returnTime: Date;
};
}
export interface PlanPageParam extends PageParam {
customerId?: number;
contractId?: number;
}
}
/** 查询回款计划列表 */

View File

@ -3,24 +3,37 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace AlertConfigApi {
/** IoT 告警配置 */
/** IoT 告警配置 VO */
export interface AlertConfig {
id?: number;
name?: string;
name: string;
description?: string;
level?: number;
status?: number;
sceneRuleIds?: number[];
receiveUserIds?: number[];
receiveUserNames?: string[];
receiveUserNames?: string;
receiveTypes?: number[];
smsTemplateCode?: string;
mailTemplateCode?: string;
notifyTemplateCode?: string;
createTime?: Date;
updateTime?: Date;
}
}
/** IoT 告警配置 */
export interface AlertConfig {
id?: number;
name?: string;
description?: string;
level?: number;
status?: number;
sceneRuleIds?: number[];
receiveUserIds?: number[];
receiveUserNames?: string;
receiveTypes?: number[];
createTime?: Date;
updateTime?: Date;
}
/** 查询告警配置分页 */
export function getAlertConfigPage(params: PageParam) {
return requestClient.get<PageResult<AlertConfigApi.AlertConfig>>(
@ -36,20 +49,20 @@ export function getAlertConfig(id: number) {
);
}
/** 获取告警配置简单列表 */
export function getSimpleAlertConfigList() {
/** 查询所有告警配置列表 */
export function getAlertConfigList() {
return requestClient.get<AlertConfigApi.AlertConfig[]>(
'/iot/alert-config/simple-list',
'/iot/alert-config/list',
);
}
/** 新增告警配置 */
export function createAlertConfig(data: AlertConfigApi.AlertConfig) {
export function createAlertConfig(data: AlertConfig) {
return requestClient.post('/iot/alert-config/create', data);
}
/** 修改告警配置 */
export function updateAlertConfig(data: AlertConfigApi.AlertConfig) {
export function updateAlertConfig(data: AlertConfig) {
return requestClient.put('/iot/alert-config/update', data);
}
@ -57,3 +70,25 @@ export function updateAlertConfig(data: AlertConfigApi.AlertConfig) {
export function deleteAlertConfig(id: number) {
return requestClient.delete(`/iot/alert-config/delete?id=${id}`);
}
/** 批量删除告警配置 */
export function deleteAlertConfigList(ids: number[]) {
return requestClient.delete('/iot/alert-config/delete-list', {
params: { ids: ids.join(',') },
});
}
/** 启用/禁用告警配置 */
export function toggleAlertConfig(id: number, enabled: boolean) {
return requestClient.put(`/iot/alert-config/toggle`, {
id,
enabled,
});
}
/** 获取告警配置简单列表 */
export function getSimpleAlertConfigList() {
return requestClient.get<AlertConfigApi.AlertConfig[]>(
'/iot/alert-config/simple-list',
);
}

View File

@ -3,21 +3,41 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace AlertRecordApi {
/** IoT 告警记录 */
/** IoT 告警记录 VO */
export interface AlertRecord {
id?: number;
configId?: number;
configName?: string;
configLevel?: number;
deviceId?: number;
deviceName?: string;
productId?: number;
deviceMessage?: any;
productName?: string;
deviceMessage?: string;
processStatus?: boolean;
processRemark?: string;
processTime?: Date;
createTime?: Date;
}
}
/** IoT 告警记录 */
export interface AlertRecord {
id?: number;
configId?: number;
configName?: string;
configLevel?: number;
deviceId?: number;
deviceName?: string;
productId?: number;
productName?: string;
deviceMessage?: string;
processStatus?: boolean;
processRemark?: string;
processTime?: Date;
createTime?: Date;
}
/** 查询告警记录分页 */
export function getAlertRecordPage(params: PageParam) {
return requestClient.get<PageResult<AlertRecordApi.AlertRecord>>(
@ -34,9 +54,29 @@ export function getAlertRecord(id: number) {
}
/** 处理告警记录 */
export function processAlertRecord(id: number, processRemark?: string) {
export function processAlertRecord(id: number, remark?: string) {
return requestClient.put('/iot/alert-record/process', {
id,
processRemark,
remark,
});
}
/** 批量处理告警记录 */
export function batchProcessAlertRecord(ids: number[], remark?: string) {
return requestClient.put('/iot/alert-record/batch-process', {
ids,
remark,
});
}
/** 删除告警记录 */
export function deleteAlertRecord(id: number) {
return requestClient.delete(`/iot/alert-record/delete?id=${id}`);
}
/** 批量删除告警记录 */
export function deleteAlertRecordList(ids: number[]) {
return requestClient.delete('/iot/alert-record/delete-list', {
params: { ids: ids.join(',') },
});
}

View File

@ -3,48 +3,39 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace IotDeviceApi {
// TODO @haohao需要跟后端对齐必要的 ReqVO、RespVO
/** 设备 */
export interface Device {
id?: number; // 设备编号
id?: number; // 设备 ID主键自增
deviceName: string; // 设备名称
nickname?: string; // 备注名称
serialNumber?: string; // 设备序列号
picUrl?: string; // 设备图片
groupIds?: number[]; // 设备分组编号数组
productId: number; // 产品编号
productKey?: string; // 产品标识
productName?: string; // 产品名称(只有部分接口返回,例如 getDeviceLocationList
deviceType?: number; // 设备类型
nickname?: string; // 设备备注名称
gatewayId?: number; // 网关设备 ID
state?: number; // 设备状态
status?: number; // 设备状态(兼容字段)
onlineTime?: Date; // 最后上线时间
offlineTime?: Date; // 最后离线时间
activeTime?: Date; // 设备激活时间
deviceSecret?: string; // 设备密钥,用于设备认证
config?: string; // 设备配置
createTime?: Date; // 创建时间
ip?: string; // 设备的 IP 地址
firmwareVersion?: string; // 设备的固件版本
deviceSecret?: string; // 设备密钥,用于设备认证,需安全存储
mqttClientId?: string; // MQTT 客户端 ID
mqttUsername?: string; // MQTT 用户名
mqttPassword?: string; // MQTT 密码
authType?: string; // 认证类型
locationType?: number; // 定位类型
latitude?: number; // 设备位置的纬度
longitude?: number; // 设备位置的经度
createTime?: Date; // 创建时间
}
/** 设备更新分组 Request VO */
export interface DeviceUpdateGroupReqVO {
ids: number[]; // 设备编号列表(必填)
groupIds: number[]; // 分组编号列表(必填)
}
/** 设备认证信息 Response VO */
export interface DeviceAuthInfoRespVO {
clientId: string; // 客户端 ID
username: string; // 用户名
password: string; // 密码
}
/** 设备导入 Response VO */
export interface DeviceImportRespVO {
createDeviceNames?: string[]; // 创建成功的设备名称列表
updateDeviceNames?: string[]; // 更新成功的设备名称列表
failureDeviceNames?: Record<string, string>; // 失败的设备名称及原因
areaId?: number; // 地区编码
address?: string; // 设备详细地址
serialNumber?: string; // 设备序列号
config?: string; // 设备配置
groupIds?: number[]; // 添加分组 ID
picUrl?: string; // 设备图片
location?: string; // 位置信息(格式:经度,纬度)
}
/** IoT 设备属性详细 VO */
@ -65,12 +56,25 @@ export namespace IotDeviceApi {
updateTime: Date; // 更新时间
}
/** 设备认证参数 VO */
export interface DeviceAuthInfo {
clientId: string; // 客户端 ID
username: string; // 用户名
password: string; // 密码
}
/** 设备发送消息 Request VO */
export interface DeviceMessageSendReq {
deviceId: number; // 设备编号
method: string; // 请求方法
params?: any; // 请求参数
}
/** 设备分组更新请求 */
export interface DeviceGroupUpdateReq {
ids: number[]; // 设备 ID 列表
groupIds: number[]; // 分组 ID 列表
}
}
/** 查询设备分页 */
@ -88,33 +92,33 @@ export function getDevice(id: number) {
/** 新增设备 */
export function createDevice(data: IotDeviceApi.Device) {
return requestClient.post<number>('/iot/device/create', data);
return requestClient.post('/iot/device/create', data);
}
/** 修改设备 */
export function updateDevice(data: IotDeviceApi.Device) {
return requestClient.put<boolean>('/iot/device/update', data);
return requestClient.put('/iot/device/update', data);
}
/** 修改设备分组 */
export function updateDeviceGroup(data: IotDeviceApi.DeviceUpdateGroupReqVO) {
return requestClient.put<boolean>('/iot/device/update-group', data);
export function updateDeviceGroup(data: IotDeviceApi.DeviceGroupUpdateReq) {
return requestClient.put('/iot/device/update-group', data);
}
/** 删除单个设备 */
export function deleteDevice(id: number) {
return requestClient.delete<boolean>(`/iot/device/delete?id=${id}`);
return requestClient.delete(`/iot/device/delete?id=${id}`);
}
/** 删除多个设备 */
export function deleteDeviceList(ids: number[]) {
return requestClient.delete<boolean>('/iot/device/delete-list', {
return requestClient.delete('/iot/device/delete-list', {
params: { ids: ids.join(',') },
});
}
/** 导出设备 */
export function exportDeviceExcel(params: PageParam) {
export function exportDeviceExcel(params: any) {
return requestClient.download('/iot/device/export-excel', { params });
}
@ -137,11 +141,6 @@ export function getDeviceListByProductId(productId: number) {
});
}
/** 获取设备位置列表(用于地图展示) */
export function getDeviceLocationList() {
return requestClient.get<IotDeviceApi.Device[]>('/iot/device/location-list');
}
/** 获取导入模板 */
export function importDeviceTemplate() {
return requestClient.download('/iot/device/get-import-template');
@ -149,10 +148,10 @@ export function importDeviceTemplate() {
/** 导入设备 */
export function importDevice(file: File, updateSupport: boolean) {
return requestClient.upload<IotDeviceApi.DeviceImportRespVO>(
`/iot/device/import?updateSupport=${updateSupport}`,
{ file },
);
return requestClient.upload('/iot/device/import', {
file,
updateSupport,
});
}
/** 获取设备属性最新数据 */
@ -165,7 +164,7 @@ export function getLatestDeviceProperties(params: any) {
/** 获取设备属性历史数据 */
export function getHistoryDevicePropertyList(params: any) {
return requestClient.get<IotDeviceApi.DeviceProperty[]>(
return requestClient.get<PageResult<IotDeviceApi.DeviceProperty>>(
'/iot/device/property/history-list',
{ params },
);
@ -173,7 +172,7 @@ export function getHistoryDevicePropertyList(params: any) {
/** 获取设备认证信息 */
export function getDeviceAuthInfo(id: number) {
return requestClient.get<IotDeviceApi.DeviceAuthInfoRespVO>(
return requestClient.get<IotDeviceApi.DeviceAuthInfo>(
'/iot/device/get-auth-info',
{ params: { id } },
);
@ -197,35 +196,3 @@ export function getDeviceMessagePairPage(params: PageParam) {
export function sendDeviceMessage(params: IotDeviceApi.DeviceMessageSendReq) {
return requestClient.post('/iot/device/message/send', params);
}
/** 绑定子设备到网关设备 */
export function bindDeviceGateway(gatewayId: number, subIds: number[]) {
return requestClient.put<boolean>('/iot/device/bind-gateway', {
gatewayId,
subIds,
});
}
/** 解绑子设备与网关设备 */
export function unbindDeviceGateway(gatewayId: number, subIds: number[]) {
return requestClient.put<boolean>('/iot/device/unbind-gateway', {
gatewayId,
subIds,
});
}
/** 获取网关设备的子设备列表 */
export function getSubDeviceList(gatewayId: number) {
return requestClient.get<IotDeviceApi.Device[]>(
'/iot/device/sub-device-list',
{ params: { gatewayId } },
);
}
/** 获取未绑定的子设备分页 */
export function getUnboundSubDevicePage(params: PageParam) {
return requestClient.get<PageResult<IotDeviceApi.Device>>(
'/iot/device/unbound-sub-device-page',
{ params },
);
}

View File

@ -1,30 +0,0 @@
import { requestClient } from '#/api/request';
export namespace IotDeviceModbusConfigApi {
/** Modbus 连接配置 VO */
export interface ModbusConfig {
id?: number; // 主键
deviceId: number; // 设备编号
ip: string; // Modbus 服务器 IP 地址
port: number; // Modbus 服务器端口
slaveId: number; // 从站地址
timeout: number; // 连接超时时间,单位:毫秒
retryInterval: number; // 重试间隔,单位:毫秒
mode: number; // 模式
frameFormat: number; // 帧格式
status: number; // 状态
}
}
/** 获取设备的 Modbus 连接配置 */
export function getModbusConfig(deviceId: number) {
return requestClient.get<IotDeviceModbusConfigApi.ModbusConfig>(
'/iot/device-modbus-config/get',
{ params: { deviceId } },
);
}
/** 保存 Modbus 连接配置 */
export function saveModbusConfig(data: IotDeviceModbusConfigApi.ModbusConfig) {
return requestClient.post('/iot/device-modbus-config/save', data);
}

View File

@ -1,52 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace IotDeviceModbusPointApi {
/** Modbus 点位配置 VO */
export interface ModbusPoint {
id?: number; // 主键
deviceId: number; // 设备编号
thingModelId?: number; // 物模型属性编号
identifier: string; // 属性标识符
name: string; // 属性名称
functionCode?: number; // Modbus 功能码
registerAddress?: number; // 寄存器起始地址
registerCount?: number; // 寄存器数量
byteOrder?: string; // 字节序
rawDataType?: string; // 原始数据类型
scale: number; // 缩放因子
pollInterval: number; // 轮询间隔,单位:毫秒
status: number; // 状态
}
}
/** 获取设备的 Modbus 点位分页 */
export function getModbusPointPage(params: PageParam) {
return requestClient.get<PageResult<IotDeviceModbusPointApi.ModbusPoint>>(
'/iot/device-modbus-point/page',
{ params },
);
}
/** 获取 Modbus 点位详情 */
export function getModbusPoint(id: number) {
return requestClient.get<IotDeviceModbusPointApi.ModbusPoint>(
`/iot/device-modbus-point/get?id=${id}`,
);
}
/** 创建 Modbus 点位配置 */
export function createModbusPoint(data: IotDeviceModbusPointApi.ModbusPoint) {
return requestClient.post('/iot/device-modbus-point/create', data);
}
/** 更新 Modbus 点位配置 */
export function updateModbusPoint(data: IotDeviceModbusPointApi.ModbusPoint) {
return requestClient.put('/iot/device-modbus-point/update', data);
}
/** 删除 Modbus 点位配置 */
export function deleteModbusPoint(id: number) {
return requestClient.delete(`/iot/device-modbus-point/delete?id=${id}`);
}

View File

@ -3,22 +3,39 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace IoTOtaFirmwareApi {
/** IoT OTA 固件信息 */
/** IoT OTA 固件 VO */
export interface Firmware {
id?: number;
name?: string;
description?: string;
version?: string;
productId?: number;
name: string;
version: string;
productId: number;
productName?: string;
description?: string;
fileUrl?: string;
fileMd5?: string;
fileSize?: number;
fileDigestAlgorithm?: string;
fileDigestValue?: string;
status?: number;
createTime?: Date;
updateTime?: Date;
}
}
/** IoT OTA 固件 */
export interface IoTOtaFirmware {
id?: number;
name?: string;
version?: string;
productId?: number;
productName?: string;
description?: string;
fileUrl?: string;
fileMd5?: string;
fileSize?: number;
status?: number;
createTime?: Date;
updateTime?: Date;
}
/** 查询 OTA 固件分页 */
export function getOtaFirmwarePage(params: PageParam) {
return requestClient.get<PageResult<IoTOtaFirmwareApi.Firmware>>(
@ -35,12 +52,12 @@ export function getOtaFirmware(id: number) {
}
/** 新增 OTA 固件 */
export function createOtaFirmware(data: IoTOtaFirmwareApi.Firmware) {
export function createOtaFirmware(data: IoTOtaFirmware) {
return requestClient.post('/iot/ota/firmware/create', data);
}
/** 修改 OTA 固件 */
export function updateOtaFirmware(data: IoTOtaFirmwareApi.Firmware) {
export function updateOtaFirmware(data: IoTOtaFirmware) {
return requestClient.put('/iot/ota/firmware/update', data);
}
@ -48,3 +65,26 @@ export function updateOtaFirmware(data: IoTOtaFirmwareApi.Firmware) {
export function deleteOtaFirmware(id: number) {
return requestClient.delete(`/iot/ota/firmware/delete?id=${id}`);
}
/** 批量删除 OTA 固件 */
export function deleteOtaFirmwareList(ids: number[]) {
return requestClient.delete('/iot/ota/firmware/delete-list', {
params: { ids: ids.join(',') },
});
}
/** 更新 OTA 固件状态 */
export function updateOtaFirmwareStatus(id: number, status: number) {
return requestClient.put(`/iot/ota/firmware/update-status`, {
id,
status,
});
}
/** 根据产品 ID 查询固件列表 */
export function getOtaFirmwareListByProductId(productId: number) {
return requestClient.get<IoTOtaFirmwareApi.Firmware[]>(
'/iot/ota/firmware/list-by-product-id',
{ params: { productId } },
);
}

View File

@ -3,21 +3,45 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace IoTOtaTaskApi {
/** IoT OTA 升级任务 */
/** IoT OTA 升级任务 VO */
export interface Task {
id?: number;
name?: string;
name: string;
description?: string;
firmwareId?: number;
status?: number;
firmwareId: number;
firmwareName?: string;
productId?: number;
productName?: string;
deviceScope?: number;
deviceIds?: number[];
deviceTotalCount?: number;
deviceSuccessCount?: number;
status?: number;
successCount?: number;
failureCount?: number;
pendingCount?: number;
createTime?: Date;
updateTime?: Date;
}
}
/** IoT OTA 升级任务 */
export interface OtaTask {
id?: number;
name?: string;
description?: string;
firmwareId?: number;
firmwareName?: string;
productId?: number;
productName?: string;
deviceScope?: number;
deviceIds?: number[];
status?: number;
successCount?: number;
failureCount?: number;
pendingCount?: number;
createTime?: Date;
updateTime?: Date;
}
/** 查询 OTA 升级任务分页 */
export function getOtaTaskPage(params: PageParam) {
return requestClient.get<PageResult<IoTOtaTaskApi.Task>>(
@ -32,11 +56,43 @@ export function getOtaTask(id: number) {
}
/** 新增 OTA 升级任务 */
export function createOtaTask(data: IoTOtaTaskApi.Task) {
export function createOtaTask(data: OtaTask) {
return requestClient.post('/iot/ota/task/create', data);
}
/** 修改 OTA 升级任务 */
export function updateOtaTask(data: OtaTask) {
return requestClient.put('/iot/ota/task/update', data);
}
/** 删除 OTA 升级任务 */
export function deleteOtaTask(id: number) {
return requestClient.delete(`/iot/ota/task/delete?id=${id}`);
}
/** 批量删除 OTA 升级任务 */
export function deleteOtaTaskList(ids: number[]) {
return requestClient.delete('/iot/ota/task/delete-list', {
params: { ids: ids.join(',') },
});
}
/** 取消 OTA 升级任务 */
export function cancelOtaTask(id: number) {
return requestClient.post(`/iot/ota/task/cancel?id=${id}`);
return requestClient.put(`/iot/ota/task/cancel?id=${id}`);
}
/** 启动 OTA 升级任务 */
export function startOtaTask(id: number) {
return requestClient.put(`/iot/ota/task/start?id=${id}`);
}
/** 暂停 OTA 升级任务 */
export function pauseOtaTask(id: number) {
return requestClient.put(`/iot/ota/task/pause?id=${id}`);
}
/** 恢复 OTA 升级任务 */
export function resumeOtaTask(id: number) {
return requestClient.put(`/iot/ota/task/resume?id=${id}`);
}

View File

@ -3,24 +3,44 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace IoTOtaTaskRecordApi {
/** IoT OTA 升级任务记录 */
/** IoT OTA 升级任务记录 VO */
export interface TaskRecord {
id?: number;
firmwareId?: number;
firmwareVersion?: string;
taskId?: number;
deviceId?: string;
taskId: number;
taskName?: string;
deviceId: number;
deviceName?: string;
currentVersion?: string;
fromFirmwareId?: number;
fromFirmwareVersion?: string;
firmwareId?: number;
firmwareName?: string;
firmwareVersion?: string;
status?: number;
progress?: number;
description?: string;
updateTime?: Date;
errorMessage?: string;
startTime?: Date;
endTime?: Date;
createTime?: Date;
}
}
// TODO @AI这里应该拿到 IoTOtaTaskRecordApi 里
/** IoT OTA 升级任务记录 */
export interface OtaTaskRecord {
id?: number;
taskId?: number;
taskName?: string;
deviceId?: number;
deviceName?: string;
firmwareId?: number;
firmwareName?: string;
firmwareVersion?: string;
status?: number;
progress?: number;
errorMessage?: string;
startTime?: Date;
endTime?: Date;
createTime?: Date;
}
/** 查询 OTA 升级任务记录分页 */
export function getOtaTaskRecordPage(params: PageParam) {
return requestClient.get<PageResult<IoTOtaTaskRecordApi.TaskRecord>>(
@ -29,12 +49,48 @@ export function getOtaTaskRecordPage(params: PageParam) {
);
}
/** 取消 OTA 升级任务记录 */
/** 查询 OTA 升级任务记录详情 */
export function getOtaTaskRecord(id: number) {
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord>(
`/iot/ota/task/record/get?id=${id}`,
);
}
/** 根据任务 ID 查询记录列表 */
export function getOtaTaskRecordListByTaskId(taskId: number) {
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord[]>(
'/iot/ota/task/record/list-by-task-id',
{ params: { taskId } },
);
}
/** 根据设备 ID 查询记录列表 */
export function getOtaTaskRecordListByDeviceId(deviceId: number) {
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord[]>(
'/iot/ota/task/record/list-by-device-id',
{ params: { deviceId } },
);
}
/** 根据固件 ID 查询记录列表 */
export function getOtaTaskRecordListByFirmwareId(firmwareId: number) {
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord[]>(
'/iot/ota/task/record/list-by-firmware-id',
{ params: { firmwareId } },
);
}
/** 重试升级任务记录 */
export function retryOtaTaskRecord(id: number) {
return requestClient.put(`/iot/ota/task/record/retry?id=${id}`);
}
/** 取消升级任务记录 */
export function cancelOtaTaskRecord(id: number) {
return requestClient.put(`/iot/ota/task/record/cancel?id=${id}`);
}
/** 获取 OTA 升级任务记录状态统计 */
/** 获取升级任务记录状态统计 */
export function getOtaTaskRecordStatusStatistics(
firmwareId?: number,
taskId?: number,

View File

@ -7,10 +7,11 @@ export namespace IotProductCategoryApi {
export interface ProductCategory {
id?: number; // 分类 ID
name: string; // 分类名称
parentId?: number; // 父级分类 ID
sort?: number; // 分类排序
status?: number; // 分类状态
description?: string; // 分类描述
createTime?: Date; // 创建时间
createTime?: string; // 创建时间
}
}

View File

@ -8,9 +8,8 @@ export namespace IotProductApi {
id?: number; // 产品编号
name: string; // 产品名称
productKey?: string; // 产品标识
productSecret?: string; // 产品密钥
protocolId?: number; // 协议编号
protocolType?: string; // 协议类型
protocolType?: number; // 接入协议类型
categoryId?: number; // 产品所属品类标识符
categoryName?: string; // 产品所属品类名称
icon?: string; // 产品图标
@ -18,33 +17,16 @@ export namespace IotProductApi {
description?: string; // 产品描述
status?: number; // 产品状态
deviceType?: number; // 设备类型
locationType?: number; // 定位类型
netType?: number; // 联网方式
serializeType?: string; // 序列化类型
registerEnabled?: boolean; // 是否开启动态注册
codecType?: string; // 数据格式(编解码器类型)
dataFormat?: number; // 数据格式
validateType?: number; // 认证方式
deviceCount?: number; // 设备数量
createTime?: Date; // 创建时间
}
}
// IoT 协议类型枚举
export enum ProtocolTypeEnum {
COAP = 'coap',
EMQX = 'emqx',
HTTP = 'http',
MODBUS_TCP_CLIENT = 'modbus_tcp_client',
MODBUS_TCP_SERVER = 'modbus_tcp_server',
MQTT = 'mqtt',
TCP = 'tcp',
UDP = 'udp',
WEBSOCKET = 'websocket',
}
// IoT 序列化类型枚举
export enum SerializeTypeEnum {
BINARY = 'binary',
JSON = 'json',
}
/** 查询产品分页 */
export function getProductPage(params: PageParam) {
return requestClient.get<PageResult<IotProductApi.Product>>(
@ -86,13 +68,8 @@ export function updateProductStatus(id: number, status: number) {
}
/** 查询产品(精简)列表 */
export function getSimpleProductList(deviceType?: number) {
return requestClient.get<IotProductApi.Product[]>(
'/iot/product/simple-list',
{
params: { deviceType },
},
);
export function getSimpleProductList() {
return requestClient.get<IotProductApi.Product[]>('/iot/product/simple-list');
}
/** 根据 ProductKey 获取产品信息 */
@ -101,10 +78,3 @@ export function getProductByKey(productKey: string) {
params: { productKey },
});
}
/** 同步产品物模型 TDengine 超级表结构 */
export function syncProductPropertyTable(productId: number) {
return requestClient.post(
`/iot/product/sync-property-table?productId=${productId}`,
);
}

View File

@ -3,21 +3,45 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace DataRuleApi {
/** IoT 数据流转规则 */
export interface DataRule {
/** IoT 数据流转规则 VO */
export interface Rule {
id?: number;
name?: string;
name: string;
description?: string;
status?: number;
sourceConfigs?: any[];
productId?: number;
productKey?: string;
sourceConfigs?: SourceConfig[];
sinkIds?: number[];
createTime?: Date;
}
/** IoT 数据源配置 */
export interface SourceConfig {
productId?: number;
productKey?: string;
deviceId?: number;
type?: string;
topic?: string;
}
}
/** IoT 数据流转规则 */
export interface DataRule {
id?: number;
name?: string;
description?: string;
status?: number;
productId?: number;
productKey?: string;
sourceConfigs?: any[];
sinkIds?: number[];
createTime?: Date;
}
/** 查询数据流转规则分页 */
export function getDataRulePage(params: PageParam) {
return requestClient.get<PageResult<DataRuleApi.DataRule>>(
return requestClient.get<PageResult<DataRuleApi.Rule>>(
'/iot/data-rule/page',
{ params },
);
@ -25,16 +49,16 @@ export function getDataRulePage(params: PageParam) {
/** 查询数据流转规则详情 */
export function getDataRule(id: number) {
return requestClient.get<DataRuleApi.DataRule>(`/iot/data-rule/get?id=${id}`);
return requestClient.get<DataRuleApi.Rule>(`/iot/data-rule/get?id=${id}`);
}
/** 新增数据流转规则 */
export function createDataRule(data: DataRuleApi.DataRule) {
export function createDataRule(data: DataRule) {
return requestClient.post('/iot/data-rule/create', data);
}
/** 修改数据流转规则 */
export function updateDataRule(data: DataRuleApi.DataRule) {
export function updateDataRule(data: DataRule) {
return requestClient.put('/iot/data-rule/update', data);
}
@ -42,3 +66,18 @@ export function updateDataRule(data: DataRuleApi.DataRule) {
export function deleteDataRule(id: number) {
return requestClient.delete(`/iot/data-rule/delete?id=${id}`);
}
/** 批量删除数据流转规则 */
export function deleteDataRuleList(ids: number[]) {
return requestClient.delete('/iot/data-rule/delete-list', {
params: { ids: ids.join(',') },
});
}
/** 更新数据流转规则状态 */
export function updateDataRuleStatus(id: number, status: number) {
return requestClient.put(`/iot/data-rule/update-status`, {
id,
status,
});
}

View File

@ -2,147 +2,101 @@ import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
interface BaseConfig {
type: string;
}
export namespace DataSinkApi {
/** IoT 数据流转目的 VO */
export interface DataSink {
export interface Sink {
id?: number;
name?: string;
name: string;
description?: string;
status?: number;
direction?: number;
type?: number;
config?:
| DatabaseConfig
| HttpConfig
| KafkaMQConfig
| MqttConfig
| RabbitMQConfig
| RedisStreamMQConfig
| RocketMQConfig
| TcpConfig
| WebSocketConfig;
type: string;
config?: any;
createTime?: Date;
}
/** HTTP 配置 */
export interface HttpConfig extends BaseConfig {
url: string;
method: string;
headers: Record<string, string>;
query: Record<string, string>;
body: string;
}
/** TCP 配置 */
export interface TcpConfig extends BaseConfig {
host: string;
port: number;
connectTimeoutMs: number;
readTimeoutMs: number;
ssl: boolean;
sslCertPath: string;
dataFormat: string;
heartbeatIntervalMs: number;
reconnectIntervalMs: number;
maxReconnectAttempts: number;
}
/** WebSocket 配置 */
export interface WebSocketConfig extends BaseConfig {
serverUrl: string;
connectTimeoutMs: number;
sendTimeoutMs: number;
heartbeatIntervalMs: number;
heartbeatMessage: string;
subprotocols: string;
customHeaders: string;
verifySslCert: boolean;
dataFormat: string;
reconnectIntervalMs: number;
maxReconnectAttempts: number;
enableCompression: boolean;
sendRetryCount: number;
sendRetryIntervalMs: number;
}
/** MQTT 配置 */
export interface MqttConfig extends BaseConfig {
url: string;
username: string;
password: string;
clientId: string;
topic: string;
}
/** Database 配置 */
export interface DatabaseConfig extends BaseConfig {
jdbcUrl: string;
username: string;
password: string;
tableName: string;
}
/** RocketMQ 配置 */
export interface RocketMQConfig extends BaseConfig {
nameServer: string;
accessKey: string;
secretKey: string;
group: string;
topic: string;
tags: string;
}
/** Kafka 配置 */
export interface KafkaMQConfig extends BaseConfig {
bootstrapServers: string;
username: string;
password: string;
ssl: boolean;
topic: string;
}
/** RabbitMQ 配置 */
export interface RabbitMQConfig extends BaseConfig {
host: string;
port: number;
virtualHost: string;
username: string;
password: string;
exchange: string;
routingKey: string;
queue: string;
}
/** Redis Stream MQ 配置 */
export interface RedisStreamMQConfig extends BaseConfig {
host: string;
port: number;
password: string;
database: number;
topic: string;
}
}
/** 数据流转目的类型 */
export const IotDataSinkTypeEnum = {
HTTP: 1,
TCP: 2,
WEBSOCKET: 3,
MQTT: 10,
DATABASE: 20,
REDIS_STREAM: 21,
ROCKETMQ: 30,
RABBITMQ: 31,
KAFKA: 32,
} as const;
/** IoT 数据流转目的 */
export interface DataSinkVO {
id?: number;
name?: string;
description?: string;
status?: number;
type?: string;
config?: any;
createTime?: Date;
}
/** IoT 数据目的类型枚举 */
export enum IotDataSinkTypeEnum {
HTTP = 'HTTP',
KAFKA = 'KAFKA',
MQTT = 'MQTT',
RABBITMQ = 'RABBITMQ',
REDIS_STREAM = 'REDIS_STREAM',
ROCKETMQ = 'ROCKETMQ',
}
/** HTTP 配置 */
export interface HttpConfig {
url?: string;
method?: string;
headers?: Record<string, string>;
timeout?: number;
}
/** MQTT 配置 */
export interface MqttConfig {
broker?: string;
port?: number;
topic?: string;
username?: string;
password?: string;
clientId?: string;
qos?: number;
}
/** Kafka 配置 */
export interface KafkaMQConfig {
bootstrapServers?: string;
topic?: string;
acks?: string;
retries?: number;
batchSize?: number;
}
/** RabbitMQ 配置 */
export interface RabbitMQConfig {
host?: string;
port?: number;
virtualHost?: string;
username?: string;
password?: string;
exchange?: string;
routingKey?: string;
queue?: string;
}
/** RocketMQ 配置 */
export interface RocketMQConfig {
nameServer?: string;
topic?: string;
tag?: string;
producerGroup?: string;
}
/** Redis Stream 配置 */
export interface RedisStreamMQConfig {
host?: string;
port?: number;
password?: string;
database?: number;
streamKey?: string;
maxLen?: number;
}
/** 查询数据流转目的分页 */
export function getDataSinkPage(params: PageParam) {
return requestClient.get<PageResult<DataSinkApi.DataSink>>(
return requestClient.get<PageResult<DataSinkApi.Sink>>(
'/iot/data-sink/page',
{ params },
);
@ -150,23 +104,26 @@ export function getDataSinkPage(params: PageParam) {
/** 查询数据流转目的详情 */
export function getDataSink(id: number) {
return requestClient.get<DataSinkApi.DataSink>(`/iot/data-sink/get?id=${id}`);
return requestClient.get<DataSinkApi.Sink>(`/iot/data-sink/get?id=${id}`);
}
/** 查询数据流转目的(精简)列表 */
/** 查询所有数据流转目的列表 */
export function getDataSinkList() {
return requestClient.get<DataSinkApi.Sink[]>('/iot/data-sink/list');
}
/** 查询数据流转目的简单列表 */
export function getDataSinkSimpleList() {
return requestClient.get<DataSinkApi.DataSink[]>(
'/iot/data-sink/simple-list',
);
return requestClient.get<DataSinkApi.Sink[]>('/iot/data-sink/simple-list');
}
/** 新增数据流转目的 */
export function createDataSink(data: DataSinkApi.DataSink) {
export function createDataSink(data: DataSinkVO) {
return requestClient.post('/iot/data-sink/create', data);
}
/** 修改数据流转目的 */
export function updateDataSink(data: DataSinkApi.DataSink) {
export function updateDataSink(data: DataSinkVO) {
return requestClient.put('/iot/data-sink/update', data);
}
@ -174,3 +131,18 @@ export function updateDataSink(data: DataSinkApi.DataSink) {
export function deleteDataSink(id: number) {
return requestClient.delete(`/iot/data-sink/delete?id=${id}`);
}
/** 批量删除数据流转目的 */
export function deleteDataSinkList(ids: number[]) {
return requestClient.delete('/iot/data-sink/delete-list', {
params: { ids: ids.join(',') },
});
}
/** 更新数据流转目的状态 */
export function updateDataSinkStatus(id: number, status: number) {
return requestClient.put(`/iot/data-sink/update-status`, {
id,
status,
});
}

View File

@ -11,20 +11,25 @@ export namespace RuleSceneApi {
status?: number;
triggers?: Trigger[];
actions?: Action[];
lastTriggerTime?: Date;
createTime?: Date;
}
/** 场景联动规则的触发器 */
export interface Trigger {
type?: number;
type?: string;
productId?: number;
deviceId?: number;
identifier?: string;
operator?: string;
value?: any;
cronExpression?: string;
conditionGroups?: TriggerCondition[][]; // 后端结构List<List<TriggerCondition>>;外层「或」、组内「且」
conditionGroups?: TriggerConditionGroup[];
}
/** 场景联动规则的触发条件组 */
export interface TriggerConditionGroup {
conditions?: TriggerCondition[];
operator?: string;
}
/** 场景联动规则的触发条件 */
@ -34,22 +39,72 @@ export namespace RuleSceneApi {
identifier?: string;
operator?: string;
value?: any;
type?: number;
param?: string;
type?: string;
}
/** 场景联动规则的动作 */
export interface Action {
type?: number;
type?: string;
productId?: number;
deviceId?: number;
identifier?: string;
value?: any;
alertConfigId?: number;
params?: string;
}
}
// TODO @haohao貌似下面的和 RuleSceneApi 重复了。
/** IoT 场景联动规则 */
export interface IotSceneRule {
id?: number;
name?: string;
description?: string;
status?: number;
triggers?: Trigger[];
actions?: Action[];
createTime?: Date;
}
/** IoT 场景联动规则触发器 */
export interface Trigger {
type?: string;
productId?: number;
deviceId?: number;
identifier?: string;
operator?: string;
value?: any;
cronExpression?: string;
conditionGroups?: TriggerConditionGroup[];
}
/** IoT 场景联动规则触发条件组 */
export interface TriggerConditionGroup {
conditions?: TriggerCondition[];
operator?: string;
}
/** IoT 场景联动规则触发条件 */
export interface TriggerCondition {
productId?: number;
deviceId?: number;
identifier?: string;
operator?: string;
value?: any;
type?: string;
param?: string;
}
/** IoT 场景联动规则动作 */
export interface Action {
type?: string;
productId?: number;
deviceId?: number;
identifier?: string;
value?: any;
alertConfigId?: number;
params?: string;
}
/** 查询场景联动规则分页 */
export function getSceneRulePage(params: PageParam) {
return requestClient.get<PageResult<RuleSceneApi.SceneRule>>(
@ -66,12 +121,12 @@ export function getSceneRule(id: number) {
}
/** 新增场景联动规则 */
export function createSceneRule(data: RuleSceneApi.SceneRule) {
export function createSceneRule(data: IotSceneRule) {
return requestClient.post('/iot/scene-rule/create', data);
}
/** 修改场景联动规则 */
export function updateSceneRule(data: RuleSceneApi.SceneRule) {
export function updateSceneRule(data: IotSceneRule) {
return requestClient.put('/iot/scene-rule/update', data);
}
@ -80,6 +135,14 @@ export function deleteSceneRule(id: number) {
return requestClient.delete(`/iot/scene-rule/delete?id=${id}`);
}
/** 批量删除场景联动规则 */
// TODO @haohao貌似用上。
export function deleteSceneRuleList(ids: number[]) {
return requestClient.delete('/iot/scene-rule/delete-list', {
params: { ids: ids.join(',') },
});
}
/** 更新场景联动规则状态 */
export function updateSceneRuleStatus(id: number, status: number) {
return requestClient.put(`/iot/scene-rule/update-status`, {

View File

@ -17,6 +17,18 @@ export namespace IotStatisticsApi {
productCategoryDeviceCounts: Record<string, number>; // 按品类统计的设备数量
}
/** 时间戳-数值的键值对类型 */
export interface TimeValueItem {
[key: string]: number;
}
/** 消息统计数据类型 */
export interface DeviceMessageSummary {
statType: number;
upstreamCounts: TimeValueItem[];
downstreamCounts: TimeValueItem[];
}
/** 设备消息数量统计(按日期) */
export interface DeviceMessageSummaryByDateRespVO {
time: string; // 时间轴

View File

@ -1,209 +1,126 @@
import type { Rule } from 'ant-design-vue/es/form';
import type { PageParam, PageResult } from '@vben/request';
import { isEmpty } from '@vben/utils';
import { requestClient } from '#/api/request';
export namespace ThingModelApi {
/** IoT 物模型数据 */
/** IoT 物模型数据 VO */
export interface ThingModel {
id?: number;
productId?: number;
productKey?: string;
identifier?: string;
name?: string;
description?: string;
dataType?: string;
type?: number; // 参见 IoTThingModelTypeEnum 枚举类
property?: Property;
event?: Event;
service?: Service;
identifier: string;
name: string;
desc?: string;
type: string;
property?: ThingModelProperty;
event?: ThingModelEvent;
service?: ThingModelService;
}
/** IoT 物模型属性 */
export interface Property {
identifier?: string;
name?: string;
accessMode?: string;
required?: boolean;
dataType?: string;
description?: string;
identifier: string;
name: string;
accessMode: string;
dataType: string;
dataSpecs?: any;
dataSpecsList?: any[];
desc?: string;
}
/** IoT 物模型服务 */
export interface Service {
identifier?: string;
name?: string;
required?: boolean;
callType?: string;
description?: string;
inputParams?: Param[];
outputParams?: Param[];
method?: string;
identifier: string;
name: string;
callType: string;
inputData?: any[];
outputData?: any[];
desc?: string;
}
/** IoT 物模型事件 */
export interface Event {
identifier?: string;
name?: string;
required?: boolean;
type?: string;
description?: string;
outputParams?: Param[];
method?: string;
}
/** IoT 物模型参数 */
export interface Param {
identifier?: string;
name?: string;
direction?: string;
paraOrder?: number;
dataType?: string;
dataSpecs?: any;
dataSpecsList?: any[];
}
/** IoT 物模型 TSL树形响应 */
export interface ThingModelTSL {
productId?: number;
productKey?: string;
properties?: Property[];
events?: Event[];
services?: Service[];
}
/** IoT 数据定义(数值型) */
export interface DataSpecsNumberData {
min?: number | string;
max?: number | string;
step?: number | string;
unit?: string;
unitName?: string;
}
/** IoT 数据定义(枚举/布尔型) */
export interface DataSpecsEnumOrBoolData {
value: number | string;
identifier: string;
name: string;
type: string;
outputData?: any[];
desc?: string;
}
}
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
function buildRequiredNumberValidator(label: string) {
return (_rule: any, value: any, callback: any) => {
if (isEmpty(value)) {
callback(new Error(`${label}不能为空`));
return;
}
if (Number.isNaN(Number(value))) {
callback(new Error(`${label}必须是数字`));
return;
}
callback();
};
/** IoT 物模型数据 */
export interface ThingModelData {
id?: number;
productId?: number;
productKey?: string;
identifier?: string;
name?: string;
desc?: string;
type?: string;
dataType?: string;
property?: ThingModelProperty;
event?: ThingModelEvent;
service?: ThingModelService;
}
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
export function buildIdentifierLikeNameValidator(label: string) {
return (_rule: any, value: string, callback: any) => {
if (isEmpty(value)) {
callback(new Error(`${label}不能为空`));
return;
}
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
callback(new Error(`${label}必须以中文、英文字母或数字开头`));
return;
}
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
callback(
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
);
return;
}
if (value.length > 20) {
callback(new Error(`${label}长度不能超过 20 个字符`));
return;
}
callback();
};
/** IoT 物模型属性 */
export interface ThingModelProperty {
identifier?: string;
name?: string;
accessMode?: string;
dataType?: string;
dataSpecs?: any;
dataSpecsList?: any[];
desc?: string;
}
/** IoT 物模型服务 */
export interface ThingModelService {
identifier?: string;
name?: string;
callType?: string;
inputData?: any[];
outputData?: any[];
desc?: string;
}
/** IoT 物模型事件 */
export interface ThingModelEvent {
identifier?: string;
name?: string;
type?: string;
outputData?: any[];
desc?: string;
}
/** IoT 数据定义(数值型) */
export interface DataSpecsNumberData {
min?: number | string;
max?: number | string;
step?: number | string;
unit?: string;
unitName?: string;
}
/** IoT 数据定义(枚举/布尔型) */
export interface DataSpecsEnumOrBoolData {
value: number | string;
name: string;
}
/** IoT 物模型表单校验规则 */
export const ThingModelFormRules: Record<string, Rule[]> = {
name: [
{ required: true, message: '功能名称不能为空', trigger: 'blur' },
{
pattern: /^[一-龥A-Za-z0-9][一-龥A-Za-z0-9\-_/.]{0,29}$/,
message:
'支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点,必须以中文、英文或数字开头,不超过 30 个字符',
trigger: 'blur',
},
],
type: [{ required: true, message: '功能类型不能为空', trigger: 'blur' }],
identifier: [
{ required: true, message: '标识符不能为空', trigger: 'blur' },
{
pattern: /^[a-zA-Z][a-zA-Z0-9_]{0,31}$/,
message: '支持大小写字母、数字和下划线,必须以字母开头,不超过 32 个字符',
trigger: 'blur',
},
{
validator: (_rule: any, value: string, callback: any) => {
const reservedKeywords = [
'set',
'get',
'post',
'property',
'event',
'time',
'value',
];
if (reservedKeywords.includes(value)) {
callback(
new Error(
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
),
);
return;
}
if (/^\d+$/.test(value)) {
callback(new Error('标识符不能是纯数字'));
return;
}
callback();
},
trigger: 'blur',
},
],
childDataType: [{ required: true, message: '元素类型不能为空' }],
size: [
{
required: true,
validator: buildRequiredNumberValidator('元素个数'),
trigger: 'blur',
},
],
length: [
{
required: true,
validator: buildRequiredNumberValidator('文本长度'),
trigger: 'blur',
},
],
accessMode: [
{ required: true, message: '请选择读写类型', trigger: 'change' },
],
callType: [{ required: true, message: '请选择调用方式', trigger: 'change' }],
eventType: [{ required: true, message: '请选择事件类型', trigger: 'change' }],
};
export interface ThingModelFormRules {
[key: string]: any;
}
/** 校验布尔值名称 */
export const validateBoolName = buildIdentifierLikeNameValidator('布尔值名称');
/** 验证布尔型名称 */
export function validateBoolName(_rule: any, value: any, callback: any) {
if (value) {
callback();
} else {
callback(new Error('枚举描述不能为空'));
}
}
/** 查询产品物模型分页 */
export function getThingModelPage(params: PageParam) {
@ -224,19 +141,17 @@ export function getThingModel(id: number) {
export function getThingModelListByProductId(productId: number) {
return requestClient.get<ThingModelApi.ThingModel[]>(
'/iot/thing-model/list',
{
params: { productId },
},
{ params: { productId } },
);
}
/** 新增物模型 */
export function createThingModel(data: ThingModelApi.ThingModel) {
export function createThingModel(data: ThingModelData) {
return requestClient.post('/iot/thing-model/create', data);
}
/** 修改物模型 */
export function updateThingModel(data: ThingModelApi.ThingModel) {
export function updateThingModel(data: ThingModelData) {
return requestClient.put('/iot/thing-model/update', data);
}
@ -246,11 +161,26 @@ export function deleteThingModel(id: number) {
}
/** 获取物模型 TSL */
export function getThingModelTSLByProductId(productId: number) {
return requestClient.get<ThingModelApi.ThingModelTSL>(
export function getThingModelTSL(productId: number) {
return requestClient.get<ThingModelApi.ThingModel[]>(
'/iot/thing-model/get-tsl',
{
params: { productId },
},
{ params: { productId } },
);
}
/** TSL
export function importThingModelTSL(productId: number, tslData: any) {
return requestClient.post('/iot/thing-model/import-tsl', {
productId,
tslData,
});
}
*/
/** TSL
export function exportThingModelTSL(productId: number) {
return requestClient.get<any>('/iot/thing-model/export-tsl', {
params: { productId },
});
}
*/

View File

@ -7,7 +7,7 @@ import { requestClient } from '#/api/request';
export namespace MallTradeStatisticsApi {
/** 交易状况 Request */
export interface TradeTrendReqVO {
times?: string[];
times: [Date, Date];
}
/** 交易统计 Response */

View File

@ -13,7 +13,6 @@ export namespace MemberUserApi {
loginIp: string;
mark: string;
mobile: string;
email?: string;
name?: string;
nickname?: string;
registerIp: string;

View File

@ -1,27 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesCalCalendarApi {
/** 排班日历班组排班项 */
export interface CalendarTeamShiftItem {
teamId?: number; // 班组编号
teamName?: string; // 班组名称
shiftId?: number; // 班次编号
shiftName?: string; // 班次名称
sort?: number; // 排序
}
/** 排班日历天 */
export interface CalendarDay {
day?: string; // 日期
shiftType?: number; // 轮班方式
teamShifts?: CalendarTeamShiftItem[]; // 班组班次
}
}
/** 查询排班日历列表 */
export function getCalendarList(params: any) {
return requestClient.get<MesCalCalendarApi.CalendarDay[]>(
'/mes/cal/calendar/list',
{ params },
);
}

View File

@ -1,39 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesCalHolidayApi {
/** MES 假期设置 */
export interface Holiday {
id?: number; // 编号
day?: number | string; // 日期
type?: number; // 日期类型
remark?: string; // 备注
createTime?: Date; // 创建时间
}
/** 假期查询参数 */
export interface HolidayQuery {
startDay?: string;
endDay?: string;
}
}
/** 查询假期设置列表 */
export function getHolidayList(params?: MesCalHolidayApi.HolidayQuery) {
return requestClient.get<MesCalHolidayApi.Holiday[]>(
'/mes/cal/holiday/list',
{ params },
);
}
/** 根据日期查询假期设置 */
export function getHolidayByDay(day: string) {
return requestClient.get<MesCalHolidayApi.Holiday>(
'/mes/cal/holiday/get-by-day',
{ params: { day } },
);
}
/** 保存假期设置 */
export function saveHoliday(data: MesCalHolidayApi.Holiday) {
return requestClient.post('/mes/cal/holiday/save', data);
}

View File

@ -1,59 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesCalPlanApi {
/** MES 排班计划 */
export interface Plan {
id?: number; // 计划编号
code?: string; // 计划编码
name?: string; // 计划名称
calendarType?: number; // 班组类型
startDate?: number; // 开始日期
endDate?: number; // 结束日期
shiftType?: number; // 轮班方式
shiftMethod?: number; // 倒班方式
shiftCount?: number; // 倒班天数
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询排班计划分页 */
export function getPlanPage(params: PageParam) {
return requestClient.get<PageResult<MesCalPlanApi.Plan>>(
'/mes/cal/plan/page',
{ params },
);
}
/** 查询排班计划详情 */
export function getPlan(id: number) {
return requestClient.get<MesCalPlanApi.Plan>(`/mes/cal/plan/get?id=${id}`);
}
/** 新增排班计划 */
export function createPlan(data: MesCalPlanApi.Plan) {
return requestClient.post<number>('/mes/cal/plan/create', data);
}
/** 修改排班计划 */
export function updatePlan(data: MesCalPlanApi.Plan) {
return requestClient.put('/mes/cal/plan/update', data);
}
/** 确认排班计划 */
export function confirmPlan(id: number) {
return requestClient.put(`/mes/cal/plan/confirm?id=${id}`);
}
/** 删除排班计划 */
export function deletePlan(id: number) {
return requestClient.delete(`/mes/cal/plan/delete?id=${id}`);
}
/** 导出排班计划 */
export function exportPlan(params: any) {
return requestClient.download('/mes/cal/plan/export-excel', { params });
}

View File

@ -1,36 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesCalPlanShiftApi {
/** MES 计划班次 */
export interface PlanShift {
id?: number; // 班次编号
planId?: number; // 排班计划编号
sort?: number; // 显示顺序
name?: string; // 班次名称
startTime?: string; // 开始时间
endTime?: string; // 结束时间
remark?: string; // 备注
}
}
/** 查询指定排班计划的班次列表 */
export function getPlanShiftListByPlan(planId: number) {
return requestClient.get<MesCalPlanShiftApi.PlanShift[]>(
`/mes/cal/plan-shift/list-by-plan?planId=${planId}`,
);
}
/** 新增计划班次 */
export function createPlanShift(data: MesCalPlanShiftApi.PlanShift) {
return requestClient.post('/mes/cal/plan-shift/create', data);
}
/** 修改计划班次 */
export function updatePlanShift(data: MesCalPlanShiftApi.PlanShift) {
return requestClient.put('/mes/cal/plan-shift/update', data);
}
/** 删除计划班次 */
export function deletePlanShift(id: number) {
return requestClient.delete(`/mes/cal/plan-shift/delete?id=${id}`);
}

View File

@ -1,30 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesCalPlanTeamApi {
/** MES 计划班组关联 */
export interface PlanTeam {
id?: number; // 关联编号
planId?: number; // 排班计划编号
teamId?: number; // 班组编号
teamCode?: string; // 班组编码
teamName?: string; // 班组名称
remark?: string; // 备注
}
}
/** 查询指定排班计划的班组列表 */
export function getPlanTeamListByPlan(planId: number) {
return requestClient.get<MesCalPlanTeamApi.PlanTeam[]>(
`/mes/cal/plan-team/list-by-plan?planId=${planId}`,
);
}
/** 新增计划班组关联 */
export function createPlanTeam(data: MesCalPlanTeamApi.PlanTeam) {
return requestClient.post('/mes/cal/plan-team/create', data);
}
/** 删除计划班组关联 */
export function deletePlanTeam(id: number) {
return requestClient.delete(`/mes/cal/plan-team/delete?id=${id}`);
}

View File

@ -1,53 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesCalTeamApi {
/** MES 班组 */
export interface Team {
id?: number; // 班组编号
code?: string; // 班组编码
name?: string; // 班组名称
calendarType?: number; // 班组类型
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询班组分页 */
export function getTeamPage(params: PageParam) {
return requestClient.get<PageResult<MesCalTeamApi.Team>>(
'/mes/cal/team/page',
{ params },
);
}
/** 查询班组列表 */
export function getTeamList() {
return requestClient.get<MesCalTeamApi.Team[]>('/mes/cal/team/list');
}
/** 查询班组详情 */
export function getTeam(id: number) {
return requestClient.get<MesCalTeamApi.Team>(`/mes/cal/team/get?id=${id}`);
}
/** 新增班组 */
export function createTeam(data: MesCalTeamApi.Team) {
return requestClient.post('/mes/cal/team/create', data);
}
/** 修改班组 */
export function updateTeam(data: MesCalTeamApi.Team) {
return requestClient.put('/mes/cal/team/update', data);
}
/** 删除班组 */
export function deleteTeam(id: number) {
return requestClient.delete(`/mes/cal/team/delete?id=${id}`);
}
/** 导出班组 */
export function exportTeam(params: any) {
return requestClient.download('/mes/cal/team/export-excel', { params });
}

View File

@ -1,51 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesCalTeamMemberApi {
/** MES 班组成员 */
export interface TeamMember {
id?: number; // 成员编号
teamId?: number; // 班组编号
userId?: number; // 用户编号
nickname?: string; // 用户昵称
telephone?: string; // 用户手机号
remark?: string; // 备注
}
}
/** 创建班组成员 */
export function createTeamMember(data: MesCalTeamMemberApi.TeamMember) {
return requestClient.post('/mes/cal/team-member/create', data);
}
/** 删除班组成员 */
export function deleteTeamMember(id: number) {
return requestClient.delete(`/mes/cal/team-member/delete?id=${id}`);
}
/** 查询班组成员分页 */
export function getTeamMemberPage(params: PageParam) {
return requestClient.get<PageResult<MesCalTeamMemberApi.TeamMember>>(
'/mes/cal/team-member/page',
{ params },
);
}
/** 查询指定班组的成员列表 */
export function getTeamMemberListByTeam(teamId: number) {
return requestClient.get<MesCalTeamMemberApi.TeamMember[]>(
'/mes/cal/team-member/list-by-team',
{ params: { teamId } },
);
}
/** 查询多个班组的成员列表 */
export function getTeamMemberListByTeamIds(teamIds: number[]) {
return requestClient.get<MesCalTeamMemberApi.TeamMember[]>(
'/mes/cal/team-member/list-by-team',
{
params: { teamIds: teamIds.join(',') },
},
);
}

View File

@ -1,65 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvCheckPlanApi {
/** MES 点检保养方案 */
export interface CheckPlan {
id?: number; // 方案编号
code?: string; // 方案编码
name?: string; // 方案名称
type?: number; // 方案类型
startDate?: Date | number; // 开始日期
endDate?: Date | number; // 结束日期
cycleType?: number; // 周期类型
cycleCount?: number; // 周期数量
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询点检保养方案分页 */
export function getCheckPlanPage(params: PageParam) {
return requestClient.get<PageResult<MesDvCheckPlanApi.CheckPlan>>(
'/mes/dv/check-plan/page',
{ params },
);
}
/** 查询点检保养方案详情 */
export function getCheckPlan(id: number) {
return requestClient.get<MesDvCheckPlanApi.CheckPlan>(
`/mes/dv/check-plan/get?id=${id}`,
);
}
/** 新增点检保养方案 */
export function createCheckPlan(data: MesDvCheckPlanApi.CheckPlan) {
return requestClient.post<number>('/mes/dv/check-plan/create', data);
}
/** 修改点检保养方案 */
export function updateCheckPlan(data: MesDvCheckPlanApi.CheckPlan) {
return requestClient.put('/mes/dv/check-plan/update', data);
}
/** 启用点检保养方案 */
export function enableCheckPlan(id: number) {
return requestClient.put(`/mes/dv/check-plan/enable?id=${id}`);
}
/** 停用点检保养方案 */
export function disableCheckPlan(id: number) {
return requestClient.put(`/mes/dv/check-plan/disable?id=${id}`);
}
/** 删除点检保养方案 */
export function deleteCheckPlan(id: number) {
return requestClient.delete(`/mes/dv/check-plan/delete?id=${id}`);
}
/** 导出点检保养方案 */
export function exportCheckPlan(params: any) {
return requestClient.download('/mes/dv/check-plan/export-excel', { params });
}

View File

@ -1,34 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesDvCheckPlanMachineryApi {
/** MES 点检保养方案设备 */
export interface CheckPlanMachinery {
id?: number; // 关联编号
planId?: number; // 方案编号
machineryId?: number; // 设备编号
machineryCode?: string; // 设备编码
machineryName?: string; // 设备名称
machineryBrand?: string; // 品牌
machinerySpecification?: string; // 规格型号
remark?: string; // 备注
}
}
/** 查询指定方案的设备列表 */
export function getCheckPlanMachineryListByPlan(planId: number) {
return requestClient.get<MesDvCheckPlanMachineryApi.CheckPlanMachinery[]>(
`/mes/dv/check-plan-machinery/list-by-plan?planId=${planId}`,
);
}
/** 新增方案设备关联 */
export function createCheckPlanMachinery(
data: MesDvCheckPlanMachineryApi.CheckPlanMachinery,
) {
return requestClient.post('/mes/dv/check-plan-machinery/create', data);
}
/** 删除方案设备关联 */
export function deleteCheckPlanMachinery(id: number) {
return requestClient.delete(`/mes/dv/check-plan-machinery/delete?id=${id}`);
}

View File

@ -1,35 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesDvCheckPlanSubjectApi {
/** MES 点检保养方案项目 */
export interface CheckPlanSubject {
id?: number; // 关联编号
planId?: number; // 方案编号
subjectId?: number; // 项目编号
subjectCode?: string; // 项目编码
subjectName?: string; // 项目名称
subjectType?: number; // 项目类型
subjectContent?: string; // 项目内容
subjectStandard?: string; // 标准
remark?: string; // 备注
}
}
/** 查询指定方案的项目列表 */
export function getCheckPlanSubjectListByPlan(planId: number) {
return requestClient.get<MesDvCheckPlanSubjectApi.CheckPlanSubject[]>(
`/mes/dv/check-plan-subject/list-by-plan?planId=${planId}`,
);
}
/** 新增方案项目关联 */
export function createCheckPlanSubject(
data: MesDvCheckPlanSubjectApi.CheckPlanSubject,
) {
return requestClient.post('/mes/dv/check-plan-subject/create', data);
}
/** 删除方案项目关联 */
export function deleteCheckPlanSubject(id: number) {
return requestClient.delete(`/mes/dv/check-plan-subject/delete?id=${id}`);
}

View File

@ -1,65 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvCheckRecordApi {
/** MES 设备点检记录 */
export interface CheckRecord {
id?: number; // 记录编号
planId?: number; // 点检计划编号
planName?: string; // 计划名称
machineryId?: number; // 设备编号
machineryCode?: string; // 设备编码
machineryName?: string; // 设备名称
machineryBrand?: string; // 品牌
machinerySpecification?: string; // 规格型号
checkTime?: Date | number; // 点检时间
userId?: number; // 点检人编号
nickname?: string; // 点检人名称
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询设备点检记录分页 */
export function getCheckRecordPage(params: PageParam) {
return requestClient.get<PageResult<MesDvCheckRecordApi.CheckRecord>>(
'/mes/dv/check-record/page',
{ params },
);
}
/** 查询设备点检记录详情 */
export function getCheckRecord(id: number) {
return requestClient.get<MesDvCheckRecordApi.CheckRecord>(
`/mes/dv/check-record/get?id=${id}`,
);
}
/** 新增设备点检记录 */
export function createCheckRecord(data: MesDvCheckRecordApi.CheckRecord) {
return requestClient.post<number>('/mes/dv/check-record/create', data);
}
/** 修改设备点检记录 */
export function updateCheckRecord(data: MesDvCheckRecordApi.CheckRecord) {
return requestClient.put('/mes/dv/check-record/update', data);
}
/** 提交设备点检记录 */
export function submitCheckRecord(id: number) {
return requestClient.put(`/mes/dv/check-record/submit?id=${id}`);
}
/** 删除设备点检记录 */
export function deleteCheckRecord(id: number) {
return requestClient.delete(`/mes/dv/check-record/delete?id=${id}`);
}
/** 导出设备点检记录 */
export function exportCheckRecord(params: any) {
return requestClient.download('/mes/dv/check-record/export-excel', {
params,
});
}

View File

@ -1,53 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvCheckRecordLineApi {
/** MES 设备点检记录明细 */
export interface CheckRecordLine {
id?: number; // 明细编号
recordId?: number; // 点检记录编号
subjectId?: number; // 点检项目编号
subjectCode?: string; // 项目编码
subjectName?: string; // 项目名称
subjectContent?: string; // 检查内容
subjectStandard?: string; // 检查标准
checkStatus?: number; // 点检结果
checkResult?: string; // 异常描述
remark?: string; // 备注
}
}
/** 查询设备点检记录明细分页 */
export function getCheckRecordLinePage(params: PageParam) {
return requestClient.get<PageResult<MesDvCheckRecordLineApi.CheckRecordLine>>(
'/mes/dv/check-record-line/page',
{ params },
);
}
/** 查询设备点检记录明细详情 */
export function getCheckRecordLine(id: number) {
return requestClient.get<MesDvCheckRecordLineApi.CheckRecordLine>(
`/mes/dv/check-record-line/get?id=${id}`,
);
}
/** 新增设备点检记录明细 */
export function createCheckRecordLine(
data: MesDvCheckRecordLineApi.CheckRecordLine,
) {
return requestClient.post('/mes/dv/check-record-line/create', data);
}
/** 修改设备点检记录明细 */
export function updateCheckRecordLine(
data: MesDvCheckRecordLineApi.CheckRecordLine,
) {
return requestClient.put('/mes/dv/check-record-line/update', data);
}
/** 删除设备点检记录明细 */
export function deleteCheckRecordLine(id: number) {
return requestClient.delete(`/mes/dv/check-record-line/delete?id=${id}`);
}

View File

@ -1,85 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvMachineryApi {
/** MES 设备台账 */
export interface Machinery {
id?: number; // 设备编号
code?: string; // 设备编码
name?: string; // 设备名称
brand?: string; // 品牌
specification?: string; // 规格型号
machineryTypeId?: number; // 设备类型编号
machineryTypeName?: string; // 设备类型名称
workshopId?: number; // 所属车间编号
workshopName?: string; // 所属车间名称
status?: number; // 设备状态
lastMaintenTime?: Date; // 最近保养时间
lastCheckTime?: Date; // 最近点检时间
remark?: string; // 备注
createTime?: Date; // 创建时间
}
/** 设备导入结果 */
export interface MachineryImportRespVO {
createCodes?: string[]; // 新增成功的设备编码
updateCodes?: string[]; // 更新成功的设备编码
failureCodes?: Record<string, string>; // 导入失败的设备编码及原因
}
}
/** 查询设备分页 */
export function getMachineryPage(params: PageParam) {
return requestClient.get<PageResult<MesDvMachineryApi.Machinery>>(
'/mes/dv/machinery/page',
{ params },
);
}
/** 查询设备精简列表 */
export function getMachinerySimpleList() {
return requestClient.get<MesDvMachineryApi.Machinery[]>(
'/mes/dv/machinery/simple-list',
);
}
/** 查询设备详情 */
export function getMachinery(id: number) {
return requestClient.get<MesDvMachineryApi.Machinery>(
`/mes/dv/machinery/get?id=${id}`,
);
}
/** 新增设备 */
export function createMachinery(data: MesDvMachineryApi.Machinery) {
return requestClient.post('/mes/dv/machinery/create', data);
}
/** 修改设备 */
export function updateMachinery(data: MesDvMachineryApi.Machinery) {
return requestClient.put('/mes/dv/machinery/update', data);
}
/** 删除设备 */
export function deleteMachinery(id: number) {
return requestClient.delete(`/mes/dv/machinery/delete?id=${id}`);
}
/** 导出设备 */
export function exportMachinery(params: any) {
return requestClient.download('/mes/dv/machinery/export-excel', { params });
}
/** 下载设备导入模板 */
export function importMachineryTemplate() {
return requestClient.download('/mes/dv/machinery/get-import-template');
}
/** 导入设备 */
export function importMachinery(file: File, updateSupport: boolean) {
return requestClient.upload<MesDvMachineryApi.MachineryImportRespVO>(
`/mes/dv/machinery/import?updateSupport=${updateSupport}`,
{ file },
);
}

View File

@ -1,53 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesDvMachineryTypeApi {
/** MES 设备类型 */
export interface MachineryType {
id?: number; // 设备类型编号
parentId?: number; // 父类型编号
code?: string; // 类型编码
name?: string; // 类型名称
sort?: number; // 显示排序
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
children?: MachineryType[]; // 子类型
}
}
/** 查询设备类型列表 */
export function getMachineryTypeList(params?: any) {
return requestClient.get<MesDvMachineryTypeApi.MachineryType[]>(
'/mes/dv/machinery-type/list',
{ params },
);
}
/** 查询设备类型精简列表 */
export function getMachineryTypeSimpleList() {
return requestClient.get<MesDvMachineryTypeApi.MachineryType[]>(
'/mes/dv/machinery-type/simple-list',
);
}
/** 查询设备类型详情 */
export function getMachineryType(id: number) {
return requestClient.get<MesDvMachineryTypeApi.MachineryType>(
`/mes/dv/machinery-type/get?id=${id}`,
);
}
/** 新增设备类型 */
export function createMachineryType(data: MesDvMachineryTypeApi.MachineryType) {
return requestClient.post('/mes/dv/machinery-type/create', data);
}
/** 修改设备类型 */
export function updateMachineryType(data: MesDvMachineryTypeApi.MachineryType) {
return requestClient.put('/mes/dv/machinery-type/update', data);
}
/** 删除设备类型 */
export function deleteMachineryType(id: number) {
return requestClient.delete(`/mes/dv/machinery-type/delete?id=${id}`);
}

View File

@ -1,65 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvMaintenRecordApi {
/** MES 设备保养记录 */
export interface MaintenRecord {
id?: number; // 记录编号
planId?: number; // 计划编号
planName?: string; // 计划名称
machineryId?: number; // 设备编号
machineryCode?: string; // 设备编码
machineryName?: string; // 设备名称
machineryBrand?: string; // 品牌
machinerySpecification?: string; // 规格型号
maintenTime?: Date | number; // 保养时间
userId?: number; // 用户编号
nickname?: string; // 保养人名称
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询设备保养记录分页 */
export function getMaintenRecordPage(params: PageParam) {
return requestClient.get<PageResult<MesDvMaintenRecordApi.MaintenRecord>>(
'/mes/dv/mainten-record/page',
{ params },
);
}
/** 查询设备保养记录详情 */
export function getMaintenRecord(id: number) {
return requestClient.get<MesDvMaintenRecordApi.MaintenRecord>(
`/mes/dv/mainten-record/get?id=${id}`,
);
}
/** 新增设备保养记录 */
export function createMaintenRecord(data: MesDvMaintenRecordApi.MaintenRecord) {
return requestClient.post<number>('/mes/dv/mainten-record/create', data);
}
/** 修改设备保养记录 */
export function updateMaintenRecord(data: MesDvMaintenRecordApi.MaintenRecord) {
return requestClient.put('/mes/dv/mainten-record/update', data);
}
/** 提交设备保养记录 */
export function submitMaintenRecord(id: number) {
return requestClient.put(`/mes/dv/mainten-record/submit?id=${id}`);
}
/** 删除设备保养记录 */
export function deleteMaintenRecord(id: number) {
return requestClient.delete(`/mes/dv/mainten-record/delete?id=${id}`);
}
/** 导出设备保养记录 */
export function exportMaintenRecord(params: any) {
return requestClient.download('/mes/dv/mainten-record/export-excel', {
params,
});
}

View File

@ -1,51 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvMaintenRecordLineApi {
/** MES 设备保养记录明细 */
export interface MaintenRecordLine {
id?: number; // 明细编号
recordId?: number; // 保养记录编号
subjectId?: number; // 项目编号
subjectName?: string; // 项目名称
subjectContent?: string; // 项目内容
subjectStandard?: string; // 项目标准
status?: number; // 保养结果
result?: string; // 异常描述
remark?: string; // 备注
}
}
/** 查询设备保养记录明细分页 */
export function getMaintenRecordLinePage(params: PageParam) {
return requestClient.get<
PageResult<MesDvMaintenRecordLineApi.MaintenRecordLine>
>('/mes/dv/mainten-record-line/page', { params });
}
/** 查询设备保养记录明细详情 */
export function getMaintenRecordLine(id: number) {
return requestClient.get<MesDvMaintenRecordLineApi.MaintenRecordLine>(
`/mes/dv/mainten-record-line/get?id=${id}`,
);
}
/** 新增设备保养记录明细 */
export function createMaintenRecordLine(
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
) {
return requestClient.post('/mes/dv/mainten-record-line/create', data);
}
/** 修改设备保养记录明细 */
export function updateMaintenRecordLine(
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
) {
return requestClient.put('/mes/dv/mainten-record-line/update', data);
}
/** 删除设备保养记录明细 */
export function deleteMaintenRecordLine(id: number) {
return requestClient.delete(`/mes/dv/mainten-record-line/delete?id=${id}`);
}

View File

@ -1,81 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvRepairApi {
/** MES 维修工单 */
export interface Repair {
id?: number; // 工单编号
code?: string; // 维修工单编码
name?: string; // 维修工单名称
machineryId?: number; // 设备编号
machineryCode?: string; // 设备编码
machineryName?: string; // 设备名称
machineryBrand?: string; // 品牌
machinerySpecification?: string; // 规格型号
requireDate?: Date | number; // 报修日期
finishDate?: Date | number; // 维修完成日期
confirmDate?: Date | number; // 验收日期
result?: number; // 维修结果
acceptedUserId?: number; // 维修人编号
acceptedUserNickname?: string; // 维修人名称
confirmUserId?: number; // 验收人编号
confirmUserNickname?: string; // 验收人名称
sourceDocType?: number; // 来源单据类型
sourceDocId?: number; // 来源单据编号
sourceDocCode?: string; // 来源单据编码
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询维修工单分页 */
export function getRepairPage(params: PageParam) {
return requestClient.get<PageResult<MesDvRepairApi.Repair>>(
'/mes/dv/repair/page',
{ params },
);
}
/** 查询维修工单详情 */
export function getRepair(id: number) {
return requestClient.get<MesDvRepairApi.Repair>(
`/mes/dv/repair/get?id=${id}`,
);
}
/** 新增维修工单 */
export function createRepair(data: MesDvRepairApi.Repair) {
return requestClient.post<number>('/mes/dv/repair/create', data);
}
/** 修改维修工单 */
export function updateRepair(data: MesDvRepairApi.Repair) {
return requestClient.put('/mes/dv/repair/update', data);
}
/** 删除维修工单 */
export function deleteRepair(id: number) {
return requestClient.delete(`/mes/dv/repair/delete?id=${id}`);
}
/** 导出维修工单 */
export function exportRepair(params: any) {
return requestClient.download('/mes/dv/repair/export-excel', { params });
}
/** 提交维修工单 */
export function submitRepair(id: number) {
return requestClient.put(`/mes/dv/repair/submit?id=${id}`);
}
/** 确认维修完成 */
export function confirmRepair(data: MesDvRepairApi.Repair) {
return requestClient.put('/mes/dv/repair/confirm', data);
}
/** 完成验收 */
export function finishRepair(id: number, result: number) {
return requestClient.put(`/mes/dv/repair/finish?id=${id}&result=${result}`);
}

View File

@ -1,49 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvRepairLineApi {
/** MES 维修工单行 */
export interface RepairLine {
id?: number; // 明细编号
repairId?: number; // 维修工单编号
subjectId?: number; // 项目编号
subjectName?: string; // 项目名称
subjectContent?: string; // 项目内容
subjectStandard?: string; // 项目标准
malfunction?: string; // 故障描述
malfunctionUrl?: string; // 故障图片 URL
description?: string; // 维修描述
remark?: string; // 备注
}
}
/** 查询维修工单行分页 */
export function getRepairLinePage(params: PageParam) {
return requestClient.get<PageResult<MesDvRepairLineApi.RepairLine>>(
'/mes/dv/repair-line/page',
{ params },
);
}
/** 查询维修工单行详情 */
export function getRepairLine(id: number) {
return requestClient.get<MesDvRepairLineApi.RepairLine>(
`/mes/dv/repair-line/get?id=${id}`,
);
}
/** 新增维修工单行 */
export function createRepairLine(data: MesDvRepairLineApi.RepairLine) {
return requestClient.post('/mes/dv/repair-line/create', data);
}
/** 修改维修工单行 */
export function updateRepairLine(data: MesDvRepairLineApi.RepairLine) {
return requestClient.put('/mes/dv/repair-line/update', data);
}
/** 删除维修工单行 */
export function deleteRepairLine(id: number) {
return requestClient.delete(`/mes/dv/repair-line/delete?id=${id}`);
}

View File

@ -1,60 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesDvSubjectApi {
/** MES 点检保养项目 */
export interface Subject {
id?: number; // 项目编号
code?: string; // 项目编码
name?: string; // 项目名称
type?: number; // 项目类型
content?: string; // 项目内容
standard?: string; // 标准
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询点检保养项目分页 */
export function getSubjectPage(params: PageParam) {
return requestClient.get<PageResult<MesDvSubjectApi.Subject>>(
'/mes/dv/subject/page',
{ params },
);
}
/** 查询点检保养项目精简列表 */
export function getSubjectSimpleList() {
return requestClient.get<MesDvSubjectApi.Subject[]>(
'/mes/dv/subject/simple-list',
);
}
/** 查询点检保养项目详情 */
export function getSubject(id: number) {
return requestClient.get<MesDvSubjectApi.Subject>(
`/mes/dv/subject/get?id=${id}`,
);
}
/** 新增点检保养项目 */
export function createSubject(data: MesDvSubjectApi.Subject) {
return requestClient.post('/mes/dv/subject/create', data);
}
/** 修改点检保养项目 */
export function updateSubject(data: MesDvSubjectApi.Subject) {
return requestClient.put('/mes/dv/subject/update', data);
}
/** 删除点检保养项目 */
export function deleteSubject(id: number) {
return requestClient.delete(`/mes/dv/subject/delete?id=${id}`);
}
/** 导出点检保养项目 */
export function exportSubject(params: any) {
return requestClient.download('/mes/dv/subject/export-excel', { params });
}

View File

@ -1,55 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesHomeApi {
/** MES 首页汇总统计 */
export interface Summary {
workOrderActiveCount: number; // 进行中工单数
workOrderPrepareCount: number; // 待排产工单数
workOrderFinishedCount: number; // 已完成工单数
todayOutput: number; // 今日产量
yesterdayOutput: number; // 昨日产量
todayQualifiedQuantity: number; // 今日合格品数
todayUnqualifiedQuantity: number; // 今日不良品数
machineryTotal: number; // 设备总数
machineryProducing: number; // 生产中设备数
machineryStop: number; // 停机设备数
machineryMaintenance: number; // 维护中设备数
andonActiveCount: number; // 未处置安灯呼叫数
repairActiveCount: number; // 待处理维修工单数
}
/** MES 工单状态分布 */
export interface WorkOrderStatus {
status: number; // 工单状态
statusName: string; // 工单状态名称
count: number; // 数量
}
/** MES 生产趋势 */
export interface ProductionTrend {
date: string; // 日期
quantity: number; // 产量
qualifiedQuantity: number; // 合格品数
unqualifiedQuantity: number; // 不良品数
}
}
/** 获得首页汇总统计 */
export function getHomeSummary() {
return requestClient.get<MesHomeApi.Summary>('/mes/home-statistics/summary');
}
/** 获得工单状态分布 */
export function getWorkOrderStatusDistribution() {
return requestClient.get<MesHomeApi.WorkOrderStatus[]>(
'/mes/home-statistics/work-order-status',
);
}
/** 获得生产趋势 */
export function getProductionTrend(days?: number) {
return requestClient.get<MesHomeApi.ProductionTrend[]>(
'/mes/home-statistics/production-trend',
{ params: { days } },
);
}

View File

@ -1,49 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesMdAutoCodePartApi {
/** MES 编码规则分段 */
export interface AutoCodePart {
id?: number; // 分段编号
ruleId?: number; // 规则编号
sort?: number; // 排序
type?: number; // 分段类型
length?: number; // 长度
dateFormat?: string; // 日期格式
fixCharacter?: string; // 固定字符
serialStartNo?: number; // 流水号起始值
serialStep?: number; // 流水号步长
cycleFlag?: boolean; // 是否循环
cycleMethod?: number; // 循环方式
remark?: string; // 备注
}
}
/** 查询编码规则分段详情 */
export function getAutoCodePart(id: number) {
return requestClient.get<MesMdAutoCodePartApi.AutoCodePart>(
`/mes/md/auto-code-part/get?id=${id}`,
);
}
/** 查询编码规则分段列表 */
export function getAutoCodePartListByRuleId(ruleId: number) {
return requestClient.get<MesMdAutoCodePartApi.AutoCodePart[]>(
'/mes/md/auto-code-part/list-by-rule-id',
{ params: { ruleId } },
);
}
/** 新增编码规则分段 */
export function createAutoCodePart(data: MesMdAutoCodePartApi.AutoCodePart) {
return requestClient.post('/mes/md/auto-code-part/create', data);
}
/** 修改编码规则分段 */
export function updateAutoCodePart(data: MesMdAutoCodePartApi.AutoCodePart) {
return requestClient.put('/mes/md/auto-code-part/update', data);
}
/** 删除编码规则分段 */
export function deleteAutoCodePart(id: number) {
return requestClient.delete(`/mes/md/auto-code-part/delete?id=${id}`);
}

View File

@ -1,9 +0,0 @@
import { requestClient } from '#/api/request';
/** 生成 MES 编码 */
export function generateAutoCode(ruleCode: string, inputChar?: string) {
return requestClient.post<string>('/mes/md/auto-code-record/generate', {
inputChar,
ruleCode,
});
}

View File

@ -1,57 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdAutoCodeRuleApi {
/** MES 编码规则 */
export interface AutoCodeRule {
id?: number; // 规则编号
code?: string; // 规则编码
name?: string; // 规则名称
description?: string; // 规则描述
maxLength?: number; // 最大长度
padded?: boolean; // 是否补齐
paddedChar?: string; // 补齐字符
paddedMethod?: number; // 补齐方式
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询编码规则分页 */
export function getAutoCodeRulePage(params: PageParam) {
return requestClient.get<PageResult<MesMdAutoCodeRuleApi.AutoCodeRule>>(
'/mes/md/auto-code-rule/page',
{ params },
);
}
/** 查询编码规则详情 */
export function getAutoCodeRule(id: number) {
return requestClient.get<MesMdAutoCodeRuleApi.AutoCodeRule>(
`/mes/md/auto-code-rule/get?id=${id}`,
);
}
/** 新增编码规则 */
export function createAutoCodeRule(data: MesMdAutoCodeRuleApi.AutoCodeRule) {
return requestClient.post('/mes/md/auto-code-rule/create', data);
}
/** 修改编码规则 */
export function updateAutoCodeRule(data: MesMdAutoCodeRuleApi.AutoCodeRule) {
return requestClient.put('/mes/md/auto-code-rule/update', data);
}
/** 删除编码规则 */
export function deleteAutoCodeRule(id: number) {
return requestClient.delete(`/mes/md/auto-code-rule/delete?id=${id}`);
}
/** 导出编码规则 */
export function exportAutoCodeRule(params: PageParam) {
return requestClient.download('/mes/md/auto-code-rule/export-excel', {
params,
});
}

View File

@ -1,86 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdClientApi {
/** MES 客户 */
export interface Client {
id?: number; // 客户编号
code?: string; // 客户编码
name?: string; // 客户名称
nickname?: string; // 客户简称
englishName?: string; // 客户英文名称
description?: string; // 客户简介
logo?: string; // 客户 LOGO 地址
type?: number; // 客户类型
address?: string; // 客户地址
website?: string; // 客户官网地址
email?: string; // 客户邮箱地址
telephone?: string; // 客户电话
contact1Name?: string; // 联系人1
contact1Telephone?: string; // 联系人1电话
contact1Email?: string; // 联系人1邮箱
contact2Name?: string; // 联系人2
contact2Telephone?: string; // 联系人2电话
contact2Email?: string; // 联系人2邮箱
creditCode?: string; // 统一社会信用代码
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
/** 客户导入结果 */
export interface ClientImportRespVO {
createCodes?: string[]; // 新增成功的客户编码
updateCodes?: string[]; // 更新成功的客户编码
failureCodes?: Record<string, string>; // 导入失败的客户编码及原因
}
}
/** 查询客户分页 */
export function getClientPage(params: PageParam) {
return requestClient.get<PageResult<MesMdClientApi.Client>>(
'/mes/md-client/page',
{ params },
);
}
/** 查询客户详情 */
export function getClient(id: number) {
return requestClient.get<MesMdClientApi.Client>(
`/mes/md-client/get?id=${id}`,
);
}
/** 新增客户 */
export function createClient(data: MesMdClientApi.Client) {
return requestClient.post('/mes/md-client/create', data);
}
/** 修改客户 */
export function updateClient(data: MesMdClientApi.Client) {
return requestClient.put('/mes/md-client/update', data);
}
/** 删除客户 */
export function deleteClient(id: number) {
return requestClient.delete(`/mes/md-client/delete?id=${id}`);
}
/** 导出客户 */
export function exportClient(params: any) {
return requestClient.download('/mes/md-client/export-excel', { params });
}
/** 下载客户导入模板 */
export function importClientTemplate() {
return requestClient.download('/mes/md-client/get-import-template');
}
/** 导入客户 */
export function importClient(file: File, updateSupport: boolean) {
return requestClient.upload<MesMdClientApi.ClientImportRespVO>(
`/mes/md-client/import?updateSupport=${updateSupport}`,
{ file },
);
}

View File

@ -1,35 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesMdItemBatchConfigApi {
/** MES 物料批次属性配置 */
export interface BatchConfig {
id?: number; // 编号
itemId?: number; // 物料编号
produceDateFlag?: boolean; // 批次属性-生产日期
expireDateFlag?: boolean; // 批次属性-有效期
receiptDateFlag?: boolean; // 批次属性-入库日期
vendorFlag?: boolean; // 批次属性-供应商
clientFlag?: boolean; // 批次属性-客户
salesOrderCodeFlag?: boolean; // 批次属性-销售订单编号
purchaseOrderCodeFlag?: boolean; // 批次属性-采购订单编号
workorderFlag?: boolean; // 批次属性-生产工单
taskFlag?: boolean; // 批次属性-生产任务
workstationFlag?: boolean; // 批次属性-工作站
toolFlag?: boolean; // 批次属性-工具
moldFlag?: boolean; // 批次属性-模具
lotNumberFlag?: boolean; // 批次属性-生产批号
qualityStatusFlag?: boolean; // 批次属性-质量状态
}
}
/** 根据物料编号获取批次属性配置 */
export function getBatchConfigByItemId(itemId: number) {
return requestClient.get<MesMdItemBatchConfigApi.BatchConfig>(
`/mes/md/item-batch-config/get-by-item-id?itemId=${itemId}`,
);
}
/** 保存批次属性配置 */
export function saveBatchConfig(data: MesMdItemBatchConfigApi.BatchConfig) {
return requestClient.post('/mes/md/item-batch-config/save', data);
}

View File

@ -1,85 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdItemApi {
/** MES 物料产品 */
export interface Item {
id?: number; // 物料编号
code?: string; // 物料编码
name?: string; // 物料名称
specification?: string; // 规格型号
unitMeasureId?: number; // 计量单位编号
unitMeasureName?: string; // 计量单位名称
itemTypeId?: number; // 物料分类编号
itemTypeName?: string; // 物料分类名称
itemOrProduct?: string; // 物料/产品标识
status?: number; // 状态
safeStockFlag?: boolean; // 是否启用安全库存
minStock?: number; // 最低库存量
maxStock?: number; // 最高库存量
highValue?: boolean; // 是否高值物料
batchFlag?: boolean; // 是否启用批次管理
remark?: string; // 备注
createTime?: Date; // 创建时间
}
/** 物料导入结果 */
export interface ItemImportRespVO {
createCodes?: string[]; // 新增成功的物料编码
updateCodes?: string[]; // 更新成功的物料编码
failureCodes?: Record<string, string>; // 导入失败的物料编码及原因
}
}
/** 查询物料产品分页 */
export function getItemPage(params: PageParam) {
return requestClient.get<PageResult<MesMdItemApi.Item>>('/mes/md/item/page', {
params,
});
}
/** 查询物料产品详情 */
export function getItem(id: number) {
return requestClient.get<MesMdItemApi.Item>(`/mes/md/item/get?id=${id}`);
}
/** 新增物料产品 */
export function createItem(data: MesMdItemApi.Item) {
return requestClient.post<number>('/mes/md/item/create', data);
}
/** 修改物料产品 */
export function updateItem(data: MesMdItemApi.Item) {
return requestClient.put('/mes/md/item/update', data);
}
/** 修改物料产品状态 */
export function updateItemStatus(id: number, status: number) {
return requestClient.put('/mes/md/item/update-status', undefined, {
params: { id, status },
});
}
/** 删除物料产品 */
export function deleteItem(id: number) {
return requestClient.delete(`/mes/md/item/delete?id=${id}`);
}
/** 导出物料产品 */
export function exportItem(params: any) {
return requestClient.download('/mes/md/item/export-excel', { params });
}
/** 下载物料导入模板 */
export function importItemTemplate() {
return requestClient.download('/mes/md/item/get-import-template');
}
/** 导入物料产品 */
export function importItem(file: File, updateSupport: boolean) {
return requestClient.upload<MesMdItemApi.ItemImportRespVO>(
`/mes/md/item/import?updateSupport=${updateSupport}`,
{ file },
);
}

View File

@ -1,58 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdProductBomApi {
/** MES 产品 BOM */
export interface ProductBom {
id?: number; // BOM 编号
itemId?: number; // 物料产品编号
bomItemId?: number; // BOM 物料编号
quantity?: number; // 物料使用比例
status?: number; // 是否启用
remark?: string; // 备注
createTime?: Date; // 创建时间
bomItemCode?: string; // BOM 物料编码
bomItemName?: string; // BOM 物料名称
bomItemSpecification?: string; // BOM 物料规格
unitMeasureName?: string; // 计量单位名称
itemOrProduct?: string; // 物料/产品标识
}
}
/** 新增产品 BOM */
export function createProductBom(data: MesMdProductBomApi.ProductBom) {
return requestClient.post('/mes/md/product-bom/create', data);
}
/** 修改产品 BOM */
export function updateProductBom(data: MesMdProductBomApi.ProductBom) {
return requestClient.put('/mes/md/product-bom/update', data);
}
/** 删除产品 BOM */
export function deleteProductBom(id: number) {
return requestClient.delete(`/mes/md/product-bom/delete?id=${id}`);
}
/** 查询产品 BOM 详情 */
export function getProductBom(id: number) {
return requestClient.get<MesMdProductBomApi.ProductBom>(
`/mes/md/product-bom/get?id=${id}`,
);
}
/** 查询产品 BOM 分页 */
export function getProductBomPage(params: PageParam) {
return requestClient.get<PageResult<MesMdProductBomApi.ProductBom>>(
'/mes/md/product-bom/page',
{ params },
);
}
/** 根据物料产品编号查询产品 BOM 列表 */
export function getProductBomListByItemId(itemId: number) {
return requestClient.get<MesMdProductBomApi.ProductBom[]>(
`/mes/md/product-bom/list-by-item-id?itemId=${itemId}`,
);
}

View File

@ -1,57 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdProductSipApi {
/** MES 产品 SIP */
export interface ProductSip {
id?: number; // SIP 编号
itemId?: number; // 物料产品编号
sort?: number; // 排列顺序
processId?: number; // 工序编号
title?: string; // 标题
description?: string; // 详细描述
url?: string; // 图片地址
remark?: string; // 备注
createTime?: Date; // 创建时间
processCode?: string; // 工序编码
processName?: string; // 工序名称
}
}
/** 新增产品 SIP */
export function createProductSip(data: MesMdProductSipApi.ProductSip) {
return requestClient.post('/mes/md/product-sip/create', data);
}
/** 修改产品 SIP */
export function updateProductSip(data: MesMdProductSipApi.ProductSip) {
return requestClient.put('/mes/md/product-sip/update', data);
}
/** 删除产品 SIP */
export function deleteProductSip(id: number) {
return requestClient.delete(`/mes/md/product-sip/delete?id=${id}`);
}
/** 查询产品 SIP 详情 */
export function getProductSip(id: number) {
return requestClient.get<MesMdProductSipApi.ProductSip>(
`/mes/md/product-sip/get?id=${id}`,
);
}
/** 查询产品 SIP 分页 */
export function getProductSipPage(params: PageParam) {
return requestClient.get<PageResult<MesMdProductSipApi.ProductSip>>(
'/mes/md/product-sip/page',
{ params },
);
}
/** 根据物料产品编号查询产品 SIP 列表 */
export function getProductSipListByItemId(itemId: number) {
return requestClient.get<MesMdProductSipApi.ProductSip[]>(
`/mes/md/product-sip/list-by-item-id?itemId=${itemId}`,
);
}

View File

@ -1,57 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdProductSopApi {
/** MES 产品 SOP */
export interface ProductSop {
id?: number; // SOP 编号
itemId?: number; // 物料产品编号
sort?: number; // 排列顺序
processId?: number; // 工序编号
title?: string; // 标题
description?: string; // 详细描述
url?: string; // 图片地址
remark?: string; // 备注
createTime?: Date; // 创建时间
processCode?: string; // 工序编码
processName?: string; // 工序名称
}
}
/** 新增产品 SOP */
export function createProductSop(data: MesMdProductSopApi.ProductSop) {
return requestClient.post('/mes/md/product-sop/create', data);
}
/** 修改产品 SOP */
export function updateProductSop(data: MesMdProductSopApi.ProductSop) {
return requestClient.put('/mes/md/product-sop/update', data);
}
/** 删除产品 SOP */
export function deleteProductSop(id: number) {
return requestClient.delete(`/mes/md/product-sop/delete?id=${id}`);
}
/** 查询产品 SOP 详情 */
export function getProductSop(id: number) {
return requestClient.get<MesMdProductSopApi.ProductSop>(
`/mes/md/product-sop/get?id=${id}`,
);
}
/** 查询产品 SOP 分页 */
export function getProductSopPage(params: PageParam) {
return requestClient.get<PageResult<MesMdProductSopApi.ProductSop>>(
'/mes/md/product-sop/page',
{ params },
);
}
/** 根据物料产品编号查询产品 SOP 列表 */
export function getProductSopListByItemId(itemId: number) {
return requestClient.get<MesMdProductSopApi.ProductSop[]>(
`/mes/md/product-sop/list-by-item-id?itemId=${itemId}`,
);
}

View File

@ -1,54 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesMdItemTypeApi {
/** MES 物料产品分类 */
export interface ItemType {
id?: number; // 分类编号
parentId?: number; // 父分类编号
code?: string; // 分类编码
name?: string; // 分类名称
itemOrProduct?: string; // 物料/产品标识
sort?: number; // 显示排序
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
children?: ItemType[]; // 子分类
}
}
/** 查询物料产品分类列表 */
export function getItemTypeList(params?: any) {
return requestClient.get<MesMdItemTypeApi.ItemType[]>(
'/mes/md/item-type/list',
{ params },
);
}
/** 查询物料产品分类精简列表 */
export function getItemTypeSimpleList() {
return requestClient.get<MesMdItemTypeApi.ItemType[]>(
'/mes/md/item-type/simple-list',
);
}
/** 查询物料产品分类详情 */
export function getItemType(id: number) {
return requestClient.get<MesMdItemTypeApi.ItemType>(
`/mes/md/item-type/get?id=${id}`,
);
}
/** 新增物料产品分类 */
export function createItemType(data: MesMdItemTypeApi.ItemType) {
return requestClient.post('/mes/md/item-type/create', data);
}
/** 修改物料产品分类 */
export function updateItemType(data: MesMdItemTypeApi.ItemType) {
return requestClient.put('/mes/md/item-type/update', data);
}
/** 删除物料产品分类 */
export function deleteItemType(id: number) {
return requestClient.delete(`/mes/md/item-type/delete?id=${id}`);
}

View File

@ -1,62 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdUnitMeasureApi {
/** MES 计量单位 */
export interface UnitMeasure {
id?: number; // 单位编号
code?: string; // 单位编码
name?: string; // 单位名称
primaryFlag?: boolean; // 是否主单位
primaryId?: number; // 主单位编号
changeRate?: number; // 与主单位换算比例
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询计量单位分页 */
export function getUnitMeasurePage(params: PageParam) {
return requestClient.get<PageResult<MesMdUnitMeasureApi.UnitMeasure>>(
'/mes/md/unit-measure/page',
{ params },
);
}
/** 查询计量单位精简列表 */
export function getUnitMeasureSimpleList() {
return requestClient.get<MesMdUnitMeasureApi.UnitMeasure[]>(
'/mes/md/unit-measure/simple-list',
);
}
/** 查询计量单位详情 */
export function getUnitMeasure(id: number) {
return requestClient.get<MesMdUnitMeasureApi.UnitMeasure>(
`/mes/md/unit-measure/get?id=${id}`,
);
}
/** 新增计量单位 */
export function createUnitMeasure(data: MesMdUnitMeasureApi.UnitMeasure) {
return requestClient.post('/mes/md/unit-measure/create', data);
}
/** 修改计量单位 */
export function updateUnitMeasure(data: MesMdUnitMeasureApi.UnitMeasure) {
return requestClient.put('/mes/md/unit-measure/update', data);
}
/** 删除计量单位 */
export function deleteUnitMeasure(id: number) {
return requestClient.delete(`/mes/md/unit-measure/delete?id=${id}`);
}
/** 导出计量单位 */
export function exportUnitMeasure(params: PageParam) {
return requestClient.download('/mes/md/unit-measure/export-excel', {
params,
});
}

View File

@ -1,87 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdVendorApi {
/** MES 供应商 */
export interface Vendor {
id?: number; // 供应商编号
code?: string; // 供应商编码
name?: string; // 供应商名称
nickname?: string; // 供应商简称
englishName?: string; // 供应商英文名称
description?: string; // 供应商简介
logo?: string; // 供应商 LOGO 地址
level?: string; // 供应商等级
score?: number; // 供应商评分
address?: string; // 供应商地址
website?: string; // 供应商官网地址
email?: string; // 供应商邮箱地址
telephone?: string; // 供应商电话
contact1Name?: string; // 联系人1
contact1Telephone?: string; // 联系人1电话
contact1Email?: string; // 联系人1邮箱
contact2Name?: string; // 联系人2
contact2Telephone?: string; // 联系人2电话
contact2Email?: string; // 联系人2邮箱
creditCode?: string; // 统一社会信用代码
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
/** 供应商导入结果 */
export interface VendorImportRespVO {
createCodes?: string[]; // 新增成功的供应商编码
updateCodes?: string[]; // 更新成功的供应商编码
failureCodes?: Record<string, string>; // 导入失败的供应商编码及原因
}
}
/** 查询供应商分页 */
export function getVendorPage(params: PageParam) {
return requestClient.get<PageResult<MesMdVendorApi.Vendor>>(
'/mes/md-vendor/page',
{ params },
);
}
/** 查询供应商详情 */
export function getVendor(id: number) {
return requestClient.get<MesMdVendorApi.Vendor>(
`/mes/md-vendor/get?id=${id}`,
);
}
/** 新增供应商 */
export function createVendor(data: MesMdVendorApi.Vendor) {
return requestClient.post('/mes/md-vendor/create', data);
}
/** 修改供应商 */
export function updateVendor(data: MesMdVendorApi.Vendor) {
return requestClient.put('/mes/md-vendor/update', data);
}
/** 删除供应商 */
export function deleteVendor(id: number) {
return requestClient.delete(`/mes/md-vendor/delete?id=${id}`);
}
/** 导出供应商 */
export function exportVendor(params: any) {
return requestClient.download('/mes/md-vendor/export-excel', { params });
}
/** 下载供应商导入模板 */
export function importVendorTemplate() {
return requestClient.download('/mes/md-vendor/get-import-template');
}
/** 导入供应商 */
export function importVendor(file: File, updateSupport: boolean) {
return requestClient.upload<MesMdVendorApi.VendorImportRespVO>(
`/mes/md-vendor/import?updateSupport=${updateSupport}`,
{ file },
);
}

View File

@ -1,58 +0,0 @@
import type { PageParam, PageResult } from '@vben/request';
import { requestClient } from '#/api/request';
export namespace MesMdWorkstationApi {
/** MES 工作站 */
export interface Workstation {
id?: number; // 工作站编号
code?: string; // 工作站编码
name?: string; // 工作站名称
address?: string; // 工作站地点
workshopId?: number; // 所在车间编号
workshopName?: string; // 所在车间名称
processId?: number; // 工序编号
processName?: string; // 工序名称
warehouseId?: number; // 线边库编号
locationId?: number; // 库区编号
areaId?: number; // 库位编号
status?: number; // 状态
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询工作站分页 */
export function getWorkstationPage(params: PageParam) {
return requestClient.get<PageResult<MesMdWorkstationApi.Workstation>>(
'/mes/md-workstation/page',
{ params },
);
}
/** 查询工作站详情 */
export function getWorkstation(id: number) {
return requestClient.get<MesMdWorkstationApi.Workstation>(
`/mes/md-workstation/get?id=${id}`,
);
}
/** 新增工作站 */
export function createWorkstation(data: MesMdWorkstationApi.Workstation) {
return requestClient.post<number>('/mes/md-workstation/create', data);
}
/** 修改工作站 */
export function updateWorkstation(data: MesMdWorkstationApi.Workstation) {
return requestClient.put('/mes/md-workstation/update', data);
}
/** 删除工作站 */
export function deleteWorkstation(id: number) {
return requestClient.delete(`/mes/md-workstation/delete?id=${id}`);
}
/** 导出工作站 */
export function exportWorkstation(params: any) {
return requestClient.download('/mes/md-workstation/export-excel', { params });
}

View File

@ -1,35 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesMdWorkstationMachineApi {
/** MES 工作站设备资源 */
export interface WorkstationMachine {
id?: number; // 资源编号
workstationId?: number; // 工作站编号
machineryId?: number; // 设备编号
machineryCode?: string; // 设备编码
machineryName?: string; // 设备名称
quantity?: number; // 数量
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询工作站设备资源列表 */
export function getWorkstationMachineList(workstationId: number) {
return requestClient.get<MesMdWorkstationMachineApi.WorkstationMachine[]>(
'/mes/md-workstation-machine/list-by-workstation',
{ params: { workstationId } },
);
}
/** 新增工作站设备资源 */
export function createWorkstationMachine(
data: MesMdWorkstationMachineApi.WorkstationMachine,
) {
return requestClient.post('/mes/md-workstation-machine/create', data);
}
/** 删除工作站设备资源 */
export function deleteWorkstationMachine(id: number) {
return requestClient.delete(`/mes/md-workstation-machine/delete?id=${id}`);
}

View File

@ -1,41 +0,0 @@
import { requestClient } from '#/api/request';
export namespace MesMdWorkstationToolApi {
/** MES 工作站工装夹具资源 */
export interface WorkstationTool {
id?: number; // 资源编号
workstationId?: number; // 工作站编号
toolTypeId?: number; // 工具类型编号
toolTypeName?: string; // 工具类型名称
quantity?: number; // 数量
remark?: string; // 备注
createTime?: Date; // 创建时间
}
}
/** 查询工作站工装夹具资源列表 */
export function getWorkstationToolList(workstationId: number) {
return requestClient.get<MesMdWorkstationToolApi.WorkstationTool[]>(
'/mes/md-workstation-tool/list-by-workstation',
{ params: { workstationId } },
);
}
/** 新增工作站工装夹具资源 */
export function createWorkstationTool(
data: MesMdWorkstationToolApi.WorkstationTool,
) {
return requestClient.post('/mes/md-workstation-tool/create', data);
}
/** 修改工作站工装夹具资源 */
export function updateWorkstationTool(
data: MesMdWorkstationToolApi.WorkstationTool,
) {
return requestClient.put('/mes/md-workstation-tool/update', data);
}
/** 删除工作站工装夹具资源 */
export function deleteWorkstationTool(id: number) {
return requestClient.delete(`/mes/md-workstation-tool/delete?id=${id}`);
}

Some files were not shown because too many files have changed in this diff Show More