Compare commits
No commits in common. "6.X-Vue" and "v5.1.0-v2.1.0" have entirely different histories.
6.X-Vue
...
v5.1.0-v2.
@ -1,32 +0,0 @@
|
||||
---
|
||||
name: frontend-api-types
|
||||
description: 前端 API 与类型定义专家。用于 plus-ui 前端项目中的 src/api 层、types.ts、返回结构、Query/Form/VO/InfoVO 定义,以及前后端接口映射任务;默认基线为 Gitee 仓库 JavaLionLi/plus-ui 的 6.X-Vue 分支。
|
||||
---
|
||||
|
||||
你负责 plus-ui 前端项目中的 API 层和类型定义。
|
||||
|
||||
基线仓库:`https://gitee.com/JavaLionLi/plus-ui`
|
||||
默认分支:`6.X-Vue`
|
||||
远端引用必须同时标记仓库、分支和文件路径;不要写本机绝对路径。
|
||||
|
||||
## 核心原则
|
||||
|
||||
1. 先看当前模块已有 `src/api/<module>/<business>`。
|
||||
2. API 路径、返回类型、命名风格与当前模块保持一致。
|
||||
3. 能明确写出类型时,不要偷懒用 `any`。
|
||||
4. 如果当前模块已有 `export default { ... }`,继续保持一致。
|
||||
|
||||
## 重点关注
|
||||
|
||||
- `Query`
|
||||
- `VO`
|
||||
- `Form`
|
||||
- `InfoVO`
|
||||
- `AxiosPromise<PageResult<T>>`
|
||||
- 详情接口与列表接口返回结构
|
||||
|
||||
## 自检
|
||||
|
||||
- API 路径是否与后端一致
|
||||
- 类型是否覆盖接口真实结构
|
||||
- 是否不必要地把类型写宽了
|
||||
@ -1,22 +0,0 @@
|
||||
---
|
||||
name: frontend-crud-coding
|
||||
description: 前端总入口。用于 plus-ui 前端项目中的标准 CRUD 页面、新增 API/types、复杂列表页增强、树筛选、导入导出、权限按钮与弹窗表单等任务,并根据任务类型选择合适的前端子 agent;默认基线为 Gitee 仓库 JavaLionLi/plus-ui 的 6.X-Vue 分支。
|
||||
---
|
||||
|
||||
你是 plus-ui 前端项目的总入口 agent。
|
||||
|
||||
基线仓库:`https://gitee.com/JavaLionLi/plus-ui`
|
||||
默认分支:`6.X-Vue`
|
||||
远端引用必须同时标记仓库、分支和文件路径;不要在 agent 文档中写本机绝对路径。
|
||||
|
||||
先判断任务类型,再按下面规则处理:
|
||||
|
||||
1. 如果是新增标准 CRUD 页面、补 `src/api`、`types.ts`、`index.vue`,优先使用 `frontend-crud-page.md`。
|
||||
2. 如果是修改已有列表页、增强导入导出、树筛选、更多菜单、状态切换,优先使用 `frontend-page-enhancement.md`。
|
||||
3. 如果只改接口层和类型定义,优先使用 `frontend-api-types.md`。
|
||||
|
||||
通用要求:
|
||||
|
||||
- 先读当前目录下最近似页面和 API,再动代码。
|
||||
- 冲突时优先相信当前项目真实页面,其次是公共组件和工具,再其次才是 plus-ui Gitee 仓库 `6.X-Vue` 分支的 `gen` 模板。
|
||||
- 默认直接产出可落地代码,而不是只给抽象建议。
|
||||
@ -1,41 +0,0 @@
|
||||
---
|
||||
name: frontend-crud-page
|
||||
description: 前端标准 CRUD 页面专家。用于 plus-ui 前端项目中的新建列表页、弹窗表单页、标准 API/types/index.vue 骨架,以及 gen 模板到项目风格的落地任务;默认参考 Gitee 仓库 JavaLionLi/plus-ui 的 6.X-Vue 分支。
|
||||
---
|
||||
|
||||
你负责 plus-ui 前端项目中的标准 CRUD 页面实现。
|
||||
|
||||
基线仓库:`https://gitee.com/JavaLionLi/plus-ui`
|
||||
默认分支:`6.X-Vue`
|
||||
远端模板引用必须同时标记仓库、分支和路径,例如 `branch=6.X-Vue, path=gen/index.vue.ftl`;不要写本机绝对路径。
|
||||
|
||||
## 核心原则
|
||||
|
||||
1. 先看当前模块最近似页面。
|
||||
2. 再参考 plus-ui Gitee 仓库 `6.X-Vue` 分支中的 `gen` 模板。
|
||||
3. 默认同时维护:
|
||||
`src/api/<module>/<business>/index.ts`
|
||||
`src/api/<module>/<business>/types.ts`
|
||||
`src/views/<module>/<business>/index.vue`
|
||||
|
||||
## 页面规则
|
||||
|
||||
- 页面优先使用 `<script setup name="Xxx" lang="ts">`
|
||||
- 标准结构通常包含:
|
||||
搜索区、表格区、工具栏、分页、编辑弹窗
|
||||
- 常见状态:
|
||||
`loading`、`showSearch`、`ids`、`single`、`multiple`、`total`
|
||||
- 查询与表单优先使用 `reactive<PageData<Form, Query>>({...})`
|
||||
|
||||
## API / types 规则
|
||||
|
||||
- 请求统一通过 `@/utils/request`
|
||||
- 同目录维护 `index.ts` 与 `types.ts`
|
||||
- 标准 CRUD 通常包含:列表、详情、新增、修改、删除
|
||||
- 列表接口通常返回 `AxiosPromise<PageResult<XxxVO>>`
|
||||
|
||||
## 自检
|
||||
|
||||
- API 路径是否与后端一致
|
||||
- `index.ts` 与 `types.ts` 是否同步补齐
|
||||
- 页面是否只是模板裸输出,如果是要继续补强到当前项目风格
|
||||
@ -1,31 +0,0 @@
|
||||
---
|
||||
name: frontend-page-enhancement
|
||||
description: 复杂前端页面增强专家。用于修改 plus-ui 前端项目中已经存在的列表页、树筛选页、带导入导出和更多菜单的页面,强调增量修改和保留现有交互能力;默认基线为 Gitee 仓库 JavaLionLi/plus-ui 的 6.X-Vue 分支。
|
||||
---
|
||||
|
||||
你负责 plus-ui 前端项目中已有页面的增强,不是重写页面。
|
||||
|
||||
基线仓库:`https://gitee.com/JavaLionLi/plus-ui`
|
||||
默认分支:`6.X-Vue`
|
||||
远端引用必须同时标记仓库、分支和文件路径;不要写本机绝对路径。
|
||||
|
||||
## 核心原则
|
||||
|
||||
1. 优先阅读当前页面完整实现。
|
||||
2. 增量修改,不重写整页。
|
||||
3. 保留已有树筛选、导入导出、列显隐、更多菜单、状态切换、路由跳转、SCSS 页面壳。
|
||||
4. 不要把复杂页面退化成 generator 式基础列表页。
|
||||
|
||||
## 常见任务
|
||||
|
||||
- 调整工具栏和更多菜单
|
||||
- 增加筛选条件和日期范围
|
||||
- 增加导入导出能力
|
||||
- 增加状态切换、快捷操作、确认弹窗
|
||||
- 补复杂页面的小型子功能
|
||||
|
||||
## 自检
|
||||
|
||||
- 是否破坏了原页面结构和样式
|
||||
- 是否误删了已有权限控制或交互能力
|
||||
- 是否应该拆成子组件而不是继续堆主页面
|
||||
@ -1,151 +0,0 @@
|
||||
---
|
||||
name: frontend-crud-coding
|
||||
description: 在 plus-ui 前端项目中按真实 Vue 3 + TypeScript + Element Plus + oxlint/oxfmt 代码风格生成或修改页面、API、types、hooks 接入和样式壳。用于新增或修改标准 CRUD 列表页、树表页、系统管理页、监控页、workflow 页面、demo 页面,补齐与后端接口对应的 src/api、types 和 src/views 代码;默认参考 Gitee 仓库 JavaLionLi/plus-ui 的 6.X-Vue 分支,触发后应先读取适用 references,再阅读目标模块真实代码和项目内 gen 代码生成模板。
|
||||
---
|
||||
|
||||
# 前端编码规范
|
||||
|
||||
先对齐当前前端项目里的真实实现,再参考项目内 `gen` 目录下的代码生成模板。不要只套通用 Vue 模板,也不要把 generator 模板原样复制进来而忽略当前项目已经演进出的 hooks、页面壳、类型入口和下载方式。
|
||||
|
||||
## 项目基线
|
||||
|
||||
- 基线仓库:`https://gitee.com/JavaLionLi/plus-ui`
|
||||
- 默认分支:`6.X-Vue`
|
||||
- 远端引用必须同时标记仓库、分支和文件路径,例如 `https://gitee.com/JavaLionLi/plus-ui/blob/6.X-Vue/gen/index.vue.ftl` 或 `branch=6.X-Vue, path=gen/index.vue.ftl`。
|
||||
- 不要在 skill、reference 或 agent 文档中写本机绝对路径;本地文件读取以运行时工作目录为准。
|
||||
- 如果用户指定其他分支,先按用户分支读取同一仓库的对应文件,并在结果中说明使用的分支。
|
||||
|
||||
## 执行流程
|
||||
|
||||
1. 判断任务类型:新增标准 CRUD、树表、已有页面增强、复杂业务页、只补 API/types。
|
||||
2. 按“文档读取规则”读取必要 reference,不一次性展开所有资料。
|
||||
3. 阅读目标目录下最近似的真实代码:
|
||||
- 标准单表优先看 `src/views/demo/demo/index.vue`、`src/api/demo/demo/*`。
|
||||
- 树表优先看 `src/views/demo/tree/index.vue`、`src/views/workflow/category/index.vue`。
|
||||
- 系统复杂页优先看 `src/views/system/user/index.vue`、`system/role`、`system/post`、`system/config`。
|
||||
- workflow 业务页优先看 `src/views/workflow/*` 同类页面。
|
||||
4. 新增标准页面前,对照项目内模板确认基础骨架:
|
||||
- API 模板:`gen/api.ts.ftl`
|
||||
- types 模板:`gen/types.ts.ftl`
|
||||
- 标准单表页模板:`gen/index.vue.ftl`
|
||||
- 树表页模板:`gen/index-tree.vue.ftl`
|
||||
5. 新增代码时通常同步维护 `src/api/<module>/<business>/index.ts`、`types.ts`、`src/views/<module>/<business>/index.vue`。
|
||||
6. 增强已有页面时只做增量修改,保留原页面的树筛选、导入导出、列显隐、权限、字典、弹窗和路由跳转能力。
|
||||
7. 修改完成后按影响范围运行验证:优先 `pnpm exec vue-tsc --noEmit`,改动页面或导入时再跑 `pnpm lint`,大范围变更再跑 `pnpm build`。
|
||||
|
||||
## 文档读取规则
|
||||
|
||||
- 前端 API、types、页面、hooks、样式和验证规则,先读 [references/frontend.md](references/frontend.md)。
|
||||
- 不确定任务边界、需要标准用例或提问方式时,再读 [references/examples.md](references/examples.md)。
|
||||
- reference 只约束实现方式和自检范围;发生冲突时,以当前模块真实代码和实际调用点为准。
|
||||
|
||||
## 优先级规则
|
||||
|
||||
发生冲突时按下面顺序决策:
|
||||
|
||||
1. 目标目录下最近似页面、API、types 的真实实现。
|
||||
2. 当前项目公共 hooks、组件、工具和样式约定。
|
||||
3. 项目内 `gen` 代码生成模板。
|
||||
4. 通用 Vue 3 / Element Plus 习惯。
|
||||
|
||||
也就是说:
|
||||
|
||||
- 同模块已有页面怎么写,优先怎么写。
|
||||
- 没有现成页面时,使用项目内 `gen` 模板作为骨架,再改成当前项目风格。
|
||||
- 复杂模块不能为了“标准 CRUD”退化成裸模板页。
|
||||
|
||||
## 仓库通用规则
|
||||
|
||||
- 遵循 [`.editorconfig`](../../../.editorconfig):UTF-8、LF、2 空格缩进;Markdown 例外。
|
||||
- 当前仓库没有 `.prettierrc`,格式脚本是 `pnpm run fmt` 调用 `oxfmt .`,lint 脚本是 `pnpm lint` 调用 `oxlint src`。
|
||||
- 页面优先使用 `<script setup name="Xxx" lang="ts">`。
|
||||
- API 返回类型优先从 `@/utils/api-types` 引入 `AxiosPromise`,分页结果从 `@/api/types` 引入 `PageResult`。
|
||||
- 请求统一通过 `@/utils/request`,导出下载使用 `import { download as requestDownload } from '@/utils/request';`。
|
||||
- 标准列表页优先复用 `useLoading`、`useSearchToggle`、`useSearchReset`、`useTableSelection`、`useFormDialog`、`useDateRangeQuery`。
|
||||
- 页面壳优先使用 `p-2 app-container <module>-<business>-page`、`search-panel`、`toolbar-shell`、`data-table`、`right-toolbar`、`pagination`。
|
||||
- 新页面不要无故引入另一套状态管理、请求封装、样式体系或权限写法。
|
||||
|
||||
## 目录映射规则
|
||||
|
||||
通常按下面关系组织代码:
|
||||
|
||||
- 后端 `/system/user/*` 对应 `src/api/system/user/*` 与 `src/views/system/user/*`
|
||||
- 后端 `/monitor/xxx/*` 对应 `src/api/monitor/xxx/*` 与 `src/views/monitor/xxx/*`
|
||||
- 后端 `/workflow/xxx/*` 对应 `src/api/workflow/xxx/*` 与 `src/views/workflow/xxx/*`
|
||||
- 后端 `/demo/xxx/*` 对应 `src/api/demo/xxx/*` 与 `src/views/demo/xxx/*`
|
||||
|
||||
标准新增通常至少包含:
|
||||
|
||||
- `src/api/<module>/<business>/index.ts`
|
||||
- `src/api/<module>/<business>/types.ts`
|
||||
- `src/views/<module>/<business>/index.vue`
|
||||
|
||||
按业务复杂度,可能继续补:
|
||||
|
||||
- 导入弹窗
|
||||
- 详情抽屉或详情页
|
||||
- 树筛选面板
|
||||
- 列显隐配置
|
||||
- 分配/授权子页面
|
||||
- 自定义 SCSS 样式
|
||||
|
||||
## 任务分型
|
||||
|
||||
### 1. 标准单表 CRUD
|
||||
|
||||
以 `gen/index.vue.ftl`、`gen/api.ts.ftl`、`gen/types.ts.ftl` 和 `src/views/demo/demo/index.vue` 为主要起点,补齐列表、搜索、分页、新增、编辑、删除、导出、权限、类型和验证。
|
||||
|
||||
### 2. 树表 CRUD
|
||||
|
||||
以 `src/views/demo/tree/index.vue`、`src/views/workflow/category/index.vue` 为主要起点。列表接口通常返回数组而不是 `PageResult`,页面使用 `handleTree`、`useTreeTableExpand`,`Query` 通常不继承 `PageQuery`。
|
||||
|
||||
### 3. 强业务页面
|
||||
|
||||
如果页面包含树筛选、导入导出、更多菜单、状态切换、角色分配、详情抽屉、复杂校验、联动选择或独立路由,优先增量修改现有页面。不要重写成简单 CRUD。
|
||||
|
||||
### 4. 工作流页面
|
||||
|
||||
workflow 目录优先参考 `src/views/workflow/*`。流程定义、流程实例、任务列表、请假申请等页面通常有业务按钮、弹窗和路由跳转,不要硬套 system 模块。
|
||||
|
||||
### 5. 只补 API 和 types
|
||||
|
||||
只维护 `src/api/<module>/<business>/index.ts` 与 `types.ts`,但仍要与后端路由、返回结构、当前模块导入方式和类型入口一致。
|
||||
|
||||
## 输出要求
|
||||
|
||||
使用本 skill 时,默认期望产出应满足:
|
||||
|
||||
- 类型完整,不把页面逻辑大量写成 `any`。
|
||||
- API 路径、函数名、权限标识与后端接口保持一致。
|
||||
- 标准页查询、重置、分页、弹窗、提交、删除、导出流程闭环完整。
|
||||
- 复杂页面保留原有交互能力和业务约束。
|
||||
- 代码体现当前项目 hooks、页面壳和下载方式,而不是 `gen` 模板裸输出。
|
||||
- 交付前说明运行过的验证命令;如果无法验证,说明原因。
|
||||
|
||||
## 快速检查清单
|
||||
|
||||
- `AxiosPromise` 是否来自 `@/utils/api-types`。
|
||||
- `PageResult` 是否来自 `@/api/types`。
|
||||
- API `params` 和 `data` 是否与后端方法一致。
|
||||
- 日期范围是否通过 `useDateRangeQuery` 或附近页面现有方式处理。
|
||||
- 列表 loading 是否通过 `useLoading` 或原页面方式维护。
|
||||
- 弹窗是否通过 `useFormDialog` 或原页面方式维护。
|
||||
- 多选状态是否通过 `useTableSelection` 或原页面方式维护。
|
||||
- 权限指令是否保持同文件一致,默认使用当前项目主流 `v-hasPermi`。
|
||||
- 导出是否使用 `requestDownload('<module>/<business>/export', { ...queryParams.value }, '<name>_<time>.xlsx')`。
|
||||
- 页面壳是否保留 `search-panel`、`table-panel`、`toolbar-shell`、`data-table`、`right-toolbar`、`pagination`。
|
||||
|
||||
## 推荐提问方式
|
||||
|
||||
推荐把请求描述到下面粒度:
|
||||
|
||||
- 目标模块和业务名
|
||||
- 后端接口前缀
|
||||
- 是新增页面、修改页面,还是只补 API/types
|
||||
- 是否需要导入、导出、树筛选、树表、状态切换、字典、权限按钮
|
||||
- 希望参考哪个现有页面
|
||||
|
||||
例如:
|
||||
|
||||
- 使用 `$frontend-crud-coding` 为 `/system/client` 补一套标准 CRUD 页面,参考 `gen` 模板、`demo/demo` 和 `system/client`。
|
||||
- 使用 `$frontend-crud-coding` 修改 `workflow/category` 列表页,增加导出按钮和状态筛选,保持当前 workflow 风格。
|
||||
@ -1,7 +0,0 @@
|
||||
interface:
|
||||
display_name: "前端编码"
|
||||
short_description: "按 plus-ui 6.X-Vue 真实代码和 gen 模板编写前端 CRUD"
|
||||
default_prompt: "使用 $frontend-crud-coding 先读取适用 reference,再按 plus-ui Gitee 仓库 6.X-Vue 分支的真实页面、hooks、API/types 约定和项目内 gen 模板实现前端修改。"
|
||||
|
||||
policy:
|
||||
allow_implicit_invocation: true
|
||||
@ -1,126 +0,0 @@
|
||||
# 使用案例
|
||||
|
||||
## 案例 1:新增标准 CRUD 页面
|
||||
|
||||
### 用户提问示例
|
||||
|
||||
```text
|
||||
使用 $frontend-crud-coding 为 system/client 补一套前端 CRUD 页面。
|
||||
后端接口已经有 /system/client/list、/system/client/{id}、POST /system/client、PUT /system/client、DELETE /system/client/{ids}。
|
||||
请参考 plus-ui Gitee 仓库 6.X-Vue 分支的项目内 gen 模板、src/views/demo/demo/index.vue 和现有 system/client 风格实现。
|
||||
```
|
||||
|
||||
### 期望执行方式
|
||||
|
||||
- 先看 `src/api/system/client/*` 和 `src/views/system/client/index.vue` 是否已存在。
|
||||
- 再看 `src/views/demo/demo/index.vue` 的标准 hooks 版 CRUD 骨架。
|
||||
- 对照项目内 `gen/api.ts.ftl`、`gen/types.ts.ftl`、`gen/index.vue.ftl`。
|
||||
- 生成或修改 `api/index.ts`、`types.ts`、`views/.../index.vue`。
|
||||
- 使用 `AxiosPromise` from `@/utils/api-types`、`PageResult` from `@/api/types`、`useLoading`、`useFormDialog`、`useSearchReset`、`useTableSelection`。
|
||||
|
||||
## 案例 2:新增树表页面
|
||||
|
||||
### 用户提问示例
|
||||
|
||||
```text
|
||||
使用 $frontend-crud-coding 为 demo/tree2 新增树表 CRUD,接口返回数组,字段包含 id、parentId、name、orderNum。
|
||||
参考 src/views/demo/tree/index.vue 和 workflow/category。
|
||||
```
|
||||
|
||||
### 期望执行方式
|
||||
|
||||
- 优先判断这是树表,不生成分页 `PageResult` 页面。
|
||||
- API 列表返回 `AxiosPromise<Tree2VO[]>`。
|
||||
- `Query` 不继承 `PageQuery`。
|
||||
- 页面使用 `handleTree`、`row-key`、`tree-props`、`useTreeTableExpand`、`el-tree-select`。
|
||||
- 新增子节点时从当前行带入 `parentId`。
|
||||
|
||||
## 案例 3:修改已有复杂列表页
|
||||
|
||||
### 用户提问示例
|
||||
|
||||
```text
|
||||
使用 $frontend-crud-coding 修改 system/user 页面:
|
||||
1. 新增一个创建时间快捷筛选
|
||||
2. 导出按钮保留在更多菜单中
|
||||
3. 保持现有树筛选、导入、列显隐、详情抽屉和角色分配不变
|
||||
```
|
||||
|
||||
### 期望执行方式
|
||||
|
||||
- 判断这是“已有复杂页面增强”,不是重新生成 CRUD。
|
||||
- 优先阅读 `src/views/system/user/index.vue`。
|
||||
- 保留 `TreePanel`、导入弹窗、`right-toolbar` 列显隐、`UserViewDrawer`、角色分配路由、权限控制。
|
||||
- 只增量修改搜索和查询参数处理。
|
||||
|
||||
## 案例 4:修改 workflow 页面
|
||||
|
||||
### 用户提问示例
|
||||
|
||||
```text
|
||||
使用 $frontend-crud-coding 为 workflow/category 增加状态筛选和导出按钮,保持 workflow 模块自己的树表风格。
|
||||
```
|
||||
|
||||
### 期望执行方式
|
||||
|
||||
- 优先看 `src/views/workflow/category/index.vue` 和 `src/api/workflow/category/*`。
|
||||
- 判断是否需要后端新增导出接口;前端导出路径保持 `workflow/category/export`。
|
||||
- 不迁移 system/user 的用户专属逻辑。
|
||||
- 保留树表、`useTreeTableExpand`、`handleTree` 和分类弹窗逻辑。
|
||||
|
||||
## 案例 5:只补 API 和 types
|
||||
|
||||
### 用户提问示例
|
||||
|
||||
```text
|
||||
使用 $frontend-crud-coding 为 monitor/cache 补全前端 API 和 types,页面先不改。
|
||||
```
|
||||
|
||||
### 期望执行方式
|
||||
|
||||
- 只维护 `src/api/monitor/cache/index.ts` 和 `src/api/monitor/cache/types.ts`。
|
||||
- 仍然检查同目录 monitor API 的 `export function` / `export const` 风格。
|
||||
- 返回类型使用 `AxiosPromise` from `@/utils/api-types`。
|
||||
- 不创建页面,不改路由。
|
||||
|
||||
## 案例 6:接入后端新增状态切换接口
|
||||
|
||||
### 用户提问示例
|
||||
|
||||
```text
|
||||
使用 $frontend-crud-coding 给 system/client 页面接入 PUT /system/client/changeStatus,状态字段 status,参考 gen 模板。
|
||||
```
|
||||
|
||||
### 期望执行方式
|
||||
|
||||
- API 增加 `changeClientStatus(id, status)`。
|
||||
- types 确认 `status` 类型是 string、number 还是 boolean。
|
||||
- 表格列用 `el-switch`,active/inactive 值跟后端字段类型一致。
|
||||
- 切换失败时回滚原状态。
|
||||
- 权限使用 `system:client:edit` 或后端实际权限。
|
||||
|
||||
## 推荐的高质量任务描述
|
||||
|
||||
```text
|
||||
使用 $frontend-crud-coding 在当前前端项目中新增 `/system/notice` 列表页增强:
|
||||
1. 保留现有页面
|
||||
2. 新增状态筛选和导出
|
||||
3. API 路径沿用后端接口
|
||||
4. 参考 system/config 的工具栏与导出交互
|
||||
5. 参考 plus-ui Gitee 仓库 6.X-Vue 分支的 gen 模板补齐缺失 types
|
||||
```
|
||||
|
||||
## 不推荐的任务描述
|
||||
|
||||
```text
|
||||
帮我写个后台页面
|
||||
```
|
||||
|
||||
更好的写法至少补充:
|
||||
|
||||
- 模块名
|
||||
- 业务名
|
||||
- 后端接口前缀
|
||||
- 是新增还是修改
|
||||
- 是否需要分页、导出、树表、字典、权限
|
||||
- 想参考哪个现有页面
|
||||
@ -1,156 +0,0 @@
|
||||
# 前端约定
|
||||
|
||||
## 优先参考的代码来源
|
||||
|
||||
- 默认远端基线:`https://gitee.com/JavaLionLi/plus-ui`,分支 `6.X-Vue`。引用远端文件时必须同时写明 `branch=6.X-Vue` 和仓库内路径。
|
||||
- 当前目标目录下最近似页面、API、types。
|
||||
- 标准单表:`src/views/demo/demo/index.vue`、`src/api/demo/demo/index.ts`、`src/api/demo/demo/types.ts`。
|
||||
- 树表:`src/views/demo/tree/index.vue`、`src/views/workflow/category/index.vue`。
|
||||
- 复杂系统页:`src/views/system/user/index.vue`、`src/views/system/role/index.vue`、`src/views/system/post/index.vue`、`src/views/system/config/index.vue`。
|
||||
- workflow 页:`src/views/workflow/*`、`src/api/workflow/*`。
|
||||
- 监控页:`src/views/monitor/*`、`src/api/monitor/*`。
|
||||
- 公共 hooks:`src/hooks/async/useLoading.ts`、`src/hooks/dialog/*`、`src/hooks/form/*`、`src/hooks/table/*`、`src/hooks/tree/*`。
|
||||
- 项目内 generator 模板:
|
||||
`gen/api.ts.ftl`
|
||||
`gen/types.ts.ftl`
|
||||
`gen/index.vue.ftl`
|
||||
`gen/index-tree.vue.ftl`
|
||||
|
||||
## 基础栈与格式
|
||||
|
||||
- 技术栈是 Vue 3 + TypeScript + Element Plus + Vite + Pinia。
|
||||
- 包管理按仓库现状使用 pnpm。
|
||||
- `.editorconfig` 要求 UTF-8、LF、2 空格缩进。
|
||||
- 当前仓库没有 `.prettierrc`;格式化使用 `pnpm run fmt`,lint 使用 `pnpm lint`。
|
||||
- 不要在一个页面里混入与仓库不一致的格式和写法。
|
||||
- 不要把本机绝对路径写进 skill 输出或参考文档;跨环境参考统一使用 Gitee 仓库 URL、分支和仓库内相对路径。
|
||||
|
||||
## API 文件规则
|
||||
|
||||
- 标准 API 文件放在 `src/api/<module>/<business>/index.ts`,同目录维护 `types.ts`。
|
||||
- import 顺序优先跟随附近文件,标准生成页常见形式:
|
||||
`import type { XxxForm, XxxQuery, XxxVO } from '@/api/<module>/<business>/types';`
|
||||
`import type { PageResult } from '@/api/types';`
|
||||
`import type { AxiosPromise } from '@/utils/api-types';`
|
||||
`import request from '@/utils/request';`
|
||||
- 不要从 `axios` 引入 `AxiosPromise`。
|
||||
- 列表分页接口通常返回 `AxiosPromise<PageResult<XxxVO>>`。
|
||||
- 树表列表接口通常返回 `AxiosPromise<XxxVO[]>`。
|
||||
- 详情接口返回 `AxiosPromise<XxxVO>`;复杂详情返回单独的 `InfoVO`。
|
||||
- 标准函数命名:
|
||||
`listXxx` -> `GET /<module>/<business>/list`
|
||||
`getXxx` -> `GET /<module>/<business>/{id}`
|
||||
`addXxx` -> `POST /<module>/<business>`
|
||||
`updateXxx` -> `PUT /<module>/<business>`
|
||||
`delXxx` -> `DELETE /<module>/<business>/{id or ids}`
|
||||
`changeXxxStatus` -> `PUT /<module>/<business>/changeStatus`
|
||||
- query string 用 `params`,请求体用 `data`。
|
||||
- 加密、防重复提交等 headers 直接写在请求配置里,例如用户重置密码中的 `isEncrypt`、`repeatSubmit`。
|
||||
- 当前仓库有些 API 使用 `export const`,有些使用 `export function`;新增标准 CRUD 优先跟随 `gen/api.ts.ftl` 和相邻模块。
|
||||
- 只有相邻模块已有 `export default { ... }` 聚合时才新增默认导出。
|
||||
|
||||
## 类型文件规则
|
||||
|
||||
- 标准类型定义 `VO`、`Form`、`Query`,必要时补 `InfoVO`、`TreeVO`、`ResetPwdForm` 等扩展类型。
|
||||
- `Form` 通常继承 `BaseEntity`。
|
||||
- 非树表 `Query` 通常继承 `PageQuery`。
|
||||
- 树表 `Query` 通常不继承 `PageQuery`。
|
||||
- ID 字段通常使用 `string | number`,批量删除参数使用 `string | number | Array<string | number>`。
|
||||
- Java 数值类型映射为 `number`,Boolean 映射为 `boolean`,日期/文本默认 `string`。
|
||||
- 日期范围查询保留 `params?: any`,不要因为它看起来宽松就删掉。
|
||||
- 列表对象、表单对象、查询对象职责分开;字段不一致时不要强行复用一个接口。
|
||||
- 能明确写出类型时不要用 `any`;组件库、字典或历史接口确实无法收窄时再保留。
|
||||
|
||||
## Vue 页面结构规则
|
||||
|
||||
- 页面优先使用 `<script setup name="Xxx" lang="ts">`。
|
||||
- 标准根节点使用 `class="p-2 app-container <module>-<business>-page"`;已有页面是特殊布局时保持原样。
|
||||
- 标准列表页结构:
|
||||
搜索卡片 `search-panel`
|
||||
表格卡片 `table-panel`
|
||||
工具栏 `toolbar-shell`
|
||||
表格 `data-table`
|
||||
`right-toolbar`
|
||||
`pagination`
|
||||
新增/编辑 `el-dialog`
|
||||
- 搜索区通过 `useSearchToggle` 控制 `showSearch`,头部点击切换。
|
||||
- 列表 loading 通过 `useLoading(true)` 和 `withLoading`。
|
||||
- 选择状态通过 `useTableSelection<XxxVO>(item => item.id)` 返回 `ids`、`single`、`multiple`、`handleSelectionChange`。
|
||||
- 表单弹窗优先使用 `useFormDialog({ form, formRef, initialFormData })`,返回 `dialog`、`resetForm`、`openDialog`、`showDialog`、`closeDialog`。
|
||||
- 仅需要简单弹窗状态或一个页面多个弹窗时使用 `useDialogState`。
|
||||
- 日期范围查询优先使用 `useDateRangeQuery()`;带后端参数名时使用 `useDateRangeQuery('CreateTime')` 等相邻页面模式。
|
||||
- 查询和表单状态通常放在 `reactive<PageData<Form, Query>>({ form, queryParams, rules })`,再 `toRefs(data)`。
|
||||
|
||||
## 页面行为规则
|
||||
|
||||
- `getList` 负责设置 loading、调用列表接口、回填列表和 `total`。
|
||||
- `handleQuery` 先把 `queryParams.value.pageNum = 1`,再调用 `getList()`;树表无分页时只调用 `getList()`。
|
||||
- `resetQuery` 使用 `useSearchReset`,分页页传 `pageNumKey: 'pageNum'`,需要时传 `pageSizeKey` 和 `resetExtras`。
|
||||
- `handleAdd` 使用 `openDialog('添加xxx')`;如果有树/联动选项,打开前后按现有页面加载选项。
|
||||
- `handleUpdate` 先 `reset()`,再按行或 `ids.value[0]` 查详情,`Object.assign(form.value, res.data)`,最后 `showDialog('修改xxx')`。
|
||||
- `submitForm` 表单校验通过后设置 `buttonLoading`,根据主键判断新增或修改,成功后 `modal.msgSuccess('操作成功')`、关闭弹窗、刷新列表。
|
||||
- `handleDelete` 使用 `modal.confirm(...)` 二次确认,再调用删除接口,成功提示并刷新。
|
||||
- `handleExport` 使用 `requestDownload('<module>/<business>/export', { ...queryParams.value }, '<business>_<timestamp>.xlsx')`。
|
||||
- 状态切换失败时要把 switch 值回滚,参考 generator 模板和现有 `system/user`、`system/role`。
|
||||
- 导入上传使用 `globalHeaders()`、`import.meta.env.VITE_APP_BASE_API`、`ElUpload`,优先参考 `system/user` 或流程定义页面。
|
||||
|
||||
## 字典、权限与公共工具
|
||||
|
||||
- 字典使用 `useDict`:
|
||||
`const { sys_normal_disable } = toRefs<any>(useDict('sys_normal_disable'));`
|
||||
- 新增代码默认使用当前项目主流 `v-hasPermi`。
|
||||
- 如果正在修改的文件已经混用或使用 `v-has-permi`,保持同文件现状,不为统一写法而重排无关代码。
|
||||
- `el-dropdown-item` 延迟加载导致权限指令不可靠时,使用 `v-if="checkPermi([...])"`,参考 `system/user`。
|
||||
- 常用工具:
|
||||
`modal` from `@/plugins/modal`
|
||||
`download as requestDownload` from `@/utils/request`
|
||||
`useDict` from `@/utils/dict`
|
||||
`checkPermi` from `@/utils/permission`
|
||||
`handleTree`、`parseStrEmpty` from `@/utils/ruoyi`
|
||||
|
||||
## 组件与样式规则
|
||||
|
||||
- 优先复用公共组件:`right-toolbar`、`pagination`、`DictTag` / `dict-tag`、`ImageUpload` / `image-upload`、`ImagePreview` / `image-preview`、`FileUpload` / `file-upload`、`Editor` / `editor`、`TreePanel`。
|
||||
- 标准页面尽量使用已有页面壳类,不堆大量内联样式。
|
||||
- 复杂页面需要 scoped SCSS 时优先复用:
|
||||
`@use '@/assets/styles/components/page-shell' as pageShell;`
|
||||
再按现有 mixin 使用。
|
||||
- 不要为了单页需求修改全局组件样式。
|
||||
- 类名保持模块语义:`system-client-page`、`workflow-category-page`、`demo-demo-page`。
|
||||
|
||||
## 树表规则
|
||||
|
||||
- 树表列表接口通常返回数组,页面通过 `handleTree<T>(res.data, 'id', 'parentId')` 组树。
|
||||
- 使用 `row-key`、`:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"`。
|
||||
- 展开/折叠使用 `useTreeTableExpand`。
|
||||
- 表单中上级节点使用 `el-tree-select`。
|
||||
- 新增子节点时从当前行回填 `parentId`。
|
||||
- 删除确认文案优先使用业务名称,而不是批量 ID 文案。
|
||||
|
||||
## 与 gen 模板的关系
|
||||
|
||||
- `gen` 是 plus-ui 前端项目内的生成模板;默认远端位置是 `https://gitee.com/JavaLionLi/plus-ui/tree/6.X-Vue/gen`,分支必须标记为 `6.X-Vue`。
|
||||
- 本地仓库存在对应文件时优先读本地 `gen`,但不要把本地绝对路径写入 skill 或交付内容。
|
||||
- 新增标准单表页面时读取 `gen/index.vue.ftl`、`gen/api.ts.ftl`、`gen/types.ts.ftl`。
|
||||
- 新增树表页面时读取 `gen/index-tree.vue.ftl`、`gen/api.ts.ftl`、`gen/types.ts.ftl`。
|
||||
- `gen` 模板是标准骨架,不是最终答案;落地时仍要对照目标模块真实页面和公共 hooks。
|
||||
- 当前前端项目已经把生成页升级为 hooks 版:`useLoading`、`useFormDialog`、`useSearchReset`、`useTableSelection`、`useDateRangeQuery`。
|
||||
- 新增标准 CRUD 时,先从 `gen` 确认字段、权限、导出、状态切换、排序、日期范围等,再落成当前项目的实际页面壳。
|
||||
- 修改已有页面时,不要把现有强业务逻辑替换回 `gen` 的简化逻辑。
|
||||
|
||||
## 验证规则
|
||||
|
||||
- 只改文档或 skill:运行 skill 基础校验即可。
|
||||
- 改前端 TS/Vue/API/types:优先运行 `pnpm exec vue-tsc --noEmit`。
|
||||
- 改页面模板、import、权限或较多文件:再运行 `pnpm lint`。
|
||||
- 改公共 hooks、组件、构建相关或大范围页面:再运行 `pnpm build`。
|
||||
- 如果验证因为环境、依赖或权限失败,交付时说明失败命令和原因。
|
||||
|
||||
## 避免事项
|
||||
|
||||
- 不要从 `axios` 引入 `AxiosPromise`。
|
||||
- 不要绕开 `request` 或 `requestDownload` 自造请求/下载封装。
|
||||
- 不要跳过 `types.ts`,把类型全写在页面里。
|
||||
- 不要删除日期范围 `params`、权限指令、导出、导入、树筛选、列显隐等现有能力。
|
||||
- 不要为了“更整洁”重写复杂页面的大块业务逻辑。
|
||||
- 不要在新增标准页里使用与仓库不一致的 UI 壳或状态管理方式。
|
||||
@ -1,6 +1,5 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = RuoYi-Vue-Plus后台管理系统
|
||||
VITE_APP_LOGO_TITLE = RuoYi-Vue-Plus
|
||||
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
|
||||
|
||||
# 开发环境配置
|
||||
VITE_APP_ENV = 'development'
|
||||
@ -12,31 +11,15 @@ VITE_APP_BASE_API = '/dev-api'
|
||||
VITE_APP_CONTEXT_PATH = '/'
|
||||
|
||||
# 监控地址
|
||||
VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications'
|
||||
VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications'
|
||||
|
||||
# SnailJob 控制台地址
|
||||
VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
|
||||
|
||||
# SnailAI 控制台地址
|
||||
VITE_APP_SNAILAI_ADMIN = 'http://localhost:8900/snail-ai'
|
||||
# powerjob 控制台地址
|
||||
VITE_APP_POWERJOB_ADMIN = 'http://localhost:7700/'
|
||||
|
||||
VITE_APP_PORT = 80
|
||||
|
||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||
VITE_APP_ENCRYPT = true
|
||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB'
|
||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PRIVATE_KEY = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A=='
|
||||
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||
|
||||
# 客户端id
|
||||
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
||||
|
||||
# 统一消息推送开关
|
||||
VITE_APP_MESSAGE_ENABLED = true
|
||||
|
||||
# sse / websocket
|
||||
VITE_APP_MESSAGE_TRANSPORT = 'sse'
|
||||
|
||||
# 统一消息推送路径
|
||||
VITE_APP_MESSAGE_PATH = '/resource/message'
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = RuoYi-Vue-Plus后台管理系统
|
||||
VITE_APP_LOGO_TITLE = RuoYi-Vue-Plus
|
||||
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'production'
|
||||
@ -9,13 +8,10 @@ VITE_APP_ENV = 'production'
|
||||
VITE_APP_CONTEXT_PATH = '/'
|
||||
|
||||
# 监控地址
|
||||
VITE_APP_MONITOR_ADMIN = '/admin/applications'
|
||||
VITE_APP_MONITRO_ADMIN = '/admin/applications'
|
||||
|
||||
# SnailJob 控制台地址
|
||||
VITE_APP_SNAILJOB_ADMIN = '/snail-job'
|
||||
|
||||
# SnailAI 控制台地址
|
||||
VITE_APP_SNAILAI_ADMIN = '/snail-ai'
|
||||
# powerjob 控制台地址
|
||||
VITE_APP_POWERJOB_ADMIN = '/powerjob'
|
||||
|
||||
# 生产环境
|
||||
VITE_APP_BASE_API = '/prod-api'
|
||||
@ -25,21 +21,8 @@ VITE_BUILD_COMPRESS = gzip
|
||||
|
||||
VITE_APP_PORT = 80
|
||||
|
||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||
VITE_APP_ENCRYPT = true
|
||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB'
|
||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PRIVATE_KEY = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A=='
|
||||
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||
|
||||
# 客户端id
|
||||
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
|
||||
|
||||
# 统一消息推送开关
|
||||
VITE_APP_MESSAGE_ENABLED = true
|
||||
|
||||
# sse / websocket
|
||||
VITE_APP_MESSAGE_TRANSPORT = 'sse'
|
||||
|
||||
# 统一消息推送路径
|
||||
VITE_APP_MESSAGE_PATH = '/resource/message'
|
||||
|
||||
17
.eslintignore
Normal file
@ -0,0 +1,17 @@
|
||||
*.sh
|
||||
node_modules
|
||||
*.md
|
||||
*.woff
|
||||
*.ttf
|
||||
.vscode
|
||||
.idea
|
||||
dist
|
||||
/public
|
||||
/docs
|
||||
.husky
|
||||
.local
|
||||
/bin
|
||||
.eslintrc.js
|
||||
prettier.config.js
|
||||
src/assets
|
||||
tailwind.config.js
|
||||
312
.eslintrc-auto-import.json
Normal file
@ -0,0 +1,312 @@
|
||||
{
|
||||
"globals": {
|
||||
"ComponentInternalInstance": true,
|
||||
"TransferKey": true,
|
||||
"ElFormRules": true,
|
||||
"CheckboxValueType": true,
|
||||
"PropType": true,
|
||||
"DateModelType": true,
|
||||
"UploadFile": true,
|
||||
"ElFormInstance": true,
|
||||
"ElTableInstance": true,
|
||||
"ElTreeInstance": true,
|
||||
"ElTreeSelectInstance": true,
|
||||
"ElSelectInstance": true,
|
||||
"ElUploadInstance": true,
|
||||
"ElCardInstance": true,
|
||||
"ElDialogInstance": true,
|
||||
"ElInputInstance": true,
|
||||
"ElInputNumberInstance": true,
|
||||
"ElRadioInstance": true,
|
||||
"ElRadioGroupInstance": true,
|
||||
"ElRadioButtonInstance": true,
|
||||
"ElCheckboxInstance": true,
|
||||
"ElCheckboxGroupInstance": true,
|
||||
"ElSwitchInstance": true,
|
||||
"ElDatePickerInstance": true,
|
||||
"ElTimePickerInstance": true,
|
||||
"ElTimeSelectInstance": true,
|
||||
"ElScrollbarInstance": true,
|
||||
"ElCascaderInstance": true,
|
||||
"ElColorPickerInstance": true,
|
||||
"ElRateInstance": true,
|
||||
"ElSliderInstance": true,
|
||||
"useRouter": true,
|
||||
"useRoute": true,
|
||||
"EffectScope": true,
|
||||
"ElTable": true,
|
||||
"ElSelect": true,
|
||||
"ElUpload": true,
|
||||
"ElForm": true,
|
||||
"ElTree": true,
|
||||
"ElMessage": true,
|
||||
"ElMessageBox": true,
|
||||
"asyncComputed": true,
|
||||
"autoResetRef": true,
|
||||
"computed": true,
|
||||
"computedAsync": true,
|
||||
"computedEager": true,
|
||||
"computedInject": true,
|
||||
"computedWithControl": true,
|
||||
"controlledComputed": true,
|
||||
"controlledRef": true,
|
||||
"createApp": true,
|
||||
"createEventHook": true,
|
||||
"createGlobalState": true,
|
||||
"createInjectionState": true,
|
||||
"createReactiveFn": true,
|
||||
"createSharedComposable": true,
|
||||
"createUnrefFn": true,
|
||||
"customRef": true,
|
||||
"debouncedRef": true,
|
||||
"debouncedWatch": true,
|
||||
"defineAsyncComponent": true,
|
||||
"defineComponent": true,
|
||||
"eagerComputed": true,
|
||||
"effectScope": true,
|
||||
"extendRef": true,
|
||||
"getCurrentInstance": true,
|
||||
"getCurrentScope": true,
|
||||
"h": true,
|
||||
"ignorableWatch": true,
|
||||
"inject": true,
|
||||
"isDefined": true,
|
||||
"isProxy": true,
|
||||
"isReactive": true,
|
||||
"isReadonly": true,
|
||||
"isRef": true,
|
||||
"makeDestructurable": true,
|
||||
"markRaw": true,
|
||||
"nextTick": true,
|
||||
"onActivated": true,
|
||||
"onBeforeMount": true,
|
||||
"onBeforeUnmount": true,
|
||||
"onBeforeUpdate": true,
|
||||
"onClickOutside": true,
|
||||
"onDeactivated": true,
|
||||
"onErrorCaptured": true,
|
||||
"onKeyStroke": true,
|
||||
"onLongPress": true,
|
||||
"onMounted": true,
|
||||
"onRenderTracked": true,
|
||||
"onRenderTriggered": true,
|
||||
"onScopeDispose": true,
|
||||
"onServerPrefetch": true,
|
||||
"onStartTyping": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"pausableWatch": true,
|
||||
"provide": true,
|
||||
"reactify": true,
|
||||
"reactifyObject": true,
|
||||
"reactive": true,
|
||||
"reactiveComputed": true,
|
||||
"reactiveOmit": true,
|
||||
"reactivePick": true,
|
||||
"readonly": true,
|
||||
"ref": true,
|
||||
"refAutoReset": true,
|
||||
"refDebounced": true,
|
||||
"refDefault": true,
|
||||
"refThrottled": true,
|
||||
"refWithControl": true,
|
||||
"resolveComponent": true,
|
||||
"resolveDirective": true,
|
||||
"resolveRef": true,
|
||||
"resolveUnref": true,
|
||||
"shallowReactive": true,
|
||||
"shallowReadonly": true,
|
||||
"shallowRef": true,
|
||||
"syncRef": true,
|
||||
"syncRefs": true,
|
||||
"templateRef": true,
|
||||
"throttledRef": true,
|
||||
"throttledWatch": true,
|
||||
"toRaw": true,
|
||||
"toReactive": true,
|
||||
"toRef": true,
|
||||
"toRefs": true,
|
||||
"triggerRef": true,
|
||||
"tryOnBeforeMount": true,
|
||||
"tryOnBeforeUnmount": true,
|
||||
"tryOnMounted": true,
|
||||
"tryOnScopeDispose": true,
|
||||
"tryOnUnmounted": true,
|
||||
"unref": true,
|
||||
"unrefElement": true,
|
||||
"until": true,
|
||||
"useActiveElement": true,
|
||||
"useArrayEvery": true,
|
||||
"useArrayFilter": true,
|
||||
"useArrayFind": true,
|
||||
"useArrayFindIndex": true,
|
||||
"useArrayFindLast": true,
|
||||
"useArrayJoin": true,
|
||||
"useArrayMap": true,
|
||||
"useArrayReduce": true,
|
||||
"useArraySome": true,
|
||||
"useArrayUnique": true,
|
||||
"useAsyncQueue": true,
|
||||
"useAsyncState": true,
|
||||
"useAttrs": true,
|
||||
"useBase64": true,
|
||||
"useBattery": true,
|
||||
"useBluetooth": true,
|
||||
"useBreakpoints": true,
|
||||
"useBroadcastChannel": true,
|
||||
"useBrowserLocation": true,
|
||||
"useCached": true,
|
||||
"useClipboard": true,
|
||||
"useCloned": true,
|
||||
"useColorMode": true,
|
||||
"useConfirmDialog": true,
|
||||
"useCounter": true,
|
||||
"useCssModule": true,
|
||||
"useCssVar": true,
|
||||
"useCssVars": true,
|
||||
"useCurrentElement": true,
|
||||
"useCycleList": true,
|
||||
"useDark": true,
|
||||
"useDateFormat": true,
|
||||
"useDebounce": true,
|
||||
"useDebounceFn": true,
|
||||
"useDebouncedRefHistory": true,
|
||||
"useDeviceMotion": true,
|
||||
"useDeviceOrientation": true,
|
||||
"useDevicePixelRatio": true,
|
||||
"useDevicesList": true,
|
||||
"useDisplayMedia": true,
|
||||
"useDocumentVisibility": true,
|
||||
"useDraggable": true,
|
||||
"useDropZone": true,
|
||||
"useElementBounding": true,
|
||||
"useElementByPoint": true,
|
||||
"useElementHover": true,
|
||||
"useElementSize": true,
|
||||
"useElementVisibility": true,
|
||||
"useEventBus": true,
|
||||
"useEventListener": true,
|
||||
"useEventSource": true,
|
||||
"useEyeDropper": true,
|
||||
"useFavicon": true,
|
||||
"useFetch": true,
|
||||
"useFileDialog": true,
|
||||
"useFileSystemAccess": true,
|
||||
"useFocus": true,
|
||||
"useFocusWithin": true,
|
||||
"useFps": true,
|
||||
"useFullscreen": true,
|
||||
"useGamepad": true,
|
||||
"useGeolocation": true,
|
||||
"useIdle": true,
|
||||
"useImage": true,
|
||||
"useInfiniteScroll": true,
|
||||
"useIntersectionObserver": true,
|
||||
"useInterval": true,
|
||||
"useIntervalFn": true,
|
||||
"useKeyModifier": true,
|
||||
"useLastChanged": true,
|
||||
"useLocalStorage": true,
|
||||
"useMagicKeys": true,
|
||||
"useManualRefHistory": true,
|
||||
"useMediaControls": true,
|
||||
"useMediaQuery": true,
|
||||
"useMemoize": true,
|
||||
"useMemory": true,
|
||||
"useMounted": true,
|
||||
"useMouse": true,
|
||||
"useMouseInElement": true,
|
||||
"useMousePressed": true,
|
||||
"useMutationObserver": true,
|
||||
"useNavigatorLanguage": true,
|
||||
"useNetwork": true,
|
||||
"useNow": true,
|
||||
"useObjectUrl": true,
|
||||
"useOffsetPagination": true,
|
||||
"useOnline": true,
|
||||
"usePageLeave": true,
|
||||
"useParallax": true,
|
||||
"usePermission": true,
|
||||
"usePointer": true,
|
||||
"usePointerLock": true,
|
||||
"usePointerSwipe": true,
|
||||
"usePreferredColorScheme": true,
|
||||
"usePreferredContrast": true,
|
||||
"usePreferredDark": true,
|
||||
"usePreferredLanguages": true,
|
||||
"usePreferredReducedMotion": true,
|
||||
"usePrevious": true,
|
||||
"useRafFn": true,
|
||||
"useRefHistory": true,
|
||||
"useResizeObserver": true,
|
||||
"useScreenOrientation": true,
|
||||
"useScreenSafeArea": true,
|
||||
"useScriptTag": true,
|
||||
"useScroll": true,
|
||||
"useScrollLock": true,
|
||||
"useSessionStorage": true,
|
||||
"useShare": true,
|
||||
"useSlots": true,
|
||||
"useSorted": true,
|
||||
"useSpeechRecognition": true,
|
||||
"useSpeechSynthesis": true,
|
||||
"useStepper": true,
|
||||
"useStorage": true,
|
||||
"useStorageAsync": true,
|
||||
"useStyleTag": true,
|
||||
"useSupported": true,
|
||||
"useSwipe": true,
|
||||
"useTemplateRefsList": true,
|
||||
"useTextDirection": true,
|
||||
"useTextSelection": true,
|
||||
"useTextareaAutosize": true,
|
||||
"useThrottle": true,
|
||||
"useThrottleFn": true,
|
||||
"useThrottledRefHistory": true,
|
||||
"useTimeAgo": true,
|
||||
"useTimeout": true,
|
||||
"useTimeoutFn": true,
|
||||
"useTimeoutPoll": true,
|
||||
"useTimestamp": true,
|
||||
"useTitle": true,
|
||||
"useToNumber": true,
|
||||
"useToString": true,
|
||||
"useToggle": true,
|
||||
"useTransition": true,
|
||||
"useUrlSearchParams": true,
|
||||
"useUserMedia": true,
|
||||
"useVModel": true,
|
||||
"useVModels": true,
|
||||
"useVibrate": true,
|
||||
"useVirtualList": true,
|
||||
"useWakeLock": true,
|
||||
"useWebNotification": true,
|
||||
"useWebSocket": true,
|
||||
"useWebWorker": true,
|
||||
"useWebWorkerFn": true,
|
||||
"useWindowFocus": true,
|
||||
"useWindowScroll": true,
|
||||
"useWindowSize": true,
|
||||
"watch": true,
|
||||
"watchArray": true,
|
||||
"watchAtMost": true,
|
||||
"watchDebounced": true,
|
||||
"watchEffect": true,
|
||||
"watchIgnorable": true,
|
||||
"watchOnce": true,
|
||||
"watchPausable": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true,
|
||||
"watchThrottled": true,
|
||||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"whenever": true,
|
||||
"ImportOption": true,
|
||||
"TreeType": true,
|
||||
"FieldOption": true,
|
||||
"PageData": true,
|
||||
"storeToRefs": true,
|
||||
"DictDataOption": true,
|
||||
"UploadOption": true
|
||||
}
|
||||
}
|
||||
42
.eslintrc.js
Normal file
@ -0,0 +1,42 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-essential',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'./.eslintrc-auto-import.json',
|
||||
'plugin:prettier/recommended'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: '2020',
|
||||
sourceType: 'module',
|
||||
parser: '@typescript-eslint/parser'
|
||||
},
|
||||
plugins: ['vue', '@typescript-eslint'],
|
||||
rules: {
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'vue/no-v-model-argument': 'off',
|
||||
'@typescript-eslint/ban-types': [
|
||||
'error',
|
||||
{
|
||||
// 关闭空类型检查 {}
|
||||
extendDefaults: true,
|
||||
types: {
|
||||
'{}': false,
|
||||
Function: false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
globals: {
|
||||
DialogOption: 'readonly',
|
||||
OptionType: 'readonly'
|
||||
}
|
||||
};
|
||||
1
.gitignore
vendored
@ -14,7 +14,6 @@ selenium-debug.log
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.iml
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||
"ignorePatterns": [
|
||||
"src/types/components.d.ts",
|
||||
"src/types/auto-imports.d.ts",
|
||||
".ai_state",
|
||||
".claude",
|
||||
".codex",
|
||||
"doc"
|
||||
],
|
||||
"printWidth": 120,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"arrowParens": "avoid",
|
||||
"htmlWhitespaceSensitivity": "ignore",
|
||||
"experimentalSortPackageJson": {
|
||||
"sortScripts": true
|
||||
},
|
||||
"sortImports": {
|
||||
"newlinesBetween": false,
|
||||
"groups": [
|
||||
"type-import",
|
||||
["value-builtin", "value-external"],
|
||||
"type-internal",
|
||||
"value-internal",
|
||||
["type-parent", "type-sibling", "type-index"],
|
||||
["value-parent", "value-sibling", "value-index"],
|
||||
"unknown"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
|
||||
"plugins": ["eslint", "typescript", "unicorn", "oxc", "import", "vue"],
|
||||
"rules": {
|
||||
"typescript/no-empty-function": "off",
|
||||
"typescript/no-explicit-any": "off",
|
||||
"typescript/no-unused-vars": "off",
|
||||
"typescript/no-this-alias": "off",
|
||||
"typescript/no-empty-object-type": "off",
|
||||
"typescript/no-unused-expressions": "off",
|
||||
"prefer-rest-params": "off",
|
||||
"import/no-unassigned-import": "off",
|
||||
"import/no-named-as-default-member": "off",
|
||||
"import/no-named-as-default": "off",
|
||||
"no-shadow": "off",
|
||||
"unicorn/prefer-add-event-listener": "off",
|
||||
"unicorn/consistent-function-scoping": "off",
|
||||
"unicorn/no-instanceof-builtins": "off"
|
||||
},
|
||||
"categories": {
|
||||
"correctness": "error",
|
||||
"suspicious": "error"
|
||||
},
|
||||
"ignorePatterns": [".ai_state", ".claude", ".codex", "doc", "dist/**", "dist-ssr/**", "coverage/**"]
|
||||
}
|
||||
9
.prettierignore
Normal file
@ -0,0 +1,9 @@
|
||||
/dist/*
|
||||
.local
|
||||
.output.js
|
||||
/node_modules/**
|
||||
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
|
||||
/public/*
|
||||
46
.prettierrc.cjs
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 代码格式化配置
|
||||
*/
|
||||
module.exports = {
|
||||
// 一行最多多少个字符
|
||||
printWidth: 150,
|
||||
// 指定每个缩进级别的空格数
|
||||
tabWidth: 2,
|
||||
// 使用制表符而不是空格缩进行
|
||||
useTabs: false,
|
||||
// 在语句末尾是否需要分号
|
||||
semi: true,
|
||||
// 是否使用单引号
|
||||
singleQuote: true,
|
||||
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
|
||||
quoteProps: 'as-needed',
|
||||
// 在JSX中使用单引号而不是双引号
|
||||
jsxSingleQuote: false,
|
||||
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
|
||||
trailingComma: 'none',
|
||||
// 在对象文字中的括号之间打印空格
|
||||
bracketSpacing: true,
|
||||
// jsx 标签的反尖括号需要换行
|
||||
jsxBracketSameLine: false,
|
||||
embeddedLanguageFormatting: 'off',
|
||||
// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
|
||||
arrowParens: 'always',
|
||||
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
|
||||
rangeStart: 0,
|
||||
rangeEnd: Infinity,
|
||||
// 指定要使用的解析器,不需要写文件开头的 @prettier
|
||||
requirePragma: false,
|
||||
// 不需要自动在文件开头插入 @prettier
|
||||
insertPragma: false,
|
||||
// 使用默认的折行标准 always\never\preserve
|
||||
proseWrap: 'preserve',
|
||||
// 指定HTML文件的全局空格敏感度 css\strict\ignore
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
// Vue文件脚本和样式标签缩进
|
||||
vueIndentScriptAndStyle: false,
|
||||
// 在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF),
|
||||
// 然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
|
||||
// 对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
|
||||
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
|
||||
endOfLine: 'auto'
|
||||
};
|
||||
109
README.md
@ -1,76 +1,73 @@
|
||||
## 平台简介
|
||||
|
||||
- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
|
||||
- 官方项目: 基于 React + Ant Design 版本前端项目 [plus-ui-react](https://gitee.com/JavaLionLi/plus-ui/tree/6.X-React/)
|
||||
- 成员项目: 基于 vben5(ant-design-vue) 的前端项目 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5)
|
||||
- 成员项目: 基于soybean 的前端项目 [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)
|
||||
|
||||
## 配套后端代码仓库地址
|
||||
|
||||
| 介绍 | 项目名 | 项目地址 |
|
||||
| ----------------- | :--------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| 🔥 分布式集群框架 | RuoYi-Vue-Plus | - [Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus)<br> - [GitHub](https://github.com/dromara/RuoYi-Vue-Plus)<br> - [GitCode](https://gitcode.com/dromara/RuoYi-Vue-Plus) |
|
||||
| 🔥 微服务框架 | RuoYi-Cloud-Plus | - [Gitee](https://gitee.com/dromara/RuoYi-Cloud-Plus)<br>- [GitHub](https://github.com/dromara/RuoYi-Cloud-Plus)<br> - [GitCode](https://gitcode.com/dromara/RuoYi-Cloud-Plus) |
|
||||
|
||||
## 分支说明
|
||||
|
||||
- 6.X分支(稳定发布主分支 生产可用)
|
||||
- dev分支(开发分支 开发过程中使用)
|
||||
* 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
|
||||
* 配套后端代码仓库地址
|
||||
* [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
* [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
|
||||
|
||||
## 前端运行
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone https://gitee.com/JavaLionLi/plus-ui.git
|
||||
|
||||
# 安装依赖
|
||||
pnpm install --registry=https://registry.npmmirror.com
|
||||
npm install --registry=https://registry.npmmirror.com
|
||||
|
||||
# 启动服务
|
||||
pnpm dev
|
||||
|
||||
# 构建生产环境
|
||||
pnpm build:prod
|
||||
npm run dev
|
||||
|
||||
# 构建生产环境 yarn build:prod
|
||||
# 前端访问地址 http://localhost:80
|
||||
```
|
||||
|
||||
## 本框架与RuoYi的业务差异
|
||||
|
||||
| 业务 | 功能说明 | 本框架 | RuoYi |
|
||||
| ------------ | ------------------------------------------------------------- | ------ | ----------------------------- |
|
||||
| 用户管理 | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等 | 支持 | 支持 |
|
||||
| 部门管理 | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限 | 支持 | 支持 |
|
||||
| 岗位管理 | 配置系统用户所属担任职务 | 支持 | 支持 |
|
||||
| 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等 | 支持 | 支持 |
|
||||
| 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | 支持 | 支持 |
|
||||
| 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | 支持 | 支持 |
|
||||
| 参数管理 | 对系统动态配置常用参数 | 支持 | 支持 |
|
||||
| 通知公告 | 系统通知公告信息发布维护 | 支持 | 支持 |
|
||||
| 操作日志 | 系统正常操作日志记录和查询 系统异常信息日志记录和查询 | 支持 | 支持 |
|
||||
| 登录日志 | 系统登录日志记录查询包含登录异常 | 支持 | 支持 |
|
||||
| 文件管理 | 系统文件展示、上传、下载、删除等管理 | 支持 | 无 |
|
||||
| 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理 | 支持 | 无 |
|
||||
| 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作 | 支持 | 支持 |
|
||||
| 定时任务 | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等 | 支持 | 仅支持任务与日志管理 |
|
||||
| 代码生成 | 多数据源前后端代码的生成(java、html、xml、sql)支持CRUD下载 | 支持 | 仅支持单数据源 |
|
||||
| 系统接口 | 根据业务代码自动生成相关的api接口文档 | 支持 | 支持 |
|
||||
| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等 | 支持 | 仅支持单机CPU、内存、磁盘监控 |
|
||||
| 缓存监控 | 对系统的缓存信息查询,命令统计等。 | 支持 | 支持 |
|
||||
| 在线构建器 | 拖动表单元素生成相应的HTML代码。 | 支持 | 支持 |
|
||||
| 使用案例 | 系统的一些功能案例 | 支持 | 不支持 |
|
||||
| 业务 | 功能说明 | 本框架 | RuoYi |
|
||||
|--------|-----------------------------------------|-----|------------------|
|
||||
| 租户管理 | 系统内租户的管理 如:租户套餐、过期时间、用户数量、企业信息等 | 支持 | 无 |
|
||||
| 租户套餐管理 | 系统内租户所能使用的套餐管理 如:套餐内所包含的菜单等 | 支持 | 无 |
|
||||
| 用户管理 | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等 | 支持 | 支持 |
|
||||
| 部门管理 | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限 | 支持 | 支持 |
|
||||
| 岗位管理 | 配置系统用户所属担任职务 | 支持 | 支持 |
|
||||
| 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等 | 支持 | 支持 |
|
||||
| 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | 支持 | 支持 |
|
||||
| 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | 支持 | 支持 |
|
||||
| 参数管理 | 对系统动态配置常用参数 | 支持 | 支持 |
|
||||
| 通知公告 | 系统通知公告信息发布维护 | 支持 | 支持 |
|
||||
| 操作日志 | 系统正常操作日志记录和查询 系统异常信息日志记录和查询 | 支持 | 支持 |
|
||||
| 登录日志 | 系统登录日志记录查询包含登录异常 | 支持 | 支持 |
|
||||
| 文件管理 | 系统文件展示、上传、下载、删除等管理 | 支持 | 无 |
|
||||
| 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理 | 支持 | 无 |
|
||||
| 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作 | 支持 | 支持 |
|
||||
| 定时任务 | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等 | 支持 | 仅支持任务与日志管理 |
|
||||
| 代码生成 | 多数据源前后端代码的生成(java、html、xml、sql)支持CRUD下载 | 支持 | 仅支持单数据源 |
|
||||
| 系统接口 | 根据业务代码自动生成相关的api接口文档 | 支持 | 支持 |
|
||||
| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等 | 支持 | 仅支持单机CPU、内存、磁盘监控 |
|
||||
| 缓存监控 | 对系统的缓存信息查询,命令统计等。 | 支持 | 支持 |
|
||||
| 在线构建器 | 拖动表单元素生成相应的HTML代码。 | 支持 | 支持 |
|
||||
| 使用案例 | 系统的一些功能案例 | 支持 | 不支持 |
|
||||
|
||||
## 演示图例
|
||||
|
||||
| | |
|
||||
|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|
||||
12
bin/build.bat
Normal file
@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
echo.
|
||||
echo [信息] 打包Web工程,生成dist文件。
|
||||
echo.
|
||||
|
||||
%~d0
|
||||
cd %~dp0
|
||||
|
||||
cd ..
|
||||
yarn build:prod
|
||||
|
||||
pause
|
||||
12
bin/package.bat
Normal file
@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
echo.
|
||||
echo [信息] 安装Web工程,生成node_modules文件。
|
||||
echo.
|
||||
|
||||
%~d0
|
||||
cd %~dp0
|
||||
|
||||
cd ..
|
||||
yarn --registry=https://registry.npmmirror.com
|
||||
|
||||
pause
|
||||
12
bin/run-web.bat
Normal file
@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
echo.
|
||||
echo [信息] 使用 Vite 命令运行 Web 工程。
|
||||
echo.
|
||||
|
||||
%~d0
|
||||
cd %~dp0
|
||||
|
||||
cd ..
|
||||
yarn dev
|
||||
|
||||
pause
|
||||
22
commitlint.config.js
Normal file
@ -0,0 +1,22 @@
|
||||
module.exports = {
|
||||
extends: ['@commitlint/config-conventional'],
|
||||
rules: {
|
||||
'type-enum': [
|
||||
2,
|
||||
'always',
|
||||
[
|
||||
'feat', // 新功能 feature
|
||||
'fix', // 修复 bug
|
||||
'docs', // 文档注释
|
||||
'style', // 代码格式
|
||||
'refactor', // 重构
|
||||
'perf', // 性能优化
|
||||
'test', // 增加测试
|
||||
'chore', // 构建过程或辅助工具的变动
|
||||
'revert', // 回退
|
||||
'build' // 打包
|
||||
]
|
||||
],
|
||||
'subject-case': [0]
|
||||
}
|
||||
};
|
||||
104
gen/api.ts.ftl
@ -1,104 +0,0 @@
|
||||
import type { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
|
||||
<#if !table.tree>
|
||||
import type { PageResult } from '@/api/types';
|
||||
</#if>
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 查询${functionName}列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const list${BusinessName} = (query?: ${BusinessName}Query): AxiosPromise<<#if table.tree>${BusinessName}VO[]<#else>PageResult<${BusinessName}VO></#if>> => {
|
||||
return request({
|
||||
url: '/${moduleName}/${businessName}/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询${functionName}详细
|
||||
* @param ${pkColumn.javaField}
|
||||
*/
|
||||
export const get${BusinessName} = (${pkColumn.javaField}: string | number): AxiosPromise<${BusinessName}VO> => {
|
||||
return request({
|
||||
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增${functionName}
|
||||
* @param data
|
||||
*/
|
||||
export const add${BusinessName} = (data: ${BusinessName}Form) => {
|
||||
return request({
|
||||
url: '/${moduleName}/${businessName}',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改${functionName}
|
||||
* @param data
|
||||
*/
|
||||
export const update${BusinessName} = (data: ${BusinessName}Form) => {
|
||||
return request({
|
||||
url: '/${moduleName}/${businessName}',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
<#if enableStatus>
|
||||
/**
|
||||
* 修改${functionName}状态
|
||||
* @param ${pkColumn.javaField}
|
||||
* @param status
|
||||
*/
|
||||
export const change${BusinessName}Status = (${pkColumn.javaField}: string | number, status: <#if statusColumn.javaType == 'Boolean'>boolean<#elseif statusColumn.javaType == 'String'>string<#else> number</#if>) => {
|
||||
return request({
|
||||
url: '/${moduleName}/${businessName}/changeStatus',
|
||||
method: 'put',
|
||||
data: {
|
||||
${pkColumn.javaField},
|
||||
${statusField}: status
|
||||
}
|
||||
});
|
||||
};
|
||||
</#if>
|
||||
|
||||
<#if enableSort>
|
||||
/**
|
||||
* 调整${functionName}排序
|
||||
* @param ${pkColumn.javaField}
|
||||
* @param sortValue
|
||||
*/
|
||||
export const update${BusinessName}Sort = (${pkColumn.javaField}: string | number, sortValue: <#if sortColumn.javaType == 'String' || sortColumn.javaType == 'LocalDateTime'>string<#else> number</#if>) => {
|
||||
return request({
|
||||
url: '/${moduleName}/${businessName}/updateSort',
|
||||
method: 'put',
|
||||
data: {
|
||||
${pkColumn.javaField},
|
||||
${sortField}: sortValue
|
||||
}
|
||||
});
|
||||
};
|
||||
</#if>
|
||||
|
||||
/**
|
||||
* 删除${functionName}
|
||||
* @param ${pkColumn.javaField}
|
||||
*/
|
||||
export const del${BusinessName} = (${pkColumn.javaField}: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -1,691 +0,0 @@
|
||||
<template>
|
||||
<div class="p-2 page-shell ${moduleName}-${businessName}-page">
|
||||
<div class="search-wrap">
|
||||
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
|
||||
<template #header>
|
||||
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
|
||||
<div><h3>筛选条件</h3></div>
|
||||
</div>
|
||||
</template>
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
|
||||
<#list columns as column>
|
||||
<#if column.query>
|
||||
<#if column.htmlType == "input" || column.htmlType == "textarea">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input v-model="queryParams.${column.javaField}" placeholder="请输入${column.columnLabel}" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "inputNumber">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input-number v-model="queryParams.${column.javaField}" controls-position="right" />
|
||||
</el-form-item>
|
||||
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
|
||||
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "switch" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
|
||||
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "switch">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
|
||||
<#if column.javaType == "Boolean">
|
||||
<el-option label="是" :value="true" />
|
||||
<el-option label="否" :value="false" />
|
||||
<#elseif column.javaType == "Integer" || column.javaType == "Long">
|
||||
<el-option label="开启" :value="0" />
|
||||
<el-option label="关闭" :value="1" />
|
||||
<#else>
|
||||
<el-option label="开启" value="0" />
|
||||
<el-option label="关闭" value="1" />
|
||||
</#if>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable>
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "datetime" && column.queryType != "BETWEEN">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-date-picker clearable
|
||||
v-model="queryParams.${column.javaField}"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="选择${column.columnLabel}"
|
||||
/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "datetime" && column.queryType == "BETWEEN">
|
||||
<el-form-item label="${column.columnLabel}" style="width: 308px">
|
||||
<el-date-picker
|
||||
v-model="dateRange${column.capJavaField}"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
|
||||
/>
|
||||
</el-form-item>
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card shadow="hover" class="table-panel">
|
||||
<template #header>
|
||||
<div class="toolbar-shell">
|
||||
<div class="table-heading">
|
||||
<h3>${functionName}列表</h3>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
|
||||
<el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
|
||||
<#if enableExport>
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['${moduleName}:${businessName}:export']">导出</el-button>
|
||||
</#if>
|
||||
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
ref="${businessName}TableRef"
|
||||
v-loading="loading"
|
||||
class="data-table"
|
||||
:data="${businessName}List"
|
||||
row-key="${treeCode}"
|
||||
border
|
||||
:default-expand-all="isExpandAll"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<#assign firstTreeListField = "">
|
||||
<#list columns as tempColumn>
|
||||
<#if !tempColumn.pk && tempColumn.list && "" != tempColumn.javaField && firstTreeListField == "">
|
||||
<#assign firstTreeListField = tempColumn.javaField>
|
||||
</#if>
|
||||
</#list>
|
||||
<#list columns as column>
|
||||
<#if column.pk>
|
||||
<#elseif enableStatus && statusField == column.javaField>
|
||||
<#if column.javaField == firstTreeListField>
|
||||
<el-table-column label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<#else>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
|
||||
</#if>
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.${column.javaField}"
|
||||
:active-value="${statusField}ActiveValue"
|
||||
:inactive-value="${statusField}InactiveValue"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif enableSort && sortField == column.javaField>
|
||||
<#if column.javaField == firstTreeListField>
|
||||
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" width="160">
|
||||
<#else>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="160">
|
||||
</#if>
|
||||
<template #default="scope">
|
||||
<#if column.javaType == "LocalDateTime">
|
||||
<el-date-picker
|
||||
v-model="scope.row.${column.javaField}"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择${column.columnLabel}"
|
||||
@change="handleSortChange(scope.row)"
|
||||
/>
|
||||
<#else>
|
||||
<el-input-number v-model="scope.row.${column.javaField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
|
||||
</#if>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.htmlType == "switch">
|
||||
<#if column.javaField == firstTreeListField>
|
||||
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" width="120">
|
||||
<#else>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="120">
|
||||
</#if>
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.${column.javaField}"
|
||||
<#if column.javaType == "Boolean">
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
<#elseif column.javaType == "Integer" || column.javaType == "Long">
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
<#else>
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
</#if>
|
||||
disabled
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.htmlType == "datetime">
|
||||
<#if column.javaField == firstTreeListField>
|
||||
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" width="180">
|
||||
<#else>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="180">
|
||||
</#if>
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.${column.javaField}, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.htmlType == "imageUpload">
|
||||
<#if column.javaField == firstTreeListField>
|
||||
<el-table-column label="${column.columnLabel}" prop="${column.javaField}Url" width="100">
|
||||
<#else>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}Url" width="100">
|
||||
</#if>
|
||||
<template #default="scope">
|
||||
<image-preview :src="scope.row.${column.javaField}Url" :width="50" :height="50"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.dictColumn>
|
||||
<#if column.javaField == firstTreeListField>
|
||||
<el-table-column label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<#else>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
|
||||
</#if>
|
||||
<template #default="scope">
|
||||
<#if column.htmlType == "checkbox">
|
||||
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField} ? scope.row.${column.javaField}.split(',') : []"/>
|
||||
<#else>
|
||||
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField}"/>
|
||||
</#if>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && "" != column.javaField>
|
||||
<#if column.javaField == firstTreeListField>
|
||||
<el-table-column label="${column.columnLabel}" prop="${column.javaField}" />
|
||||
<#else>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" />
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
<#if enableStatus && !statusColumn.list>
|
||||
<el-table-column label="${statusColumn.columnComment}" align="center" prop="${statusField}">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.${statusField}"
|
||||
:active-value="${statusField}ActiveValue"
|
||||
:inactive-value="${statusField}InactiveValue"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</#if>
|
||||
<#if enableSort && !sortColumn.list>
|
||||
<el-table-column label="${sortColumn.columnComment}" align="center" prop="${sortField}" width="160">
|
||||
<template #default="scope">
|
||||
<#if sortColumn.javaType == "LocalDateTime">
|
||||
<el-date-picker
|
||||
v-model="scope.row.${sortField}"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择${sortColumn.columnComment}"
|
||||
@change="handleSortChange(scope.row)"
|
||||
/>
|
||||
<#else>
|
||||
<el-input-number v-model="scope.row.${sortField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
|
||||
</#if>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</#if>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="新增" placement="top">
|
||||
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']" />
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
<!-- 添加或修改${functionName}对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="${businessName}FormRef" :model="form" :rules="rules" label-width="80px">
|
||||
<#list columns as column>
|
||||
<#if (column.insert || column.edit) && !column.pk>
|
||||
<#if "" != treeParentCode && column.javaField == treeParentCode>
|
||||
<el-form-item label="${column.columnLabel}" prop="${treeParentCode}">
|
||||
<el-tree-select
|
||||
v-model="form.${treeParentCode}"
|
||||
:data="${businessName}Options"
|
||||
:props="{ value: '${treeCode}', label: '${treeName}', children: 'children' } as any"
|
||||
value-key="${treeCode}"
|
||||
placeholder="请选择${column.columnLabel}"
|
||||
check-strictly
|
||||
/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "input">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input v-model="form.${column.javaField}" placeholder="请输入${column.columnLabel}" />
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "inputNumber">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input-number v-model="form.${column.javaField}" controls-position="right" />
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "imageUpload">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<image-upload v-model="form.${column.javaField}"/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "fileUpload">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<file-upload v-model="form.${column.javaField}"/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "editor">
|
||||
<el-form-item label="${column.columnLabel}">
|
||||
<editor v-model="form.${column.javaField}" :min-height="192"/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "select" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
|
||||
<el-option
|
||||
v-for="dict in ${column.dictType}"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
<#if column.javaType == "Integer" || column.javaType == "Long">
|
||||
:value="parseInt(dict.value)"
|
||||
<#else>
|
||||
:value="dict.value"
|
||||
</#if>
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "select" && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-checkbox-group v-model="form.${column.javaField}">
|
||||
<el-checkbox
|
||||
v-for="dict in ${column.dictType}"
|
||||
:key="dict.value"
|
||||
:label="dict.value">
|
||||
{{dict.label}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "checkbox" && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-checkbox-group v-model="form.${column.javaField}">
|
||||
<el-checkbox>请选择字典生成</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "radio" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-radio-group v-model="form.${column.javaField}">
|
||||
<el-radio
|
||||
v-for="dict in ${column.dictType}"
|
||||
:key="dict.value"
|
||||
<#if column.javaType == "Integer" || column.javaType == "Long">
|
||||
:value="parseInt(dict.value)"
|
||||
<#else>
|
||||
:value="dict.value"
|
||||
</#if>
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "radio" && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-radio-group v-model="form.${column.javaField}">
|
||||
<el-radio value="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "switch">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-switch
|
||||
v-model="form.${column.javaField}"
|
||||
<#if column.javaType == "Boolean">
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
<#elseif column.javaType == "Integer" || column.javaType == "Long">
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
<#else>
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
</#if>
|
||||
/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "datetime">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-date-picker clearable
|
||||
v-model="form.${column.javaField}"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择${column.columnLabel}"
|
||||
/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "textarea">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input v-model="form.${column.javaField}" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="${BusinessName}" lang="ts">
|
||||
import {
|
||||
add${BusinessName},
|
||||
<#if enableStatus>
|
||||
change${BusinessName}Status,
|
||||
</#if>
|
||||
del${BusinessName},
|
||||
get${BusinessName},
|
||||
list${BusinessName},
|
||||
<#if enableSort>
|
||||
update${BusinessName}Sort,
|
||||
</#if>
|
||||
update${BusinessName}
|
||||
} from '@/api/${moduleName}/${businessName}';
|
||||
import { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
|
||||
import { useLoading } from '@/hooks/async/useLoading';
|
||||
import { useFormDialog } from '@/hooks/dialog/useFormDialog';
|
||||
<#if needAddDateRange>
|
||||
import { useDateRangeQuery } from '@/hooks/form/useDateRangeQuery';
|
||||
</#if>
|
||||
import { useSearchReset } from '@/hooks/form/useSearchReset';
|
||||
import { useSearchToggle } from '@/hooks/form/useSearchToggle';
|
||||
import { useTreeTableExpand } from '@/hooks/tree/useTreeTableExpand';
|
||||
<#if needDict>
|
||||
import { useDict } from '@/utils/dict';
|
||||
</#if>
|
||||
import modal from '@/plugins/modal';
|
||||
import { handleTree } from '@/utils/ruoyi';
|
||||
<#if enableExport>
|
||||
import { download as requestDownload } from '@/utils/request';
|
||||
</#if>
|
||||
|
||||
<#if needDict>
|
||||
const { ${dictsNoSymbol} } = toRefs<any>(useDict(${dicts}));
|
||||
</#if>
|
||||
|
||||
<#if enableStatus>
|
||||
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
|
||||
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
|
||||
</#if>
|
||||
|
||||
type ${BusinessName}Option = {
|
||||
${treeCode}: <#if treeParentColumn.javaType == 'String'>string<#else> number</#if>;
|
||||
${treeName}: string;
|
||||
children?: ${BusinessName}Option[];
|
||||
};
|
||||
|
||||
const ${businessName}List = ref<${BusinessName}VO[]>([]);
|
||||
const ${businessName}Options = ref<${BusinessName}Option[]>([]);
|
||||
const all${BusinessName}Options = ref<${BusinessName}Option[]>([]);
|
||||
const buttonLoading = ref(false);
|
||||
const { showSearch } = useSearchToggle();
|
||||
const { loading, setLoading, withLoading } = useLoading();
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const ${businessName}FormRef = ref<ElFormInstance>();
|
||||
const ${businessName}TableRef = ref<ElTableInstance>();
|
||||
const { isExpandAll, handleToggleExpandAll } = useTreeTableExpand<${BusinessName}VO>({
|
||||
tableRef: ${businessName}TableRef,
|
||||
data: ${businessName}List
|
||||
});
|
||||
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
|
||||
const {
|
||||
dateRange: dateRange${column.capJavaField},
|
||||
applyDateRange: apply${column.capJavaField}DateRange,
|
||||
resetDateRange: reset${column.capJavaField}DateRange
|
||||
} = useDateRangeQuery('${column.capJavaField}');
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
const initFormData: ${BusinessName}Form = {
|
||||
<#list columns as column>
|
||||
<#if column.insert || column.edit>
|
||||
<#if column.htmlType == "checkbox">
|
||||
${column.javaField}: [],
|
||||
<#else>
|
||||
${column.javaField}: undefined,
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
|
||||
const data = reactive<PageData<${BusinessName}Form, ${BusinessName}Query>>({
|
||||
form: {...initFormData},
|
||||
queryParams: {
|
||||
<#list columns as column>
|
||||
<#if column.query>
|
||||
<#if column.htmlType != "datetime" || column.queryType != "BETWEEN">
|
||||
${column.javaField}: undefined,
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
params: {
|
||||
<#list columns as column>
|
||||
<#if column.query>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
|
||||
${column.javaField}: undefined,
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
<#list columns as column>
|
||||
<#if column.insert || column.edit>
|
||||
<#if column.required>
|
||||
${column.javaField}: [
|
||||
{ required: true, message: "${column.columnLabel}不能为空", trigger: <#if column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch" || column.htmlType == "inputNumber">"change"<#else>"blur"</#if> }
|
||||
],
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
const { dialog, resetForm: reset, openDialog, showDialog, closeDialog } = useFormDialog({
|
||||
form,
|
||||
formRef: ${businessName}FormRef,
|
||||
initialFormData: initFormData
|
||||
});
|
||||
|
||||
/** 查询${functionName}列表 */
|
||||
const getList = async () => {
|
||||
await withLoading(async () => {
|
||||
<#if needAddDateRange>
|
||||
let params = queryParams.value;
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
|
||||
params = apply${column.capJavaField}DateRange(params);
|
||||
</#if>
|
||||
</#list>
|
||||
const res = await list${BusinessName}(params);
|
||||
<#else>
|
||||
const res = await list${BusinessName}(queryParams.value);
|
||||
</#if>
|
||||
const data = handleTree<${BusinessName}VO>(res.data, '${treeCode}', '${treeParentCode}');
|
||||
if (data) {
|
||||
${businessName}List.value = data;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 查询${functionName}下拉树结构 */
|
||||
const getTreeselect = async (excludeId?: string | number) => {
|
||||
const res = await list${BusinessName}();
|
||||
const data: ${BusinessName}Option = { ${treeCode}: ${treeRootValueTsLiteral}, ${treeName}: '顶级节点', children: [] };
|
||||
data.children = handleTree<${BusinessName}Option>(res.data, '${treeCode}', '${treeParentCode}');
|
||||
all${BusinessName}Options.value = [data];
|
||||
${businessName}Options.value = excludeId != null ? filterTreeOptions(all${BusinessName}Options.value, excludeId) : all${BusinessName}Options.value;
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset();
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
getList();
|
||||
};
|
||||
|
||||
const { resetQuery } = useSearchReset({
|
||||
queryFormRef,
|
||||
queryParams,
|
||||
resetExtras: () => {
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
|
||||
reset${column.capJavaField}DateRange();
|
||||
</#if>
|
||||
</#list>
|
||||
},
|
||||
afterReset: () => {
|
||||
handleQuery();
|
||||
}
|
||||
});
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = (row?: Partial<${BusinessName}VO>) => {
|
||||
openDialog('添加${functionName}');
|
||||
getTreeselect();
|
||||
if (row != null && row.${treeCode}) {
|
||||
form.value.${treeParentCode} = row.${treeCode};
|
||||
} else {
|
||||
form.value.${treeParentCode} = ${treeRootValueTsLiteral};
|
||||
}
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row: Partial<${BusinessName}VO>) => {
|
||||
reset();
|
||||
await getTreeselect(row.${treeCode});
|
||||
if (row != null) {
|
||||
form.value.${treeParentCode} = row.${treeParentCode};
|
||||
}
|
||||
const res = await get${BusinessName}(row.${pkColumn.javaField});
|
||||
Object.assign(form.value, res.data);
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "checkbox">
|
||||
form.value.${column.javaField} = form.value.${column.javaField}.split(",");
|
||||
</#if>
|
||||
</#list>
|
||||
showDialog('修改${functionName}');
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
${businessName}FormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "checkbox">
|
||||
form.value.${column.javaField} = form.value.${column.javaField}.join(",");
|
||||
</#if>
|
||||
</#list>
|
||||
if (form.value.${pkColumn.javaField}) {
|
||||
await update${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await add${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
modal.msgSuccess('操作成功');
|
||||
closeDialog();
|
||||
await getList();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row: Partial<${BusinessName}VO>) => {
|
||||
await modal.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?');
|
||||
setLoading(true);
|
||||
await del${BusinessName}(row.${pkColumn.javaField}).finally(() => setLoading(false));
|
||||
await getList();
|
||||
modal.msgSuccess('删除成功');
|
||||
};
|
||||
|
||||
const filterTreeOptions = (options: ${BusinessName}Option[], excludeId: string | number): ${BusinessName}Option[] => {
|
||||
return options
|
||||
.filter(item => item.${treeCode} !== excludeId)
|
||||
.map(item => ({
|
||||
...item,
|
||||
children: item.children ? filterTreeOptions(item.children, excludeId) : []
|
||||
}));
|
||||
};
|
||||
|
||||
<#if enableStatus>
|
||||
/** 状态修改 */
|
||||
const handleStatusChange = async (row: Partial<${BusinessName}VO>) => {
|
||||
const text = row.${statusField} === ${statusField}ActiveValue ? '启用' : '停用';
|
||||
try {
|
||||
await modal.confirm('确认要"' + text + '"吗?');
|
||||
await change${BusinessName}Status(row.${pkColumn.javaField}, row.${statusField});
|
||||
modal.msgSuccess(text + '成功');
|
||||
} catch (err) {
|
||||
row.${statusField} = row.${statusField} === ${statusField}ActiveValue ? ${statusField}InactiveValue : ${statusField}ActiveValue;
|
||||
}
|
||||
};
|
||||
</#if>
|
||||
|
||||
<#if enableSort>
|
||||
/** 排序调整 */
|
||||
const handleSortChange = async (row: Partial<${BusinessName}VO>) => {
|
||||
try {
|
||||
await update${BusinessName}Sort(row.${pkColumn.javaField}, row.${sortField});
|
||||
modal.msgSuccess('排序更新成功');
|
||||
} catch (err) {
|
||||
await getList();
|
||||
}
|
||||
};
|
||||
</#if>
|
||||
|
||||
<#if enableExport>
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
requestDownload(
|
||||
'${moduleName}/${businessName}/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`${businessName}_${r'${new Date().getTime()}'}.xlsx`
|
||||
);
|
||||
};
|
||||
</#if>
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
@ -1,615 +0,0 @@
|
||||
<template>
|
||||
<div class="p-2 page-shell ${moduleName}-${businessName}-page">
|
||||
<div class="search-wrap">
|
||||
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
|
||||
<template #header>
|
||||
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
|
||||
<div><h3>筛选条件</h3></div>
|
||||
</div>
|
||||
</template>
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
|
||||
<#list columns as column>
|
||||
<#if column.query>
|
||||
<#if column.htmlType == "input" || column.htmlType == "textarea">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input v-model="queryParams.${column.javaField}" placeholder="请输入${column.columnLabel}" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "inputNumber">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input-number v-model="queryParams.${column.javaField}" controls-position="right" />
|
||||
</el-form-item>
|
||||
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
|
||||
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "switch" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
|
||||
<el-option v-for="dict in ${column.dictType}" :key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "switch">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
|
||||
<#if column.javaType == "Boolean">
|
||||
<el-option label="是" :value="true" />
|
||||
<el-option label="否" :value="false" />
|
||||
<#elseif column.javaType == "Integer" || column.javaType == "Long">
|
||||
<el-option label="开启" :value="0" />
|
||||
<el-option label="关闭" :value="1" />
|
||||
<#else>
|
||||
<el-option label="开启" value="0" />
|
||||
<el-option label="关闭" value="1" />
|
||||
</#if>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif (column.htmlType == "select" || column.htmlType == "radio") && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="queryParams.${column.javaField}" placeholder="请选择${column.columnLabel}" clearable >
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "datetime" && column.queryType != "BETWEEN">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-date-picker clearable
|
||||
v-model="queryParams.${column.javaField}"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择${column.columnLabel}"
|
||||
/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "datetime" && column.queryType == "BETWEEN" && column.query>
|
||||
<el-form-item label="${column.columnLabel}" style="width: 308px">
|
||||
<el-date-picker
|
||||
v-model="dateRange${column.capJavaField}"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
|
||||
/>
|
||||
</el-form-item>
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card shadow="hover" class="table-panel">
|
||||
<template #header>
|
||||
<div class="toolbar-shell">
|
||||
<div class="table-heading">
|
||||
<h3>${functionName}列表</h3>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['${moduleName}:${businessName}:add']">新增</el-button>
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['${moduleName}:${businessName}:edit']">修改</el-button>
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['${moduleName}:${businessName}:remove']">删除</el-button>
|
||||
<#if enableExport>
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['${moduleName}:${businessName}:export']">导出</el-button>
|
||||
</#if>
|
||||
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" border class="data-table" :data="${businessName}List" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<#list columns as column>
|
||||
<#if column.pk && column.list>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" />
|
||||
<#elseif enableStatus && statusField == column.javaField>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.${column.javaField}"
|
||||
:active-value="${statusField}ActiveValue"
|
||||
:inactive-value="${statusField}InactiveValue"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif enableSort && sortField == column.javaField>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="160">
|
||||
<template #default="scope">
|
||||
<#if column.javaType == "LocalDateTime">
|
||||
<el-date-picker
|
||||
v-model="scope.row.${column.javaField}"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择${column.columnLabel}"
|
||||
@change="handleSortChange(scope.row)"
|
||||
/>
|
||||
<#else>
|
||||
<el-input-number v-model="scope.row.${column.javaField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
|
||||
</#if>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.htmlType == "switch">
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="120">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.${column.javaField}"
|
||||
<#if column.javaType == "Boolean">
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
<#elseif column.javaType == "Integer" || column.javaType == "Long">
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
<#else>
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
</#if>
|
||||
disabled
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.htmlType == "datetime">
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.${column.javaField}, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.htmlType == "imageUpload">
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}Url" width="100">
|
||||
<template #default="scope">
|
||||
<image-preview :src="scope.row.${column.javaField}Url" :width="50" :height="50"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && column.dictColumn>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}">
|
||||
<template #default="scope">
|
||||
<#if column.htmlType == "checkbox">
|
||||
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField} ? scope.row.${column.javaField}.split(',') : []"/>
|
||||
<#else>
|
||||
<dict-tag :options="${column.dictType}" :value="scope.row.${column.javaField}"/>
|
||||
</#if>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<#elseif column.list && "" != column.javaField>
|
||||
<el-table-column label="${column.columnLabel}" align="center" prop="${column.javaField}" />
|
||||
</#if>
|
||||
</#list>
|
||||
<#if enableStatus && !statusColumn.list>
|
||||
<el-table-column label="${statusColumn.columnComment}" align="center" prop="${statusField}">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.${statusField}"
|
||||
<#if statusColumn.javaType == "Boolean">
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
<#else>
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
</#if>
|
||||
@change="handleStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</#if>
|
||||
<#if enableSort && !sortColumn.list>
|
||||
<el-table-column label="${sortColumn.columnComment}" align="center" prop="${sortField}" width="160">
|
||||
<template #default="scope">
|
||||
<#if sortColumn.javaType == "LocalDateTime">
|
||||
<el-date-picker
|
||||
v-model="scope.row.${sortField}"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择${sortColumn.columnComment}"
|
||||
@change="handleSortChange(scope.row)"
|
||||
/>
|
||||
<#else>
|
||||
<el-input-number v-model="scope.row.${sortField}" controls-position="right" :min="0" @change="handleSortChange(scope.row)" />
|
||||
</#if>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</#if>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
<!-- 添加或修改${functionName}对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="${businessName}FormRef" :model="form" :rules="rules" label-width="80px">
|
||||
<#list columns as column>
|
||||
<#if (column.insert || column.edit) && !column.pk>
|
||||
<#if column.htmlType == "input">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input v-model="form.${column.javaField}" placeholder="请输入${column.columnLabel}" />
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "inputNumber">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input-number v-model="form.${column.javaField}" controls-position="right" />
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "imageUpload">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<image-upload v-model="form.${column.javaField}"/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "fileUpload">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<file-upload v-model="form.${column.javaField}"/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "editor">
|
||||
<el-form-item label="${column.columnLabel}">
|
||||
<editor v-model="form.${column.javaField}" :min-height="192"/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "select" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
|
||||
<el-option
|
||||
v-for="dict in ${column.dictType}"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
<#if column.javaType == "Integer" || column.javaType == "Long">
|
||||
:value="parseInt(dict.value)"
|
||||
<#else>
|
||||
:value="dict.value"
|
||||
</#if>
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "select" && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-select v-model="form.${column.javaField}" placeholder="请选择${column.columnLabel}">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "checkbox" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-checkbox-group v-model="form.${column.javaField}">
|
||||
<el-checkbox
|
||||
v-for="dict in ${column.dictType}"
|
||||
:key="dict.value"
|
||||
:label="dict.value">
|
||||
{{dict.label}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "checkbox" && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-checkbox-group v-model="form.${column.javaField}">
|
||||
<el-checkbox>请选择字典生成</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "radio" && column.dictType?has_content>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-radio-group v-model="form.${column.javaField}">
|
||||
<el-radio
|
||||
v-for="dict in ${column.dictType}"
|
||||
:key="dict.value"
|
||||
<#if column.javaType == "Integer" || column.javaType == "Long">
|
||||
:value="parseInt(dict.value)"
|
||||
<#else>
|
||||
:value="dict.value"
|
||||
</#if>
|
||||
>{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "radio" && !(column.dictType?has_content)>
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-radio-group v-model="form.${column.javaField}">
|
||||
<el-radio value="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "switch">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-switch
|
||||
v-model="form.${column.javaField}"
|
||||
<#if column.javaType == "Boolean">
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
<#elseif column.javaType == "Integer" || column.javaType == "Long">
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
<#else>
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
</#if>
|
||||
/>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "datetime">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-date-picker clearable
|
||||
v-model="form.${column.javaField}"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="请选择${column.columnLabel}">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<#elseif column.htmlType == "textarea">
|
||||
<el-form-item label="${column.columnLabel}" prop="${column.javaField}">
|
||||
<el-input v-model="form.${column.javaField}" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="${BusinessName}" lang="ts">
|
||||
import {
|
||||
add${BusinessName},
|
||||
<#if enableStatus>
|
||||
change${BusinessName}Status,
|
||||
</#if>
|
||||
del${BusinessName},
|
||||
get${BusinessName},
|
||||
list${BusinessName},
|
||||
<#if enableSort>
|
||||
update${BusinessName}Sort,
|
||||
</#if>
|
||||
update${BusinessName}
|
||||
} from '@/api/${moduleName}/${businessName}';
|
||||
import { ${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO } from '@/api/${moduleName}/${businessName}/types';
|
||||
import { useLoading } from '@/hooks/async/useLoading';
|
||||
import { useFormDialog } from '@/hooks/dialog/useFormDialog';
|
||||
<#if needAddDateRange>
|
||||
import { useDateRangeQuery } from '@/hooks/form/useDateRangeQuery';
|
||||
</#if>
|
||||
import { useSearchReset } from '@/hooks/form/useSearchReset';
|
||||
import { useSearchToggle } from '@/hooks/form/useSearchToggle';
|
||||
import { useTableSelection } from '@/hooks/table/useTableSelection';
|
||||
<#if needDict>
|
||||
import { useDict } from '@/utils/dict';
|
||||
</#if>
|
||||
<#if needParseTime>
|
||||
import { parseTime } from '@/utils/ruoyi';
|
||||
</#if>
|
||||
import modal from '@/plugins/modal';
|
||||
<#if enableExport>
|
||||
import { download as requestDownload } from '@/utils/request';
|
||||
</#if>
|
||||
|
||||
<#if needDict>
|
||||
const { ${dictsNoSymbol} } = toRefs<any>(useDict(${dicts}));
|
||||
</#if>
|
||||
|
||||
<#if enableStatus>
|
||||
const ${statusField}ActiveValue = <#if statusColumn.javaType == "Boolean">true<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">0<#else>'0'</#if>;
|
||||
const ${statusField}InactiveValue = <#if statusColumn.javaType == "Boolean">false<#elseif statusColumn.javaType == "Integer" || statusColumn.javaType == "Long">1<#else>'1'</#if>;
|
||||
</#if>
|
||||
|
||||
const ${businessName}List = ref<${BusinessName}VO[]>([]);
|
||||
const buttonLoading = ref(false);
|
||||
const { loading, withLoading } = useLoading(true);
|
||||
const { showSearch } = useSearchToggle();
|
||||
const total = ref(0);
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN" && column.query>
|
||||
const {
|
||||
dateRange: dateRange${column.capJavaField},
|
||||
applyDateRange: apply${column.capJavaField}DateRange,
|
||||
resetDateRange: reset${column.capJavaField}DateRange
|
||||
} = useDateRangeQuery('${column.capJavaField}');
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const ${businessName}FormRef = ref<ElFormInstance>();
|
||||
|
||||
const initFormData: ${BusinessName}Form = {
|
||||
<#list columns as column>
|
||||
<#if column.insert || column.edit>
|
||||
<#if column.htmlType == "checkbox">
|
||||
${column.javaField}: [],
|
||||
<#else>
|
||||
${column.javaField}: undefined,
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
const data = reactive<PageData<${BusinessName}Form, ${BusinessName}Query>>({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
<#list columns as column>
|
||||
<#if column.query>
|
||||
<#if column.htmlType != "datetime" || column.queryType != "BETWEEN">
|
||||
${column.javaField}: undefined,
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
params: {
|
||||
<#list columns as column>
|
||||
<#if column.query>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN">
|
||||
${column.javaField}: undefined,
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
<#list columns as column>
|
||||
<#if column.insert || column.edit>
|
||||
<#if column.required>
|
||||
${column.javaField}: [
|
||||
{ required: true, message: "${column.columnLabel}不能为空", trigger: <#if column.htmlType == "select" || column.htmlType == "radio" || column.htmlType == "switch" || column.htmlType == "inputNumber">"change"<#else>"blur"</#if> }
|
||||
],
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
const { ids, single, multiple, handleSelectionChange } = useTableSelection<${BusinessName}VO>(item => item.${pkColumn.javaField});
|
||||
const { dialog, resetForm: reset, openDialog, showDialog, closeDialog } = useFormDialog({
|
||||
form,
|
||||
formRef: ${businessName}FormRef,
|
||||
initialFormData: initFormData
|
||||
});
|
||||
|
||||
/** 查询${functionName}列表 */
|
||||
const getList = async () => {
|
||||
await withLoading(async () => {
|
||||
<#if needAddDateRange>
|
||||
let params = queryParams.value;
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN" && column.query>
|
||||
params = apply${column.capJavaField}DateRange(params);
|
||||
</#if>
|
||||
</#list>
|
||||
const res = await list${BusinessName}(params);
|
||||
<#else>
|
||||
const res = await list${BusinessName}(queryParams.value);
|
||||
</#if>
|
||||
${businessName}List.value = res.data?.rows;
|
||||
total.value = res.data?.total;
|
||||
});
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset();
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
const { resetQuery } = useSearchReset({
|
||||
queryFormRef,
|
||||
queryParams,
|
||||
pageNumKey: 'pageNum',
|
||||
pageSizeKey: 'pageSize',
|
||||
initialPageSize: 10,
|
||||
resetExtras: () => {
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "datetime" && column.queryType == "BETWEEN" && column.query>
|
||||
reset${column.capJavaField}DateRange();
|
||||
</#if>
|
||||
</#list>
|
||||
},
|
||||
afterReset: () => {
|
||||
handleQuery();
|
||||
}
|
||||
});
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
openDialog('添加${functionName}');
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: Partial<${BusinessName}VO>) => {
|
||||
reset();
|
||||
const _${pkColumn.javaField} = row?.${pkColumn.javaField} || ids.value[0];
|
||||
const res = await get${BusinessName}(_${pkColumn.javaField});
|
||||
Object.assign(form.value, res.data);
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "checkbox">
|
||||
form.value.${column.javaField} = form.value.${column.javaField}.split(",");
|
||||
</#if>
|
||||
</#list>
|
||||
showDialog('修改${functionName}');
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
${businessName}FormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
<#list columns as column>
|
||||
<#if column.htmlType == "checkbox">
|
||||
form.value.${column.javaField} = form.value.${column.javaField}.join(",");
|
||||
</#if>
|
||||
</#list>
|
||||
if (form.value.${pkColumn.javaField}) {
|
||||
await update${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await add${BusinessName}(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
modal.msgSuccess('操作成功');
|
||||
closeDialog();
|
||||
await getList();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: Partial<${BusinessName}VO>) => {
|
||||
const _${pkColumn.javaField}s = row?.${pkColumn.javaField} || ids.value;
|
||||
await modal.confirm('是否确认删除${functionName}编号为"' + _${pkColumn.javaField}s + '"的数据项?');
|
||||
await del${BusinessName}(_${pkColumn.javaField}s);
|
||||
modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
};
|
||||
|
||||
<#if enableExport>
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
requestDownload(
|
||||
'${moduleName}/${businessName}/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`${businessName}_${r'${new Date().getTime()}'}.xlsx`
|
||||
);
|
||||
};
|
||||
</#if>
|
||||
|
||||
<#if enableStatus>
|
||||
/** 状态修改 */
|
||||
const handleStatusChange = async (row: Partial<${BusinessName}VO>) => {
|
||||
const text = row.${statusField} === ${statusField}ActiveValue ? '启用' : '停用';
|
||||
try {
|
||||
await modal.confirm('确认要"' + text + '"吗?');
|
||||
await change${BusinessName}Status(row.${pkColumn.javaField}, row.${statusField});
|
||||
modal.msgSuccess(text + '成功');
|
||||
} catch (err) {
|
||||
row.${statusField} = row.${statusField} === ${statusField}ActiveValue ? ${statusField}InactiveValue : ${statusField}ActiveValue;
|
||||
}
|
||||
};
|
||||
</#if>
|
||||
|
||||
<#if enableSort>
|
||||
/** 排序调整 */
|
||||
const handleSortChange = async (row: Partial<${BusinessName}VO>) => {
|
||||
try {
|
||||
await update${BusinessName}Sort(row.${pkColumn.javaField}, row.${sortField});
|
||||
modal.msgSuccess('排序更新成功');
|
||||
} catch (err) {
|
||||
await getList();
|
||||
}
|
||||
};
|
||||
</#if>
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
export interface ${BusinessName}VO {
|
||||
<#list columns as column>
|
||||
<#if column.list>
|
||||
/**
|
||||
* ${column.columnComment}
|
||||
*/
|
||||
${column.javaField}: ${column.tsType};
|
||||
<#if column.htmlType == "imageUpload">
|
||||
/**
|
||||
* ${column.columnComment}Url
|
||||
*/
|
||||
${column.javaField}Url: string;
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
<#if table.tree>
|
||||
/**
|
||||
* 子对象
|
||||
*/
|
||||
children: ${BusinessName}VO[];
|
||||
</#if>
|
||||
}
|
||||
|
||||
export interface ${BusinessName}Form extends BaseEntity {
|
||||
<#list columns as column>
|
||||
<#if column.insert || column.edit>
|
||||
/**
|
||||
* ${column.columnComment}
|
||||
*/
|
||||
${column.javaField}?: ${column.tsType};
|
||||
</#if>
|
||||
</#list>
|
||||
}
|
||||
|
||||
export interface ${BusinessName}Query<#if !table.tree> extends PageQuery</#if> {
|
||||
<#list columns as column>
|
||||
<#if column.query>
|
||||
/**
|
||||
* ${column.columnComment}
|
||||
*/
|
||||
${column.javaField}?: ${column.tsType};
|
||||
</#if>
|
||||
</#list>
|
||||
/**
|
||||
* 日期范围参数
|
||||
*/
|
||||
params?: any;
|
||||
}
|
||||
60
html/ie.html
Normal file
41
index.html
@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@ -6,12 +6,12 @@
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<title>%VITE_APP_TITLE%</title>
|
||||
<!--[if lt IE 11]>
|
||||
<script>
|
||||
window.location.href = '/ie.html';
|
||||
</script>
|
||||
<![endif]-->
|
||||
<title>RuoYi-Vue-Plus多租户管理系统</title>
|
||||
<!--[if lt IE 11
|
||||
]><script>
|
||||
window.location.href='/html/ie.html';
|
||||
</script><!
|
||||
[endif]-->
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
@ -47,7 +47,7 @@
|
||||
margin: -75px 0 0 -75px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #fff;
|
||||
border-top-color: #FFF;
|
||||
-webkit-animation: spin 2s linear infinite;
|
||||
-ms-animation: spin 2s linear infinite;
|
||||
-moz-animation: spin 2s linear infinite;
|
||||
@ -57,7 +57,7 @@
|
||||
}
|
||||
|
||||
#loader:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
@ -65,7 +65,7 @@
|
||||
bottom: 5px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #fff;
|
||||
border-top-color: #FFF;
|
||||
-webkit-animation: spin 3s linear infinite;
|
||||
-moz-animation: spin 3s linear infinite;
|
||||
-o-animation: spin 3s linear infinite;
|
||||
@ -74,7 +74,7 @@
|
||||
}
|
||||
|
||||
#loader:after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
@ -82,7 +82,7 @@
|
||||
bottom: 15px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid transparent;
|
||||
border-top-color: #fff;
|
||||
border-top-color: #FFF;
|
||||
-moz-animation: spin 1.5s linear infinite;
|
||||
-o-animation: spin 1.5s linear infinite;
|
||||
-ms-animation: spin 1.5s linear infinite;
|
||||
@ -90,6 +90,7 @@
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
@ -118,12 +119,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#loader-wrapper .loader-section {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 51%;
|
||||
height: 100%;
|
||||
background: #7171c6;
|
||||
background: #7171C6;
|
||||
z-index: 1000;
|
||||
-webkit-transform: translateX(0);
|
||||
-ms-transform: translateX(0);
|
||||
@ -138,20 +140,21 @@
|
||||
right: 0;
|
||||
}
|
||||
|
||||
|
||||
.loaded #loader-wrapper .loader-section.section-left {
|
||||
-webkit-transform: translateX(-100%);
|
||||
-ms-transform: translateX(-100%);
|
||||
transform: translateX(-100%);
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
}
|
||||
|
||||
.loaded #loader-wrapper .loader-section.section-right {
|
||||
-webkit-transform: translateX(100%);
|
||||
-ms-transform: translateX(100%);
|
||||
transform: translateX(100%);
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
}
|
||||
|
||||
.loaded #loader {
|
||||
@ -179,7 +182,7 @@
|
||||
|
||||
#loader-wrapper .load_title {
|
||||
font-family: 'Open Sans';
|
||||
color: #fff;
|
||||
color: #FFF;
|
||||
font-size: 19px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@ -194,7 +197,7 @@
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
color: #FFF;
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
138
package.json
@ -1,82 +1,84 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package",
|
||||
"name": "ruoyi-vue-plus",
|
||||
"version": "6.0.0",
|
||||
"description": "RuoYi-Vue-Plus后台管理系统",
|
||||
"license": "MIT",
|
||||
"version": "5.1.0",
|
||||
"description": "RuoYi-Vue-Plus多租户管理系统",
|
||||
"author": "LionLi",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "vite serve --mode development",
|
||||
"build:prod": "vite build --mode production &&vue-tsc --noEmit",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint src/**/*.{ts,js,vue} --fix",
|
||||
"prepare": "husky install",
|
||||
"prettier": "prettier --write ."
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitee.com/JavaLionLi/plus-ui.git"
|
||||
},
|
||||
"packageManager": "pnpm@10.34.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build --mode production",
|
||||
"build:dev": "vite build --mode development",
|
||||
"build:prod": "vite build --mode production",
|
||||
"dev": "vite serve --mode development",
|
||||
"fmt": "oxfmt .",
|
||||
"lint": "oxlint src",
|
||||
"lint:fix": "oxlint --fix src",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "2.3.2",
|
||||
"@highlightjs/vue-plugin": "2.1.2",
|
||||
"@iconify/vue": "^5.0.1",
|
||||
"@noble/ciphers": "^2.4.0",
|
||||
"@vueuse/core": "14.4.0",
|
||||
"@wangeditor-next/editor": "6.4.1",
|
||||
"@wangeditor-next/editor-for-vue": "6.4.1",
|
||||
"@element-plus/icons-vue": "2.1.0",
|
||||
"@vueup/vue-quill": "1.1.0",
|
||||
"@vueuse/core": "9.5.0",
|
||||
"animate.css": "4.1.1",
|
||||
"await-to-js": "3.0.0",
|
||||
"axios": "1.20.0",
|
||||
"echarts": "6.1.0",
|
||||
"element-plus": "2.14.5",
|
||||
"highlight.js": "11.12.0",
|
||||
"image-conversion": "2.1.1",
|
||||
"jsencrypt": "3.5.4",
|
||||
"await-to-js": "^3.0.0",
|
||||
"axios": "^1.3.4",
|
||||
"echarts": "5.4.0",
|
||||
"element-plus": "2.2.27",
|
||||
"file-saver": "2.0.5",
|
||||
"fuse.js": "6.6.2",
|
||||
"js-cookie": "3.0.1",
|
||||
"jsencrypt": "3.3.1",
|
||||
"crypto-js": "^4.1.1",
|
||||
"nprogress": "0.2.0",
|
||||
"pinia": "4.0.3",
|
||||
"vue": "3.5.42",
|
||||
"vue-cropper": "1.1.4",
|
||||
"vue-i18n": "11.4.10",
|
||||
"vue-json-pretty": "2.6.0",
|
||||
"vue-router": "5.3.1",
|
||||
"vue-types": "7.0.0",
|
||||
"vxe-pc-ui": "4.18.9",
|
||||
"vxe-table": "4.21.9"
|
||||
"path-browserify": "1.0.1",
|
||||
"path-to-regexp": "6.2.0",
|
||||
"pinia": "2.0.22",
|
||||
"screenfull": "6.0.0",
|
||||
"vform3-builds": "3.0.8",
|
||||
"vue": "3.2.45",
|
||||
"vue-cropper": "1.0.3",
|
||||
"vue-i18n": "9.2.2",
|
||||
"vue-router": "4.1.4",
|
||||
"vue-types": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^26.1.1",
|
||||
"@types/nprogress": "0.2.3",
|
||||
"@unocss/preset-attributify": "66.10.1",
|
||||
"@unocss/preset-wind3": "66.10.1",
|
||||
"@vitejs/plugin-vue": "^6.0.8",
|
||||
"@vue/compiler-sfc": "3.5.42",
|
||||
"autoprefixer": "10.5.5",
|
||||
"oxfmt": "^0.67.0",
|
||||
"oxlint": "^1.82.0",
|
||||
"sass": "1.104.0",
|
||||
"typescript": "^6.0.3",
|
||||
"unocss": "66.10.1",
|
||||
"unplugin-auto-import": "21.1.0",
|
||||
"unplugin-vue-components": "32.1.0",
|
||||
"unplugin-vue-setup-extend-plus": "1.0.1",
|
||||
"vite": "^8.2.2",
|
||||
"vite-plugin-svg-icons-ng": "^1.9.3",
|
||||
"vitest": "4.1.11",
|
||||
"vue-tsc": "^3.3.11"
|
||||
},
|
||||
"browserslist": [
|
||||
"Chrome >= 87",
|
||||
"Edge >= 88",
|
||||
"Safari >= 14",
|
||||
"Firefox >= 78"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=20.19.0",
|
||||
"pnpm": ">=10.0.0"
|
||||
"@iconify/json": "^2.2.40",
|
||||
"@intlify/unplugin-vue-i18n": "0.8.2",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/file-saver": "2.0.5",
|
||||
"@types/js-cookie": "3.0.3",
|
||||
"@types/node": "18.14.2",
|
||||
"@types/nprogress": "0.2.0",
|
||||
"@types/path-browserify": "^1.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.56.0",
|
||||
"@typescript-eslint/parser": "5.56.0",
|
||||
"@unocss/preset-attributify": "^0.50.6",
|
||||
"@unocss/preset-icons": "^0.50.6",
|
||||
"@unocss/preset-uno": "^0.50.6",
|
||||
"@vitejs/plugin-vue": "4.0.0",
|
||||
"@vue/compiler-sfc": "3.2.45",
|
||||
"autoprefixer": "10.4.14",
|
||||
"eslint": "8.36.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-prettier": "4.2.1",
|
||||
"eslint-plugin-vue": "9.9.0",
|
||||
"fast-glob": "^3.2.11",
|
||||
"husky": "7.0.4",
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "2.8.6",
|
||||
"sass": "1.56.1",
|
||||
"typescript": "4.9.5",
|
||||
"unocss": "^0.50.6",
|
||||
"unplugin-auto-import": "0.13.0",
|
||||
"unplugin-icons": "0.15.1",
|
||||
"unplugin-vue-components": "0.23.0",
|
||||
"vite": "4.3.1",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-svg-icons": "2.0.1",
|
||||
"unplugin-vue-setup-extend-plus": "0.4.9",
|
||||
"vitest": "^0.29.7",
|
||||
"vue-eslint-parser": "9.1.0",
|
||||
"vue-tsc": "0.35.0"
|
||||
}
|
||||
}
|
||||
|
||||
4906
pnpm-lock.yaml
generated
@ -1,10 +0,0 @@
|
||||
packages:
|
||||
- '.'
|
||||
|
||||
allowBuilds:
|
||||
'@parcel/watcher': true
|
||||
es5-ext: true
|
||||
esbuild: true
|
||||
|
||||
overrides:
|
||||
esbuild: 0.28.1
|
||||
258
public/ie.html
15
src/App.vue
@ -1,20 +1,21 @@
|
||||
<template>
|
||||
<el-config-provider :locale="appStore.locale" :size="appStore.size">
|
||||
<el-config-provider :locale="appStore.locale" :size="size">
|
||||
<router-view />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useSettingsStore } from '@/store/modules/settings';
|
||||
import { handleThemeStyle } from '@/utils/theme';
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import { handleThemeStyle } from '@/utils/theme'
|
||||
import useAppStore from '@/store/modules/app';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const size = computed(() => appStore.size as any);
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
// 初始化主题样式
|
||||
handleThemeStyle(useSettingsStore().theme);
|
||||
});
|
||||
});
|
||||
handleThemeStyle(useSettingsStore().theme)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { SnailOpenApiUser } from './types';
|
||||
|
||||
export const registerCurrentSnailUser = (): AxiosPromise<SnailOpenApiUser> => {
|
||||
return request({
|
||||
url: '/snail-ai/user/register',
|
||||
method: 'post'
|
||||
});
|
||||
};
|
||||
@ -1,6 +0,0 @@
|
||||
export interface SnailOpenApiUser {
|
||||
openId: string;
|
||||
nickname?: string;
|
||||
externalId?: string;
|
||||
created?: boolean;
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
export * from './agent';
|
||||
export * from './agent/types';
|
||||
@ -1,14 +1,13 @@
|
||||
import type { DemoForm, DemoQuery, DemoVO } from '@/api/demo/demo/types';
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { DemoVO, DemoForm, DemoQuery } from '@/api/demo/demo/types';
|
||||
|
||||
/**
|
||||
* 查询测试单列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const listDemo = (query?: DemoQuery): AxiosPromise<PageResult<DemoVO>> => {
|
||||
export const listDemo = (query?: DemoQuery): AxiosPromise<DemoVO[]> => {
|
||||
return request({
|
||||
url: '/demo/demo/list',
|
||||
method: 'get',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { TreeForm, TreeQuery, TreeVO } from '@/api/demo/tree/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { TreeVO, TreeForm, TreeQuery } from '@/api/demo/tree/types';
|
||||
|
||||
/**
|
||||
* 查询测试树列表
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import type { UserInfo } from '@/api/system/user/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import { closePush } from '@/utils/push';
|
||||
import request from '@/utils/request';
|
||||
import type { LoginData, LoginResult, VerifyCodeResult } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { LoginData, LoginResult, VerifyCodeResult, TenantInfo } from './types';
|
||||
import { UserInfo } from '@/api/system/user/types';
|
||||
|
||||
// pc端固定客户端授权id
|
||||
const clientId = import.meta.env.VITE_APP_CLIENT_ID;
|
||||
@ -21,8 +20,7 @@ export function login(data: LoginData): AxiosPromise<LoginResult> {
|
||||
url: '/auth/login',
|
||||
headers: {
|
||||
isToken: false,
|
||||
isEncrypt: true,
|
||||
repeatSubmit: false
|
||||
isEncrypt: true
|
||||
},
|
||||
method: 'post',
|
||||
data: params
|
||||
@ -31,20 +29,14 @@ export function login(data: LoginData): AxiosPromise<LoginResult> {
|
||||
|
||||
// 注册方法
|
||||
export function register(data: any) {
|
||||
const params = {
|
||||
...data,
|
||||
clientId: clientId,
|
||||
grantType: 'password'
|
||||
};
|
||||
return request({
|
||||
url: '/auth/register',
|
||||
headers: {
|
||||
isToken: false,
|
||||
isEncrypt: true,
|
||||
repeatSubmit: false
|
||||
isEncrypt: true
|
||||
},
|
||||
method: 'post',
|
||||
data: params
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
@ -52,16 +44,6 @@ export function register(data: any) {
|
||||
* 注销
|
||||
*/
|
||||
export function logout() {
|
||||
closePush();
|
||||
if (
|
||||
import.meta.env.VITE_APP_MESSAGE_ENABLED === 'true' &&
|
||||
import.meta.env.VITE_APP_MESSAGE_TRANSPORT.toLowerCase() === 'sse'
|
||||
) {
|
||||
request({
|
||||
url: import.meta.env.VITE_APP_MESSAGE_PATH + '/close',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
return request({
|
||||
url: '/auth/logout',
|
||||
method: 'post'
|
||||
@ -105,3 +87,14 @@ export function getInfo(): AxiosPromise<UserInfo> {
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取租户列表
|
||||
export function getTenantList(): AxiosPromise<TenantInfo> {
|
||||
return request({
|
||||
url: '/auth/tenant/list',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
// 获取路由
|
||||
export function getRouters(): AxiosPromise<RouteRecordRaw[]> {
|
||||
|
||||
51
src/api/monitor/cache/index.ts
vendored
@ -1,6 +1,6 @@
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { CacheVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { CacheVO } from './types';
|
||||
|
||||
// 查询缓存详细
|
||||
export function getCache(): AxiosPromise<CacheVO> {
|
||||
@ -10,3 +10,50 @@ export function getCache(): AxiosPromise<CacheVO> {
|
||||
});
|
||||
}
|
||||
|
||||
// 查询缓存名称列表
|
||||
export function listCacheName() {
|
||||
return request({
|
||||
url: '/monitor/cache/getNames',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 查询缓存键名列表
|
||||
export function listCacheKey(cacheName: string) {
|
||||
return request({
|
||||
url: '/monitor/cache/getKeys/' + cacheName,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 查询缓存内容
|
||||
export function getCacheValue(cacheName: string, cacheKey: string) {
|
||||
return request({
|
||||
url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 清理指定名称缓存
|
||||
export function clearCacheName(cacheName: string) {
|
||||
return request({
|
||||
url: '/monitor/cache/clearCacheName/' + cacheName,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// 清理指定键名缓存
|
||||
export function clearCacheKey(cacheName: string, cacheKey: string) {
|
||||
return request({
|
||||
url: '/monitor/cache/clearCacheKey/' + cacheName + '/' + cacheKey,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// 清理全部缓存
|
||||
export function clearCacheAll() {
|
||||
return request({
|
||||
url: '/monitor/cache/clearCacheAll',
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { LoginInfoQuery, LoginInfoVO } from './types';
|
||||
import { LoginInfoQuery, LoginInfoVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询登录日志列表
|
||||
export function list(query: LoginInfoQuery): AxiosPromise<PageResult<LoginInfoVO>> {
|
||||
export function list(query: LoginInfoQuery): AxiosPromise<LoginInfoVO[]> {
|
||||
return request({
|
||||
url: '/monitor/loginInfo/list',
|
||||
url: '/monitor/logininfor/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
@ -15,7 +14,7 @@ export function list(query: LoginInfoQuery): AxiosPromise<PageResult<LoginInfoVO
|
||||
// 删除登录日志
|
||||
export function delLoginInfo(infoId: string | number | Array<string | number>) {
|
||||
return request({
|
||||
url: '/monitor/loginInfo/' + infoId,
|
||||
url: '/monitor/logininfor/' + infoId,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
@ -23,7 +22,7 @@ export function delLoginInfo(infoId: string | number | Array<string | number>) {
|
||||
// 解锁用户登录状态
|
||||
export function unlockLoginInfo(userName: string | Array<string>) {
|
||||
return request({
|
||||
url: '/monitor/loginInfo/unlock/' + userName,
|
||||
url: '/monitor/logininfor/unlock/' + userName,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
@ -31,7 +30,7 @@ export function unlockLoginInfo(userName: string | Array<string>) {
|
||||
// 清空登录日志
|
||||
export function cleanLoginInfo() {
|
||||
return request({
|
||||
url: '/monitor/loginInfo/clean',
|
||||
url: '/monitor/logininfor/clean',
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
@ -1,10 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { OnlineQuery, OnlineVO } from './types';
|
||||
import { OnlineQuery, OnlineVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询在线用户列表
|
||||
export function list(query: OnlineQuery): AxiosPromise<PageResult<OnlineVO>> {
|
||||
export function list(query: OnlineQuery): AxiosPromise<OnlineVO[]> {
|
||||
return request({
|
||||
url: '/monitor/online/list',
|
||||
method: 'get',
|
||||
@ -19,19 +18,3 @@ export function forceLogout(tokenId: string) {
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取当前用户登录在线设备
|
||||
export function getOnline() {
|
||||
return request({
|
||||
url: '/monitor/online',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 删除当前在线设备
|
||||
export function delOnline(tokenId: string) {
|
||||
return request({
|
||||
url: '/monitor/online/myself/' + tokenId,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { OperLogQuery, OperLogVO } from './types';
|
||||
import { OperLogQuery, OperLogVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询操作日志列表
|
||||
export function list(query: OperLogQuery): AxiosPromise<PageResult<OperLogVO>> {
|
||||
export function list(query: OperLogQuery): AxiosPromise<OperLogVO[]> {
|
||||
return request({
|
||||
url: '/monitor/operlog/list',
|
||||
method: 'get',
|
||||
|
||||
@ -1,13 +1,6 @@
|
||||
export interface OperLogQuery extends PageQuery {
|
||||
operIp: string;
|
||||
title: string;
|
||||
operName: string;
|
||||
userId: string;
|
||||
deptId: string;
|
||||
clientKey: string;
|
||||
deviceType: string;
|
||||
browser: string;
|
||||
os: string;
|
||||
businessType: string;
|
||||
status: string;
|
||||
orderByColumn: string;
|
||||
@ -24,13 +17,7 @@ export interface OperLogVO extends BaseEntity {
|
||||
requestMethod: string;
|
||||
operatorType: number;
|
||||
operName: string;
|
||||
userId: string | number;
|
||||
deptId: string | number;
|
||||
deptName: string;
|
||||
clientKey: string;
|
||||
deviceType: string;
|
||||
browser: string;
|
||||
os: string;
|
||||
operUrl: string;
|
||||
operIp: string;
|
||||
operLocation: string;
|
||||
@ -52,13 +39,7 @@ export interface OperLogForm {
|
||||
requestMethod: string;
|
||||
operatorType: number;
|
||||
operName: string;
|
||||
userId: string | number | undefined;
|
||||
deptId: string | number | undefined;
|
||||
deptName: string;
|
||||
clientKey: string;
|
||||
deviceType: string;
|
||||
browser: string;
|
||||
os: string;
|
||||
operUrl: string;
|
||||
operIp: string;
|
||||
operLocation: string;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import type { ClientForm, ClientQuery, ClientVO } from '@/api/system/client/types';
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { ClientVO, ClientForm, ClientQuery } from '@/api/system/client/types';
|
||||
|
||||
/**
|
||||
* 查询客户端管理列表
|
||||
@ -9,7 +8,7 @@ import request from '@/utils/request';
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const listClient = (query?: ClientQuery): AxiosPromise<PageResult<ClientVO>> => {
|
||||
export const listClient = (query?: ClientQuery): AxiosPromise<ClientVO[]> => {
|
||||
return request({
|
||||
url: '/system/client/list',
|
||||
method: 'get',
|
||||
@ -65,12 +64,12 @@ export const delClient = (id: string | number | Array<string | number>) => {
|
||||
|
||||
/**
|
||||
* 状态修改
|
||||
* @param clientId 客户端id
|
||||
* @param id ID
|
||||
* @param status 状态
|
||||
*/
|
||||
export function changeStatus(clientId: string, status: string) {
|
||||
export function changeStatus(id: number | string, status: string) {
|
||||
const data = {
|
||||
clientId,
|
||||
id,
|
||||
status
|
||||
};
|
||||
return request({
|
||||
|
||||
@ -7,7 +7,7 @@ export interface ClientVO {
|
||||
/**
|
||||
* 客户端id
|
||||
*/
|
||||
clientId: string;
|
||||
clientId: string | number;
|
||||
|
||||
/**
|
||||
* 客户端key
|
||||
@ -29,26 +29,6 @@ export interface ClientVO {
|
||||
*/
|
||||
deviceType: string;
|
||||
|
||||
/**
|
||||
* 允许访问路径
|
||||
*/
|
||||
accessPath?: string;
|
||||
|
||||
/**
|
||||
* 允许访问路径列表
|
||||
*/
|
||||
accessPathList?: string[];
|
||||
|
||||
/**
|
||||
* IP白名单
|
||||
*/
|
||||
ipWhitelist?: string;
|
||||
|
||||
/**
|
||||
* IP白名单列表
|
||||
*/
|
||||
ipWhitelistList?: string[];
|
||||
|
||||
/**
|
||||
* token活跃超时时间
|
||||
*/
|
||||
@ -96,26 +76,6 @@ export interface ClientForm extends BaseEntity {
|
||||
*/
|
||||
deviceType?: string;
|
||||
|
||||
/**
|
||||
* 允许访问路径
|
||||
*/
|
||||
accessPath?: string;
|
||||
|
||||
/**
|
||||
* 允许访问路径列表
|
||||
*/
|
||||
accessPathList?: string[];
|
||||
|
||||
/**
|
||||
* IP白名单
|
||||
*/
|
||||
ipWhitelist?: string;
|
||||
|
||||
/**
|
||||
* IP白名单列表
|
||||
*/
|
||||
ipWhitelistList?: string[];
|
||||
|
||||
/**
|
||||
* token活跃超时时间
|
||||
*/
|
||||
@ -158,16 +118,6 @@ export interface ClientQuery extends PageQuery {
|
||||
*/
|
||||
deviceType?: string;
|
||||
|
||||
/**
|
||||
* 允许访问路径
|
||||
*/
|
||||
accessPath?: string;
|
||||
|
||||
/**
|
||||
* IP白名单
|
||||
*/
|
||||
ipWhitelist?: string;
|
||||
|
||||
/**
|
||||
* token活跃超时时间
|
||||
*/
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { ConfigForm, ConfigQuery, ConfigVO } from './types';
|
||||
import { ConfigForm, ConfigQuery, ConfigVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询参数列表
|
||||
export function listConfig(query: ConfigQuery): AxiosPromise<PageResult<ConfigVO>> {
|
||||
export function listConfig(query: ConfigQuery): AxiosPromise<ConfigVO[]> {
|
||||
return request({
|
||||
url: '/system/config/list',
|
||||
method: 'get',
|
||||
@ -21,7 +20,7 @@ export function getConfig(configId: string | number): AxiosPromise<ConfigVO> {
|
||||
}
|
||||
|
||||
// 根据参数键名查询参数值
|
||||
export function getConfigKey(configKey: string): AxiosPromise<string> {
|
||||
export function getConfigKey(configKey: string): AxiosPromise<ConfigVO> {
|
||||
return request({
|
||||
url: '/system/config/configKey/' + configKey,
|
||||
method: 'get'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import { type DeptForm, type DeptQuery, type DeptVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { DeptForm, DeptQuery, DeptVO } from './types';
|
||||
|
||||
// 查询部门列表
|
||||
export const listDept = (query?: DeptQuery) => {
|
||||
@ -11,17 +11,6 @@ export const listDept = (query?: DeptQuery) => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过deptIds查询部门
|
||||
* @param deptIds
|
||||
*/
|
||||
export const optionSelect = (deptIds: (number | string)[]): AxiosPromise<DeptVO[]> => {
|
||||
return request({
|
||||
url: '/system/dept/optionselect?deptIds=' + deptIds,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 查询部门列表(排除节点)
|
||||
export const listDeptExcludeChild = (deptId: string | number): AxiosPromise<DeptVO[]> => {
|
||||
return request({
|
||||
@ -38,6 +27,14 @@ export const getDept = (deptId: string | number): AxiosPromise<DeptVO> => {
|
||||
});
|
||||
};
|
||||
|
||||
// 查询部门下拉树结构
|
||||
export const treeselect = (): AxiosPromise<DeptVO[]> => {
|
||||
return request({
|
||||
url: '/system/dept/treeselect',
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 新增部门
|
||||
export const addDept = (data: DeptForm) => {
|
||||
return request({
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
*/
|
||||
export interface DeptQuery extends PageQuery {
|
||||
deptName?: string;
|
||||
deptCategory?: string;
|
||||
status?: number;
|
||||
}
|
||||
|
||||
@ -17,7 +16,6 @@ export interface DeptVO extends BaseEntity {
|
||||
children: DeptVO[];
|
||||
deptId: number | string;
|
||||
deptName: string;
|
||||
deptCategory: string;
|
||||
orderNum: number;
|
||||
leader: string;
|
||||
phone: string;
|
||||
@ -28,18 +26,6 @@ export interface DeptVO extends BaseEntity {
|
||||
menuId: string | number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门类型
|
||||
*/
|
||||
export interface DeptTreeVO extends BaseEntity {
|
||||
id: number | string;
|
||||
label: string;
|
||||
parentId: number | string;
|
||||
weight: number;
|
||||
children: DeptTreeVO[];
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门表单类型
|
||||
*/
|
||||
@ -49,7 +35,6 @@ export interface DeptForm {
|
||||
children?: DeptForm[];
|
||||
deptId?: number | string;
|
||||
deptName?: string;
|
||||
deptCategory?: string;
|
||||
orderNum?: number;
|
||||
leader?: string;
|
||||
phone?: string;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { DictDataForm, DictDataQuery, DictDataVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { DictDataForm, DictDataQuery, DictDataVO } from './types';
|
||||
// 根据字典类型查询字典数据信息
|
||||
export function getDicts(dictType: string): AxiosPromise<DictDataVO[]> {
|
||||
return request({
|
||||
@ -11,7 +10,7 @@ export function getDicts(dictType: string): AxiosPromise<DictDataVO[]> {
|
||||
}
|
||||
|
||||
// 查询字典数据列表
|
||||
export function listData(query: DictDataQuery): AxiosPromise<PageResult<DictDataVO>> {
|
||||
export function listData(query: DictDataQuery): AxiosPromise<DictDataVO[]> {
|
||||
return request({
|
||||
url: '/system/dict/data/list',
|
||||
method: 'get',
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { DictTypeForm, DictTypeQuery, DictTypeVO } from './types';
|
||||
import { DictTypeForm, DictTypeVO, DictTypeQuery } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询字典类型列表
|
||||
export function listType(query: DictTypeQuery): AxiosPromise<PageResult<DictTypeVO>> {
|
||||
export function listType(query: DictTypeQuery): AxiosPromise<DictTypeVO[]> {
|
||||
return request({
|
||||
url: '/system/dict/type/list',
|
||||
method: 'get',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { MenuForm, MenuQuery, MenuTreeOption, MenuVO, RoleMenuTree } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { MenuQuery, MenuVO, MenuForm, MenuTreeOption, RoleMenuTree } from './types';
|
||||
|
||||
// 查询菜单列表
|
||||
export const listMenu = (query?: MenuQuery): AxiosPromise<MenuVO[]> => {
|
||||
@ -35,6 +35,14 @@ export const roleMenuTreeselect = (roleId: string | number): AxiosPromise<RoleMe
|
||||
});
|
||||
};
|
||||
|
||||
// 根据角色ID查询菜单下拉树结构
|
||||
export const tenantPackageMenuTreeselect = (packageId: string | number): AxiosPromise<RoleMenuTree> => {
|
||||
return request({
|
||||
url: '/system/menu/tenantPackageMenuTreeselect/' + packageId,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 新增菜单
|
||||
export const addMenu = (data: MenuForm) => {
|
||||
return request({
|
||||
@ -60,11 +68,3 @@ export const delMenu = (menuId: string | number) => {
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
// 级联删除菜单
|
||||
export const cascadeDelMenu = (menuIds: Array<string | number>) => {
|
||||
return request({
|
||||
url: '/system/menu/cascade/' + menuIds,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MenuTypeEnum } from '@/enums/MenuTypeEnum';
|
||||
import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
|
||||
|
||||
/**
|
||||
* 菜单树形结构类型
|
||||
@ -8,28 +8,12 @@ export interface MenuTreeOption {
|
||||
label: string;
|
||||
parentId: string | number;
|
||||
weight: number;
|
||||
menuType?: MenuTypeEnum | string;
|
||||
visible?: string;
|
||||
status?: string;
|
||||
disabled?: boolean;
|
||||
children?: MenuTreeOption[];
|
||||
}
|
||||
|
||||
export interface RoleMenuTree {
|
||||
menus: MenuTreeOption[];
|
||||
checkedKeys: Array<string | number>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色菜单分配中的按钮节点类型
|
||||
*/
|
||||
export interface RoleMenuButtonOption {
|
||||
menuId: string | number;
|
||||
menuName: string;
|
||||
parentId: string | number;
|
||||
perms?: string;
|
||||
status?: string;
|
||||
disabled?: boolean;
|
||||
checkedKeys: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,8 +44,6 @@ export interface MenuVO extends BaseEntity {
|
||||
visible: string;
|
||||
status: string;
|
||||
icon: string;
|
||||
activeMenu: string;
|
||||
ext: string;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
@ -81,8 +63,6 @@ export interface MenuForm {
|
||||
visible?: string;
|
||||
status?: string;
|
||||
icon?: string;
|
||||
activeMenu?: string;
|
||||
ext?: string;
|
||||
remark?: string;
|
||||
query?: string;
|
||||
perms?: string;
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { MessageBoxVO } from './types';
|
||||
|
||||
export function getMessageBox(): AxiosPromise<MessageBoxVO> {
|
||||
return request({
|
||||
url: '/resource/message/box',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
export interface MessageVO extends BaseEntity {
|
||||
messageId: number | string;
|
||||
category: string;
|
||||
type: string;
|
||||
source: string;
|
||||
title: string;
|
||||
message: string;
|
||||
content?: string;
|
||||
data?: Record<string, any> | null;
|
||||
path?: string;
|
||||
}
|
||||
|
||||
export interface MessageBoxVO {
|
||||
systemList: MessageVO[];
|
||||
noticeList: MessageVO[];
|
||||
workflowList: MessageVO[];
|
||||
}
|
||||
@ -1,9 +1,8 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { NoticeForm, NoticeQuery, NoticeVO } from './types';
|
||||
import { NoticeForm, NoticeQuery, NoticeVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
// 查询公告列表
|
||||
export function listNotice(query: NoticeQuery): AxiosPromise<PageResult<NoticeVO>> {
|
||||
export function listNotice(query: NoticeQuery): AxiosPromise<NoticeVO[]> {
|
||||
return request({
|
||||
url: '/system/notice/list',
|
||||
method: 'get',
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { OssQuery, OssUploadVO, OssVO } from './types';
|
||||
import { OssQuery, OssVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询OSS对象存储列表
|
||||
export function listOss(query: OssQuery): AxiosPromise<PageResult<OssVO>> {
|
||||
export function listOss(query: OssQuery): AxiosPromise<OssVO[]> {
|
||||
return request({
|
||||
url: '/resource/oss/list',
|
||||
method: 'get',
|
||||
@ -20,15 +19,6 @@ export function listByIds(ossId: string | number): AxiosPromise<OssVO[]> {
|
||||
});
|
||||
}
|
||||
|
||||
// 上传OSS对象存储
|
||||
export function uploadOss(data: FormData): AxiosPromise<OssUploadVO> {
|
||||
return request({
|
||||
url: '/resource/oss/upload',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 删除OSS对象存储
|
||||
export function delOss(ossId: string | number | Array<string | number>) {
|
||||
return request({
|
||||
|
||||
@ -8,12 +8,6 @@ export interface OssVO extends BaseEntity {
|
||||
service: string;
|
||||
}
|
||||
|
||||
export interface OssUploadVO {
|
||||
url: string;
|
||||
fileName: string;
|
||||
ossId: string;
|
||||
}
|
||||
|
||||
export interface OssQuery extends PageQuery {
|
||||
fileName: string;
|
||||
originalName: string;
|
||||
@ -26,17 +20,3 @@ export interface OssQuery extends PageQuery {
|
||||
export interface OssForm {
|
||||
file: undefined | string;
|
||||
}
|
||||
|
||||
export interface SysOssExt {
|
||||
bizType?: string;
|
||||
fileSize?: number;
|
||||
contentType?: string;
|
||||
source?: string;
|
||||
uploadIp?: string;
|
||||
remark?: string;
|
||||
tags?: string[];
|
||||
refId?: string;
|
||||
refType?: string;
|
||||
isTemp?: boolean;
|
||||
md5?: string;
|
||||
}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { OssConfigForm, OssConfigQuery, OssConfigVO } from './types';
|
||||
import { OssConfigForm, OssConfigQuery, OssConfigVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询对象存储配置列表
|
||||
export function listOssConfig(query: OssConfigQuery): AxiosPromise<PageResult<OssConfigVO>> {
|
||||
export function listOssConfig(query: OssConfigQuery): AxiosPromise<OssConfigVO[]> {
|
||||
return request({
|
||||
url: '/resource/oss/config/list',
|
||||
method: 'get',
|
||||
|
||||
@ -6,7 +6,7 @@ export interface OssConfigVO extends BaseEntity {
|
||||
bucketName: string;
|
||||
prefix: string;
|
||||
endpoint: string;
|
||||
domainUrl: string;
|
||||
domain: string;
|
||||
isHttps: string;
|
||||
region: string;
|
||||
status: string;
|
||||
@ -29,7 +29,7 @@ export interface OssConfigForm {
|
||||
bucketName: string;
|
||||
prefix: string;
|
||||
endpoint: string;
|
||||
domainUrl: string;
|
||||
domain: string;
|
||||
isHttps: string;
|
||||
accessPolicy: string;
|
||||
region: string;
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { DeptTreeVO } from '../dept/types';
|
||||
import type { PostForm, PostQuery, PostVO } from './types';
|
||||
import { PostForm, PostQuery, PostVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询岗位列表
|
||||
export function listPost(query: PostQuery): AxiosPromise<PageResult<PostVO>> {
|
||||
export function listPost(query: PostQuery): AxiosPromise<PostVO[]> {
|
||||
return request({
|
||||
url: '/system/post/list',
|
||||
method: 'get',
|
||||
@ -21,18 +19,6 @@ export function getPost(postId: string | number): AxiosPromise<PostVO> {
|
||||
});
|
||||
}
|
||||
|
||||
// 获取岗位选择框列表
|
||||
export function optionselect(deptId?: number | string, postIds?: (number | string)[]): AxiosPromise<PostVO[]> {
|
||||
return request({
|
||||
url: '/system/post/optionselect',
|
||||
method: 'get',
|
||||
params: {
|
||||
postIds: postIds,
|
||||
deptId: deptId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 新增岗位
|
||||
export function addPost(data: PostForm) {
|
||||
return request({
|
||||
@ -58,13 +44,3 @@ export function delPost(postId: string | number | (string | number)[]) {
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询部门下拉树结构
|
||||
*/
|
||||
export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => {
|
||||
return request({
|
||||
url: '/system/post/deptTree',
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
export interface PostVO extends BaseEntity {
|
||||
postId: number | string;
|
||||
deptId: number | string;
|
||||
postCode: string;
|
||||
postName: string;
|
||||
postCategory: string;
|
||||
deptName: string;
|
||||
postSort: number;
|
||||
status: string;
|
||||
remark: string;
|
||||
@ -12,20 +9,15 @@ export interface PostVO extends BaseEntity {
|
||||
|
||||
export interface PostForm {
|
||||
postId: number | string | undefined;
|
||||
deptId: number | string | undefined;
|
||||
postCode: string;
|
||||
postName: string;
|
||||
postCategory: string;
|
||||
postSort: number;
|
||||
status: string;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
export interface PostQuery extends PageQuery {
|
||||
deptId: number | string;
|
||||
belongDeptId: number | string;
|
||||
postCode: string;
|
||||
postName: string;
|
||||
postCategory: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import type { UserQuery, UserVO } from '@/api/system/user/types';
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import { UserVO } from '@/api/system/user/types';
|
||||
import { UserQuery } from '@/api/system/user/types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { RoleQuery, RoleVO, RoleDeptTree } from './types';
|
||||
import request from '@/utils/request';
|
||||
import type { RoleDeptTree, RoleQuery, RoleVO } from './types';
|
||||
|
||||
export const listRole = (query: RoleQuery): AxiosPromise<PageResult<RoleVO>> => {
|
||||
export const listRole = (query: RoleQuery): AxiosPromise<RoleVO[]> => {
|
||||
return request({
|
||||
url: '/system/role/list',
|
||||
method: 'get',
|
||||
@ -12,17 +12,6 @@ export const listRole = (query: RoleQuery): AxiosPromise<PageResult<RoleVO>> =>
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过roleIds查询角色
|
||||
* @param roleIds
|
||||
*/
|
||||
export const optionSelect = (roleIds: (number | string)[]): AxiosPromise<RoleVO[]> => {
|
||||
return request({
|
||||
url: '/system/role/optionselect?roleIds=' + roleIds,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询角色详细
|
||||
*/
|
||||
@ -45,7 +34,7 @@ export const addRole = (data: any) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改角色基础信息
|
||||
* 修改角色
|
||||
* @param data
|
||||
*/
|
||||
export const updateRole = (data: any) => {
|
||||
@ -57,11 +46,11 @@ export const updateRole = (data: any) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改角色权限(菜单权限 + 数据权限)
|
||||
* 角色数据权限
|
||||
*/
|
||||
export const updateRolePermission = (data: any) => {
|
||||
export const dataScope = (data: any) => {
|
||||
return request({
|
||||
url: '/system/role/permission',
|
||||
url: '/system/role/dataScope',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
@ -95,7 +84,7 @@ export const delRole = (roleId: Array<string | number> | string | number) => {
|
||||
/**
|
||||
* 查询角色已授权用户列表
|
||||
*/
|
||||
export const allocatedUserList = (query: UserQuery): AxiosPromise<PageResult<UserVO>> => {
|
||||
export const allocatedUserList = (query: UserQuery): AxiosPromise<UserVO[]> => {
|
||||
return request({
|
||||
url: '/system/role/authUser/allocatedList',
|
||||
method: 'get',
|
||||
@ -106,7 +95,7 @@ export const allocatedUserList = (query: UserQuery): AxiosPromise<PageResult<Use
|
||||
/**
|
||||
* 查询角色未授权用户列表
|
||||
*/
|
||||
export const unallocatedUserList = (query: UserQuery): AxiosPromise<PageResult<UserVO>> => {
|
||||
export const unallocatedUserList = (query: UserQuery): AxiosPromise<UserVO[]> => {
|
||||
return request({
|
||||
url: '/system/role/authUser/unallocatedList',
|
||||
method: 'get',
|
||||
@ -153,8 +142,3 @@ export const deptTreeSelect = (roleId: string | number): AxiosPromise<RoleDeptTr
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
optionSelect,
|
||||
listRole
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取跳转URL
|
||||
export function authRouterUrl(source: string) {
|
||||
// 绑定账号
|
||||
export function authBinding(source: string) {
|
||||
return request({
|
||||
url: '/auth/binding/' + source,
|
||||
method: 'get'
|
||||
|
||||
92
src/api/system/tenant/index.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import request from '@/utils/request';
|
||||
import { TenantForm, TenantQuery, TenantVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询租户列表
|
||||
export function listTenant(query: TenantQuery): AxiosPromise<TenantVO[]> {
|
||||
return request({
|
||||
url: '/system/tenant/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
// 查询租户详细
|
||||
export function getTenant(id: string | number): AxiosPromise<TenantVO> {
|
||||
return request({
|
||||
url: '/system/tenant/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 新增租户
|
||||
export function addTenant(data: TenantForm) {
|
||||
return request({
|
||||
url: '/system/tenant',
|
||||
method: 'post',
|
||||
headers: {
|
||||
isEncrypt: true
|
||||
},
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 修改租户
|
||||
export function updateTenant(data: TenantForm) {
|
||||
return request({
|
||||
url: '/system/tenant',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 租户状态修改
|
||||
export function changeTenantStatus(id: string | number, tenantId: string | number, status: string) {
|
||||
const data = {
|
||||
id,
|
||||
tenantId,
|
||||
status
|
||||
};
|
||||
return request({
|
||||
url: '/system/tenant/changeStatus',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 删除租户
|
||||
export function delTenant(id: string | number | Array<string | number>) {
|
||||
return request({
|
||||
url: '/system/tenant/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
// 动态切换租户
|
||||
export function dynamicTenant(tenantId: string | number) {
|
||||
return request({
|
||||
url: '/system/tenant/dynamic/' + tenantId,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 清除动态租户
|
||||
export function dynamicClear() {
|
||||
return request({
|
||||
url: '/system/tenant/dynamic/clear',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 同步租户套餐
|
||||
export function syncTenantPackage(tenantId: string | number, packageId: string | number) {
|
||||
const data = {
|
||||
tenantId,
|
||||
packageId
|
||||
};
|
||||
return request({
|
||||
url: '/system/tenant/syncTenantPackage',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
46
src/api/system/tenant/types.ts
Normal file
@ -0,0 +1,46 @@
|
||||
export interface TenantVO extends BaseEntity {
|
||||
id: number | string;
|
||||
tenantId: number | string;
|
||||
username: string;
|
||||
contactUserName: string;
|
||||
contactPhone: string;
|
||||
companyName: string;
|
||||
licenseNumber: string;
|
||||
address: string;
|
||||
domain: string;
|
||||
intro: string;
|
||||
remark: string;
|
||||
packageId: string | number;
|
||||
expireTime: string;
|
||||
accountCount: number;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface TenantQuery extends PageQuery {
|
||||
tenantId: string | number;
|
||||
|
||||
contactUserName: string;
|
||||
|
||||
contactPhone: string;
|
||||
|
||||
companyName: string;
|
||||
}
|
||||
|
||||
export interface TenantForm {
|
||||
id: number | string | undefined;
|
||||
tenantId: number | string | undefined;
|
||||
username: string;
|
||||
password: string;
|
||||
contactUserName: string;
|
||||
contactPhone: string;
|
||||
companyName: string;
|
||||
licenseNumber: string;
|
||||
domain: string;
|
||||
address: string;
|
||||
intro: string;
|
||||
remark: string;
|
||||
packageId: string | number;
|
||||
expireTime: string;
|
||||
accountCount: number;
|
||||
status: string;
|
||||
}
|
||||
67
src/api/system/tenantPackage/index.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import request from '@/utils/request';
|
||||
import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询租户套餐列表
|
||||
export function listTenantPackage(query?: TenantPkgQuery): AxiosPromise<TenantPkgVO[]> {
|
||||
return request({
|
||||
url: '/system/tenant/package/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
}
|
||||
|
||||
// 查询租户套餐下拉选列表
|
||||
export function selectTenantPackage(): AxiosPromise<TenantPkgVO[]> {
|
||||
return request({
|
||||
url: '/system/tenant/package/selectList',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 查询租户套餐详细
|
||||
export function getTenantPackage(packageId: string | number): AxiosPromise<TenantPkgVO> {
|
||||
return request({
|
||||
url: '/system/tenant/package/' + packageId,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 新增租户套餐
|
||||
export function addTenantPackage(data: TenantPkgForm) {
|
||||
return request({
|
||||
url: '/system/tenant/package',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 修改租户套餐
|
||||
export function updateTenantPackage(data: TenantPkgForm) {
|
||||
return request({
|
||||
url: '/system/tenant/package',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 租户套餐状态修改
|
||||
export function changePackageStatus(packageId: number | string, status: string) {
|
||||
const data = {
|
||||
packageId,
|
||||
status
|
||||
};
|
||||
return request({
|
||||
url: '/system/tenant/package/changeStatus',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 删除租户套餐
|
||||
export function delTenantPackage(packageId: string | number | Array<string | number>) {
|
||||
return request({
|
||||
url: '/system/tenant/package/' + packageId,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
20
src/api/system/tenantPackage/types.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export interface TenantPkgVO extends BaseEntity {
|
||||
packageId: string | number;
|
||||
packageName: string;
|
||||
menuIds: string;
|
||||
remark: string;
|
||||
menuCheckStrictly: boolean;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface TenantPkgQuery extends PageQuery {
|
||||
packageName: string;
|
||||
}
|
||||
|
||||
export interface TenantPkgForm {
|
||||
packageId: string | number | undefined;
|
||||
packageName: string;
|
||||
menuIds: string;
|
||||
remark: string;
|
||||
menuCheckStrictly: boolean;
|
||||
}
|
||||
@ -1,16 +1,15 @@
|
||||
import type { RoleVO } from '@/api/system/role/types';
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import { DeptVO } from './../dept/types';
|
||||
import { RoleVO } from '@/api/system/role/types';
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { UserForm, UserQuery, UserVO, UserInfoVO } from './types';
|
||||
import { parseStrEmpty } from '@/utils/ruoyi';
|
||||
import type { DeptTreeVO } from './../dept/types';
|
||||
import type { UserForm, UserInfoVO, UserProfileForm, UserQuery, UserVO } from './types';
|
||||
|
||||
/**
|
||||
* 查询用户列表
|
||||
* @param query
|
||||
*/
|
||||
export const listUser = (query: UserQuery): AxiosPromise<PageResult<UserVO>> => {
|
||||
export const listUser = (query: UserQuery): AxiosPromise<UserVO[]> => {
|
||||
return request({
|
||||
url: '/system/user/list',
|
||||
method: 'get',
|
||||
@ -18,17 +17,6 @@ export const listUser = (query: UserQuery): AxiosPromise<PageResult<UserVO>> =>
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过用户ids查询用户
|
||||
* @param userIds
|
||||
*/
|
||||
export const optionSelect = (userIds: (number | string)[]): AxiosPromise<UserVO[]> => {
|
||||
return request({
|
||||
url: '/system/user/optionselect?userIds=' + userIds,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取用户详情
|
||||
* @param userId
|
||||
@ -87,8 +75,7 @@ export const resetUserPwd = (userId: string | number, password: string) => {
|
||||
url: '/system/user/resetPwd',
|
||||
method: 'put',
|
||||
headers: {
|
||||
isEncrypt: true,
|
||||
repeatSubmit: false
|
||||
isEncrypt: true
|
||||
},
|
||||
data: data
|
||||
});
|
||||
@ -111,17 +98,6 @@ export const changeUserStatus = (userId: number | string, status: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 解锁用户
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
export const unlockUser = (userId: number | string) => {
|
||||
return request({
|
||||
url: '/system/user/unlock/' + userId,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询用户个人信息
|
||||
*/
|
||||
@ -136,7 +112,7 @@ export const getUserProfile = (): AxiosPromise<UserInfoVO> => {
|
||||
* 修改用户个人信息
|
||||
* @param data 用户信息
|
||||
*/
|
||||
export const updateUserProfile = (data: UserProfileForm) => {
|
||||
export const updateUserProfile = (data: UserForm) => {
|
||||
return request({
|
||||
url: '/system/user/profile',
|
||||
method: 'put',
|
||||
@ -158,9 +134,20 @@ export const updateUserPwd = (oldPassword: string, newPassword: string) => {
|
||||
url: '/system/user/profile/updatePwd',
|
||||
method: 'put',
|
||||
headers: {
|
||||
isEncrypt: true,
|
||||
repeatSubmit: false
|
||||
isEncrypt: true
|
||||
},
|
||||
params: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 用户头像上传
|
||||
* @param data 头像文件
|
||||
*/
|
||||
export const uploadAvatar = (data: FormData) => {
|
||||
return request({
|
||||
url: '/system/user/profile/avatar',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
@ -202,7 +189,7 @@ export const listUserByDeptId = (deptId: string | number): AxiosPromise<UserVO[]
|
||||
/**
|
||||
* 查询部门下拉树结构
|
||||
*/
|
||||
export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => {
|
||||
export const deptTreeSelect = (): AxiosPromise<DeptVO[]> => {
|
||||
return request({
|
||||
url: '/system/user/deptTree',
|
||||
method: 'get'
|
||||
@ -212,16 +199,15 @@ export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => {
|
||||
export default {
|
||||
listUser,
|
||||
getUser,
|
||||
optionSelect,
|
||||
addUser,
|
||||
updateUser,
|
||||
delUser,
|
||||
resetUserPwd,
|
||||
changeUserStatus,
|
||||
unlockUser,
|
||||
getUserProfile,
|
||||
updateUserProfile,
|
||||
updateUserPwd,
|
||||
uploadAvatar,
|
||||
getAuthRole,
|
||||
updateAuthRole,
|
||||
deptTreeSelect,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { PostVO } from '@/api/system/post/types';
|
||||
import type { RoleVO } from '@/api/system/role/types';
|
||||
import { DeptVO } from './../dept/types';
|
||||
import { RoleVO } from '@/api/system/role/types';
|
||||
import { PostVO } from '@/api/system/post/types';
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
@ -15,12 +16,10 @@ export interface UserInfo {
|
||||
*/
|
||||
export interface UserQuery extends PageQuery {
|
||||
userName?: string;
|
||||
nickName?: string;
|
||||
phoneNumber?: string;
|
||||
phonenumber?: string;
|
||||
status?: string;
|
||||
deptId?: string | number;
|
||||
roleId?: string | number;
|
||||
userIds?: string | number | (string | number)[] | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,24 +27,20 @@ export interface UserQuery extends PageQuery {
|
||||
*/
|
||||
export interface UserVO extends BaseEntity {
|
||||
userId: string | number;
|
||||
tenantId: string;
|
||||
deptId: number;
|
||||
userName: string;
|
||||
nickName: string;
|
||||
userType: string;
|
||||
email: string;
|
||||
phoneNumber: string;
|
||||
gender: string;
|
||||
avatar?: string | number;
|
||||
avatarUrl?: string;
|
||||
phonenumber: string;
|
||||
sex: string;
|
||||
avatar: string;
|
||||
status: string;
|
||||
delFlag: string;
|
||||
loginIp: string;
|
||||
loginDate: string;
|
||||
remark: string;
|
||||
deptName: string;
|
||||
/** 详情接口可能返回嵌套部门 */
|
||||
dept?: { deptName?: string };
|
||||
dept: DeptVO;
|
||||
roles: RoleVO[];
|
||||
roleIds: any;
|
||||
postIds: any;
|
||||
@ -63,27 +58,15 @@ export interface UserForm {
|
||||
userName: string;
|
||||
nickName?: string;
|
||||
password: string;
|
||||
phoneNumber?: string;
|
||||
phonenumber?: string;
|
||||
email?: string;
|
||||
gender?: string;
|
||||
sex?: string;
|
||||
status: string;
|
||||
remark?: string;
|
||||
avatar?: string | number;
|
||||
postIds: string[];
|
||||
roleIds: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 个人资料表单类型
|
||||
*/
|
||||
export interface UserProfileForm {
|
||||
nickName?: string;
|
||||
phoneNumber?: string;
|
||||
email?: string;
|
||||
gender?: string;
|
||||
avatar?: string | number;
|
||||
}
|
||||
|
||||
export interface UserInfoVO {
|
||||
user: UserVO;
|
||||
roles: RoleVO[];
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
import type { DbTableForm, DbTableQuery, DbTableVO, GenTableDetailPayload, TableQuery, TableVO } from './types';
|
||||
|
||||
export type { GenTableDetailPayload } from './types';
|
||||
import { DbTableQuery, DbTableVO, TableQuery, TableVO, GenTableVO, DbTableForm } from './types';
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
// 查询生成表数据
|
||||
export const listTable = (query: TableQuery): AxiosPromise<PageResult<TableVO>> => {
|
||||
export const listTable = (query: TableQuery): AxiosPromise<TableVO[]> => {
|
||||
return request({
|
||||
url: '/tool/gen/list',
|
||||
method: 'get',
|
||||
@ -14,7 +11,7 @@ export const listTable = (query: TableQuery): AxiosPromise<PageResult<TableVO>>
|
||||
});
|
||||
};
|
||||
// 查询db数据库列表
|
||||
export const listDbTable = (query: DbTableQuery): AxiosPromise<PageResult<DbTableVO>> => {
|
||||
export const listDbTable = (query: DbTableQuery): AxiosPromise<DbTableVO[]> => {
|
||||
return request({
|
||||
url: '/tool/gen/db/list',
|
||||
method: 'get',
|
||||
@ -23,7 +20,7 @@ export const listDbTable = (query: DbTableQuery): AxiosPromise<PageResult<DbTabl
|
||||
};
|
||||
|
||||
// 查询表详细信息
|
||||
export const getGenTable = (tableId: string | number): AxiosPromise<GenTableDetailPayload> => {
|
||||
export const getGenTable = (tableId: string | number): AxiosPromise<GenTableVO> => {
|
||||
return request({
|
||||
url: '/tool/gen/' + tableId,
|
||||
method: 'get'
|
||||
@ -31,7 +28,7 @@ export const getGenTable = (tableId: string | number): AxiosPromise<GenTableDeta
|
||||
};
|
||||
|
||||
// 修改代码生成信息
|
||||
export const updateGenTable = (data: DbTableForm): AxiosPromise<unknown> => {
|
||||
export const updateGenTable = (data: DbTableForm) => {
|
||||
return request({
|
||||
url: '/tool/gen',
|
||||
method: 'put',
|
||||
@ -40,7 +37,7 @@ export const updateGenTable = (data: DbTableForm): AxiosPromise<unknown> => {
|
||||
};
|
||||
|
||||
// 导入表
|
||||
export const importTable = (data: { tables: string; dataName: string }): AxiosPromise<unknown> => {
|
||||
export const importTable = (data: { tables: string; dataName: string }) => {
|
||||
return request({
|
||||
url: '/tool/gen/importTable',
|
||||
method: 'post',
|
||||
@ -64,6 +61,14 @@ export const delTable = (tableId: string | number | Array<string | number>) => {
|
||||
});
|
||||
};
|
||||
|
||||
// 生成代码(自定义路径)
|
||||
export const genCode = (tableId: string | number) => {
|
||||
return request({
|
||||
url: '/tool/gen/genCode/' + tableId,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
// 同步数据库
|
||||
export const synchDb = (tableId: string | number) => {
|
||||
return request({
|
||||
|
||||
@ -4,14 +4,17 @@ export interface TableVO extends BaseEntity {
|
||||
dataName: string;
|
||||
tableName: string;
|
||||
tableComment: string;
|
||||
subTableName?: any;
|
||||
subTableFkName?: any;
|
||||
className: string;
|
||||
tplCategory: string;
|
||||
frontendType: string;
|
||||
packageName: string;
|
||||
moduleName: string;
|
||||
businessName: string;
|
||||
functionName: string;
|
||||
functionAuthor: string;
|
||||
genType: string;
|
||||
genPath: string;
|
||||
pkColumn?: any;
|
||||
columns?: any;
|
||||
options?: any;
|
||||
@ -22,16 +25,6 @@ export interface TableVO extends BaseEntity {
|
||||
menuIds?: any;
|
||||
parentMenuId?: any;
|
||||
parentMenuName?: any;
|
||||
enableExport?: boolean;
|
||||
enableStatus?: boolean;
|
||||
statusField?: string;
|
||||
enableUnique?: boolean;
|
||||
uniqueFields?: string[];
|
||||
enableSort?: boolean;
|
||||
sortField?: string;
|
||||
treeRootValue?: string;
|
||||
treeAncestorsField?: string;
|
||||
treeOrderField?: string;
|
||||
tree: boolean;
|
||||
crud: boolean;
|
||||
}
|
||||
@ -79,14 +72,17 @@ export interface DbTableVO {
|
||||
tableId?: any;
|
||||
tableName: string;
|
||||
tableComment: string;
|
||||
subTableName?: any;
|
||||
subTableFkName?: any;
|
||||
className?: any;
|
||||
tplCategory?: any;
|
||||
frontendType?: string;
|
||||
packageName?: any;
|
||||
moduleName?: any;
|
||||
businessName?: any;
|
||||
functionName?: any;
|
||||
functionAuthor?: any;
|
||||
genType?: any;
|
||||
genPath?: any;
|
||||
pkColumn?: any;
|
||||
columns: DbColumnVO[];
|
||||
options?: any;
|
||||
@ -97,16 +93,6 @@ export interface DbTableVO {
|
||||
menuIds?: any;
|
||||
parentMenuId?: any;
|
||||
parentMenuName?: any;
|
||||
enableExport?: boolean;
|
||||
enableStatus?: boolean;
|
||||
statusField?: string;
|
||||
enableUnique?: boolean;
|
||||
uniqueFields?: string[];
|
||||
enableSort?: boolean;
|
||||
sortField?: string;
|
||||
treeRootValue?: string;
|
||||
treeAncestorsField?: string;
|
||||
treeOrderField?: string;
|
||||
tree: boolean;
|
||||
crud: boolean;
|
||||
}
|
||||
@ -117,14 +103,10 @@ export interface DbTableQuery extends PageQuery {
|
||||
tableComment: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 代码生成表详情接口 data 结构
|
||||
* - info:当前表 GenTable
|
||||
* - rows:字段列表 GenTableColumn[]
|
||||
*/
|
||||
export interface GenTableDetailPayload {
|
||||
export interface GenTableVO {
|
||||
info: DbTableVO;
|
||||
rows: DbColumnVO[];
|
||||
tables: DbTableVO[];
|
||||
}
|
||||
|
||||
export interface DbColumnForm extends BaseEntity {
|
||||
@ -164,16 +146,6 @@ export interface DbParamForm {
|
||||
treeName?: any;
|
||||
treeParentCode?: any;
|
||||
parentMenuId: string;
|
||||
enableExport?: boolean;
|
||||
enableStatus?: boolean;
|
||||
statusField?: string;
|
||||
enableUnique?: boolean;
|
||||
uniqueFields?: string[];
|
||||
enableSort?: boolean;
|
||||
sortField?: string;
|
||||
treeRootValue?: string;
|
||||
treeAncestorsField?: string;
|
||||
treeOrderField?: string;
|
||||
}
|
||||
|
||||
export interface DbTableForm extends BaseEntity {
|
||||
@ -181,14 +153,17 @@ export interface DbTableForm extends BaseEntity {
|
||||
tableId: string | string;
|
||||
tableName: string;
|
||||
tableComment: string;
|
||||
subTableName?: any;
|
||||
subTableFkName?: any;
|
||||
className: string;
|
||||
tplCategory: string;
|
||||
frontendType: string;
|
||||
packageName: string;
|
||||
moduleName: string;
|
||||
businessName: string;
|
||||
functionName: string;
|
||||
functionAuthor: string;
|
||||
genType: string;
|
||||
genPath: string;
|
||||
pkColumn?: any;
|
||||
columns: DbColumnForm[];
|
||||
options: string;
|
||||
@ -199,16 +174,6 @@ export interface DbTableForm extends BaseEntity {
|
||||
menuIds?: any;
|
||||
parentMenuId: string;
|
||||
parentMenuName?: any;
|
||||
enableExport?: boolean;
|
||||
enableStatus?: boolean;
|
||||
statusField?: string;
|
||||
enableUnique?: boolean;
|
||||
uniqueFields?: string[];
|
||||
enableSort?: boolean;
|
||||
sortField?: string;
|
||||
treeRootValue?: string;
|
||||
treeAncestorsField?: string;
|
||||
treeOrderField?: string;
|
||||
tree: boolean;
|
||||
crud: boolean;
|
||||
params: DbParamForm;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
* 注册
|
||||
*/
|
||||
export type RegisterForm = {
|
||||
tenantId: string;
|
||||
username: string;
|
||||
password: string;
|
||||
confirmPassword?: string;
|
||||
@ -14,6 +15,7 @@ export type RegisterForm = {
|
||||
* 登录请求
|
||||
*/
|
||||
export interface LoginData {
|
||||
tenantId?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
rememberMe?: boolean;
|
||||
@ -43,9 +45,15 @@ export interface VerifyCodeResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页返回结果
|
||||
* 租户
|
||||
*/
|
||||
export interface PageResult<T = any> {
|
||||
total: number;
|
||||
rows: T[];
|
||||
export interface TenantVO {
|
||||
companyName: string;
|
||||
domain: any;
|
||||
tenantId: string;
|
||||
}
|
||||
|
||||
export interface TenantInfo {
|
||||
tenantEnabled: boolean;
|
||||
voList: TenantVO[];
|
||||
}
|
||||
|
||||
@ -1,76 +0,0 @@
|
||||
import type { CategoryForm, CategoryQuery, CategoryTreeVO, CategoryVO } from '@/api/workflow/category/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 查询流程分类列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const listCategory = (query?: CategoryQuery): AxiosPromise<CategoryVO[]> => {
|
||||
return request({
|
||||
url: '/workflow/category/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询流程分类详细
|
||||
* @param categoryId
|
||||
*/
|
||||
export const getCategory = (categoryId: string | number): AxiosPromise<CategoryVO> => {
|
||||
return request({
|
||||
url: '/workflow/category/' + categoryId,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增流程分类
|
||||
* @param data
|
||||
*/
|
||||
export const addCategory = (data: CategoryForm) => {
|
||||
return request({
|
||||
url: '/workflow/category',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改流程分类
|
||||
* @param data
|
||||
*/
|
||||
export const updateCategory = (data: CategoryForm) => {
|
||||
return request({
|
||||
url: '/workflow/category',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除流程分类
|
||||
* @param categoryId
|
||||
*/
|
||||
export const delCategory = (categoryId: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: '/workflow/category/' + categoryId,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取流程分类树列表
|
||||
* @param query 流程实例id
|
||||
* @returns
|
||||
*/
|
||||
export const categoryTree = (query?: CategoryForm): AxiosPromise<CategoryTreeVO[]> => {
|
||||
return request({
|
||||
url: `/workflow/category/categoryTree`,
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
@ -1,67 +0,0 @@
|
||||
export interface CategoryTreeVO {
|
||||
id: number | string;
|
||||
label: string;
|
||||
parentId: number | string;
|
||||
weight: number;
|
||||
children: CategoryTreeVO[];
|
||||
}
|
||||
export interface CategoryVO {
|
||||
/**
|
||||
* 流程分类ID
|
||||
*/
|
||||
categoryId: string | number;
|
||||
|
||||
/**
|
||||
* 父级id
|
||||
*/
|
||||
parentId: string | number;
|
||||
|
||||
/**
|
||||
* 流程分类名称
|
||||
*/
|
||||
categoryName: string;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
orderNum: number;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
createTime: string;
|
||||
|
||||
/**
|
||||
* 子对象
|
||||
*/
|
||||
children: CategoryVO[];
|
||||
}
|
||||
|
||||
export interface CategoryForm extends BaseEntity {
|
||||
/**
|
||||
* 流程分类ID
|
||||
*/
|
||||
categoryId?: string | number;
|
||||
|
||||
/**
|
||||
* 流程分类名称
|
||||
*/
|
||||
categoryName?: string;
|
||||
|
||||
/**
|
||||
* 父流程分类id
|
||||
*/
|
||||
parentId?: string | number;
|
||||
|
||||
/**
|
||||
* 显示顺序
|
||||
*/
|
||||
orderNum?: number;
|
||||
}
|
||||
|
||||
export interface CategoryQuery {
|
||||
/**
|
||||
* 流程分类名称
|
||||
*/
|
||||
categoryName?: string;
|
||||
}
|
||||
@ -1,176 +0,0 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type {
|
||||
definitionXmlVO,
|
||||
FlowDefinitionForm,
|
||||
FlowDefinitionQuery,
|
||||
FlowDefinitionVo
|
||||
} from '@/api/workflow/definition/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 获取流程定义列表
|
||||
* @param query 流程实例id
|
||||
* @returns
|
||||
*/
|
||||
export const listDefinition = (query: FlowDefinitionQuery): AxiosPromise<PageResult<FlowDefinitionVo>> => {
|
||||
return request({
|
||||
url: `/workflow/definition/list`,
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询未发布的流程定义列表
|
||||
* @param query 流程实例id
|
||||
* @returns
|
||||
*/
|
||||
export const unPublishList = (query: FlowDefinitionQuery): AxiosPromise<PageResult<FlowDefinitionVo>> => {
|
||||
return request({
|
||||
url: `/workflow/definition/unPublishList`,
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过流程定义id获取xml
|
||||
* @param definitionId 流程定义id
|
||||
* @returns
|
||||
*/
|
||||
export const definitionXml = (definitionId: string): AxiosPromise<definitionXmlVO> => {
|
||||
return request({
|
||||
url: `/workflow/definition/definitionXml/${definitionId}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除流程定义
|
||||
* @param id 流程定义id
|
||||
* @returns
|
||||
*/
|
||||
export const deleteDefinition = (id: string | string[]) => {
|
||||
return request({
|
||||
url: `/workflow/definition/${id}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 挂起/激活
|
||||
* @param definitionId 流程定义id
|
||||
* @param activityStatus 状态
|
||||
* @returns
|
||||
*/
|
||||
export const active = (definitionId: string, activityStatus: boolean) => {
|
||||
return request({
|
||||
url: `/workflow/definition/active/${definitionId}`,
|
||||
method: 'put',
|
||||
params: {
|
||||
active: activityStatus
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过zip或xml部署流程定义
|
||||
* @returns
|
||||
*/
|
||||
export function importDef(data: any) {
|
||||
return request({
|
||||
url: '/workflow/definition/importDef',
|
||||
method: 'post',
|
||||
data: data,
|
||||
headers: {
|
||||
repeatSubmit: false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布流程定义
|
||||
* @param id 流程定义id
|
||||
* @returns
|
||||
*/
|
||||
export const publish = (id: string) => {
|
||||
return request({
|
||||
url: `/workflow/definition/publish/${id}`,
|
||||
method: 'put'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消发布流程定义
|
||||
* @param id 流程定义id
|
||||
* @returns
|
||||
*/
|
||||
export const unPublish = (id: string) => {
|
||||
return request({
|
||||
url: `/workflow/definition/unPublish/${id}`,
|
||||
method: 'put'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取流程定义xml字符串
|
||||
* @param id 流程定义id
|
||||
* @returns
|
||||
*/
|
||||
export const xmlString = (id: string) => {
|
||||
return request({
|
||||
url: `/workflow/definition/xmlString/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param data 参数
|
||||
* @returns
|
||||
*/
|
||||
export const add = (data: FlowDefinitionForm) => {
|
||||
return request({
|
||||
url: `/workflow/definition`,
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param data 参数
|
||||
* @returns
|
||||
*/
|
||||
export const edit = (data: FlowDefinitionForm) => {
|
||||
return request({
|
||||
url: `/workflow/definition`,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询详情
|
||||
* @param id 参数
|
||||
* @returns
|
||||
*/
|
||||
export const getInfo = (id: number | string) => {
|
||||
return request({
|
||||
url: `/workflow/definition/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 复制流程定义
|
||||
* @param id 流程定义id
|
||||
* @returns
|
||||
*/
|
||||
export const copy = (id: string) => {
|
||||
return request({
|
||||
url: `/workflow/definition/copy/${id}`,
|
||||
method: 'post'
|
||||
});
|
||||
};
|
||||
@ -1,34 +0,0 @@
|
||||
export interface FlowDefinitionQuery extends PageQuery {
|
||||
flowCode?: string;
|
||||
flowName?: string;
|
||||
category: string | number;
|
||||
isPublish?: number;
|
||||
}
|
||||
|
||||
export interface FlowDefinitionVo {
|
||||
id: string;
|
||||
flowName: string;
|
||||
flowCode: string;
|
||||
formPath: string;
|
||||
version: string;
|
||||
isPublish: number;
|
||||
activityStatus: number;
|
||||
createTime: Date;
|
||||
updateTime: Date;
|
||||
}
|
||||
|
||||
export interface FlowDefinitionForm {
|
||||
id: string;
|
||||
flowName: string;
|
||||
flowCode: string;
|
||||
category: string;
|
||||
ext: string;
|
||||
formPath: string;
|
||||
formCustom: string;
|
||||
modelValue: string;
|
||||
}
|
||||
|
||||
export interface definitionXmlVO {
|
||||
xml: string[];
|
||||
xmlStr: string;
|
||||
}
|
||||
@ -1,126 +0,0 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 查询运行中实例列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByRunning = (query: FlowInstanceQuery): AxiosPromise<PageResult<FlowInstanceVO>> => {
|
||||
return request({
|
||||
url: '/workflow/instance/pageByRunning',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询已完成实例列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByFinish = (query: FlowInstanceQuery): AxiosPromise<PageResult<FlowInstanceVO>> => {
|
||||
return request({
|
||||
url: '/workflow/instance/pageByFinish',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过业务id获取历史流程图
|
||||
*/
|
||||
export const flowHisTaskList = (businessId: string | number) => {
|
||||
return request({
|
||||
url: `/workflow/instance/flowHisTaskList/${businessId}?t=${Math.random()}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 分页查询当前登录人单据
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByCurrent = (query: FlowInstanceQuery): AxiosPromise<PageResult<FlowInstanceVO>> => {
|
||||
return request({
|
||||
url: '/workflow/instance/pageByCurrent',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 撤销流程
|
||||
* @param data 参数
|
||||
* @returns
|
||||
*/
|
||||
export const cancelProcessApply = (data: any) => {
|
||||
return request({
|
||||
url: `/workflow/instance/cancelProcessApply`,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取流程变量
|
||||
* @param instanceId 实例id
|
||||
* @returns
|
||||
*/
|
||||
export const instanceVariable = (instanceId: string | number) => {
|
||||
return request({
|
||||
url: `/workflow/instance/instanceVariable/${instanceId}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param instanceIds 流程实例id
|
||||
* @returns
|
||||
*/
|
||||
export const deleteByInstanceIds = (instanceIds: Array<string | number> | string | number) => {
|
||||
return request({
|
||||
url: `/workflow/instance/deleteByInstanceIds/${instanceIds}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除历史流程实例
|
||||
* @param instanceIds
|
||||
*/
|
||||
export const deleteHisByInstanceIds = (instanceIds: Array<string | number> | string | number) => {
|
||||
return request({
|
||||
url: `/workflow/instance/deleteHisByInstanceIds/${instanceIds}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 作废流程
|
||||
* @param data 参数
|
||||
* @returns
|
||||
*/
|
||||
export const invalid = (data: any) => {
|
||||
return request({
|
||||
url: `/workflow/instance/invalid`,
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 修改流程变量
|
||||
* @param data 参数
|
||||
* @returns
|
||||
*/
|
||||
export const updateVariable = (data: any) => {
|
||||
return request({
|
||||
url: `/workflow/instance/updateVariable`,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
import type { FlowTaskVO } from '@/api/workflow/task/types';
|
||||
|
||||
export interface FlowInstanceQuery extends PageQuery {
|
||||
category?: string | number;
|
||||
nodeName?: string;
|
||||
flowCode?: string;
|
||||
flowName?: string;
|
||||
createByIds?: Array<string | number>;
|
||||
businessId?: string;
|
||||
}
|
||||
|
||||
export interface FlowInstanceVO extends BaseEntity {
|
||||
id: string | number;
|
||||
definitionId: string;
|
||||
flowName: string;
|
||||
flowCode: string;
|
||||
version: string;
|
||||
businessId: string;
|
||||
activityStatus: number;
|
||||
tenantId: string;
|
||||
createTime: string;
|
||||
createBy: string;
|
||||
flowStatus: string;
|
||||
flowStatusName: string;
|
||||
flowTaskList: FlowTaskVO[];
|
||||
businessCode: string;
|
||||
businessTitle: string;
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 查询请假列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const listLeave = (query?: LeaveQuery): AxiosPromise<PageResult<LeaveVO>> => {
|
||||
return request({
|
||||
url: '/workflow/leave/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询请假详细
|
||||
* @param id
|
||||
*/
|
||||
export const getLeave = (id: string | number): AxiosPromise<LeaveVO> => {
|
||||
return request({
|
||||
url: '/workflow/leave/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增请假
|
||||
* @param data
|
||||
*/
|
||||
export const addLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
|
||||
return request({
|
||||
url: '/workflow/leave',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 提交请假并发起流程
|
||||
* @param data
|
||||
*/
|
||||
export const submitAndFlowStart = (data: LeaveForm): AxiosPromise<LeaveVO> => {
|
||||
return request({
|
||||
url: '/workflow/leave/submitAndFlowStart',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改请假
|
||||
* @param data
|
||||
*/
|
||||
export const updateLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
|
||||
return request({
|
||||
url: '/workflow/leave',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除请假
|
||||
* @param id
|
||||
*/
|
||||
export const delLeave = (id: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: '/workflow/leave/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
@ -1,26 +0,0 @@
|
||||
export interface LeaveVO {
|
||||
id: string | number;
|
||||
applyCode?: string;
|
||||
leaveType: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
leaveDays: number;
|
||||
remark: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export interface LeaveForm extends BaseEntity {
|
||||
id?: string | number;
|
||||
applyCode?: string;
|
||||
leaveType?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
leaveDays?: number;
|
||||
remark?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export interface LeaveQuery extends PageQuery {
|
||||
startLeaveDays?: number;
|
||||
endLeaveDays?: number;
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { SpelForm, SpelQuery, SpelVO } from '@/api/workflow/spel/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 查询流程spel表达式定义列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const listSpel = (query?: SpelQuery): AxiosPromise<PageResult<SpelVO>> => {
|
||||
return request({
|
||||
url: '/workflow/spel/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询流程spel表达式定义详细
|
||||
* @param id
|
||||
*/
|
||||
export const getSpel = (id: string | number): AxiosPromise<SpelVO> => {
|
||||
return request({
|
||||
url: '/workflow/spel/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增流程spel表达式定义
|
||||
* @param data
|
||||
*/
|
||||
export const addSpel = (data: SpelForm) => {
|
||||
return request({
|
||||
url: '/workflow/spel',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改流程spel表达式定义
|
||||
* @param data
|
||||
*/
|
||||
export const updateSpel = (data: SpelForm) => {
|
||||
return request({
|
||||
url: '/workflow/spel',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除流程spel表达式定义
|
||||
* @param id
|
||||
*/
|
||||
export const delSpel = (id: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: '/workflow/spel/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
@ -1,105 +0,0 @@
|
||||
export interface SpelVO {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
id: string | number;
|
||||
|
||||
/**
|
||||
* 组件名称
|
||||
*/
|
||||
componentName: string;
|
||||
|
||||
/**
|
||||
* 方法名
|
||||
*/
|
||||
methodName: string;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
methodParams: string;
|
||||
|
||||
/**
|
||||
* 预览spel值
|
||||
*/
|
||||
viewSpel: string;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
status: string;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface SpelForm extends BaseEntity {
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
id?: string | number;
|
||||
|
||||
/**
|
||||
* 组件名称
|
||||
*/
|
||||
componentName?: string;
|
||||
|
||||
/**
|
||||
* 方法名
|
||||
*/
|
||||
methodName?: string;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
methodParams?: string;
|
||||
|
||||
/**
|
||||
* 预览spel值
|
||||
*/
|
||||
viewSpel?: string;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
status?: string;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface SpelQuery extends PageQuery {
|
||||
/**
|
||||
* 组件名称
|
||||
*/
|
||||
componentName?: string;
|
||||
|
||||
/**
|
||||
* 方法名
|
||||
*/
|
||||
methodName?: string;
|
||||
|
||||
/**
|
||||
* 参数
|
||||
*/
|
||||
methodParams?: string;
|
||||
|
||||
/**
|
||||
* 预览spel值
|
||||
*/
|
||||
viewSpel?: string;
|
||||
|
||||
/**
|
||||
* 状态(0正常 1停用)
|
||||
*/
|
||||
status?: string;
|
||||
|
||||
/**
|
||||
* 日期范围参数
|
||||
*/
|
||||
params?: any;
|
||||
}
|
||||
@ -1,207 +0,0 @@
|
||||
import type { PageResult } from '@/api/types';
|
||||
import type { FlowTaskVO, TaskOperationBo, TaskQuery } from '@/api/workflow/task/types';
|
||||
import type { AxiosPromise } from '@/utils/api-types';
|
||||
import request from '@/utils/request';
|
||||
|
||||
/**
|
||||
* 查询待办列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByTaskWait = (query: TaskQuery): AxiosPromise<PageResult<FlowTaskVO>> => {
|
||||
return request({
|
||||
url: '/workflow/task/pageByTaskWait',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询已办列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByTaskFinish = (query: TaskQuery): AxiosPromise<PageResult<FlowTaskVO>> => {
|
||||
return request({
|
||||
url: '/workflow/task/pageByTaskFinish',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询当前用户的抄送列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByTaskCopy = (query: TaskQuery): AxiosPromise<PageResult<FlowTaskVO>> => {
|
||||
return request({
|
||||
url: '/workflow/task/pageByTaskCopy',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询全部待办任务
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByAllTaskWait = (query: TaskQuery): AxiosPromise<PageResult<FlowTaskVO>> => {
|
||||
return request({
|
||||
url: '/workflow/task/pageByAllTaskWait',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询全部已办任务
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const pageByAllTaskFinish = (query: TaskQuery): AxiosPromise<PageResult<FlowTaskVO>> => {
|
||||
return request({
|
||||
url: '/workflow/task/pageByAllTaskFinish',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 启动流程
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const startWorkFlow = (data: object): any => {
|
||||
return request({
|
||||
url: '/workflow/task/startWorkFlow',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 办理流程
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const completeTask = (data: object) => {
|
||||
return request({
|
||||
url: '/workflow/task/completeTask',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 任务驳回
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const backProcess = (data: any): any => {
|
||||
return request({
|
||||
url: '/workflow/task/backProcess',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前任务
|
||||
* @param taskId
|
||||
* @returns
|
||||
*/
|
||||
export const getTask = (taskId: string) => {
|
||||
return request({
|
||||
url: '/workflow/task/getTask/' + taskId,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改任务办理人
|
||||
* @param taskIdList
|
||||
* @param userId
|
||||
* @returns
|
||||
*/
|
||||
export const updateAssignee = (taskIdList: Array<string>, userId: string) => {
|
||||
return request({
|
||||
url: `/workflow/task/updateAssignee/${userId}`,
|
||||
method: 'put',
|
||||
data: taskIdList
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 终止任务
|
||||
* @returns
|
||||
*/
|
||||
export const terminationTask = (data: any) => {
|
||||
return request({
|
||||
url: `/workflow/task/terminationTask`,
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取可驳回得任务节点
|
||||
* @returns
|
||||
*/
|
||||
export const getBackTaskNode = (taskId: string | number, nodeCode: string) => {
|
||||
return request({
|
||||
url: `/workflow/task/getBackTaskNode/${taskId}/${nodeCode}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 任务操作 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature
|
||||
* @returns
|
||||
*/
|
||||
export const taskOperation = (data: TaskOperationBo, operation: string) => {
|
||||
return request({
|
||||
url: `/workflow/task/taskOperation/${operation}`,
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前任务办理人
|
||||
* @param taskId 任务id
|
||||
* @returns
|
||||
*/
|
||||
export const currentTaskAllUser = (taskId: string | number) => {
|
||||
return request({
|
||||
url: `/workflow/task/currentTaskAllUser/${taskId}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取下一节点写
|
||||
* @param data参数
|
||||
* @returns
|
||||
*/
|
||||
export const getNextNodeList = (data: any): any => {
|
||||
return request({
|
||||
url: '/workflow/task/getNextNodeList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 催办任务
|
||||
* @param data参数
|
||||
* @returns
|
||||
*/
|
||||
export const urgeTask = (data: any): any => {
|
||||
return request({
|
||||
url: '/workflow/task/urgeTask',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
@ -1,60 +0,0 @@
|
||||
export interface TaskQuery extends PageQuery {
|
||||
nodeName?: string;
|
||||
flowCode?: string;
|
||||
flowName?: string;
|
||||
createByIds?: Array<string | number>;
|
||||
}
|
||||
|
||||
export interface ParticipantVo {
|
||||
groupIds?: string[] | number[];
|
||||
candidate: string[] | number[];
|
||||
candidateName: string[];
|
||||
claim: boolean;
|
||||
}
|
||||
export interface FlowTaskVO {
|
||||
id: string | number;
|
||||
createTime?: Date;
|
||||
updateTime?: Date;
|
||||
tenantId?: string;
|
||||
definitionId?: string;
|
||||
instanceId: string;
|
||||
flowName: string;
|
||||
businessId: string;
|
||||
nodeCode: string;
|
||||
nodeName: string;
|
||||
flowCode: string;
|
||||
flowStatus: string;
|
||||
formCustom: string;
|
||||
formPath: string;
|
||||
nodeType: number;
|
||||
nodeRatio: string | number;
|
||||
version?: string;
|
||||
applyNode?: boolean;
|
||||
buttonList?: ButtonList[];
|
||||
copyList?: FlowCopyVo[];
|
||||
varList?: Map<string, string>;
|
||||
businessCode: string;
|
||||
businessTitle: string;
|
||||
}
|
||||
|
||||
export interface ButtonList {
|
||||
code: string;
|
||||
show: boolean;
|
||||
}
|
||||
export interface FlowCopyVo {
|
||||
userId: string | number;
|
||||
nickName: string;
|
||||
}
|
||||
|
||||
export interface TaskOperationBo {
|
||||
//委派/转办人的用户ID(必填,准对委派/转办人操作)
|
||||
userId?: string;
|
||||
//加签/减签人的用户ID列表(必填,针对加签/减签操作)
|
||||
userIds?: string[];
|
||||
//任务ID(必填)
|
||||
taskId: string | number;
|
||||
//消息类型
|
||||
messageType?: string[];
|
||||
//意见或备注信息(可选)
|
||||
message?: string;
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
import type { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
|
||||
import tab from '@/plugins/tab';
|
||||
import router from '@/router';
|
||||
|
||||
export default {
|
||||
routerJump(routerJumpVo: RouterJumpVo) {
|
||||
tab.closePage(router.currentRoute.value);
|
||||
router.push({
|
||||
path: routerJumpVo.formPath,
|
||||
query: {
|
||||
id: routerJumpVo.businessId,
|
||||
type: routerJumpVo.type,
|
||||
taskId: routerJumpVo.taskId
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1,14 +0,0 @@
|
||||
export interface RouterJumpVo {
|
||||
businessId: string;
|
||||
taskId: string | number;
|
||||
type: string;
|
||||
formCustom: string;
|
||||
formPath: string;
|
||||
}
|
||||
|
||||
export interface StartProcessBo {
|
||||
businessId: string | number;
|
||||
flowCode: string;
|
||||
variables: any;
|
||||
bizExt: any;
|
||||
}
|
||||
@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></svg>
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><path d="M321.94 98L158.82 237.78a24 24 0 000 36.44L321.94 414c15.57 13.34 39.62 2.28 39.62-18.22v-279.6c0-20.5-24.05-31.56-39.62-18.18z"/></svg>
|
||||
|
Before Width: | Height: | Size: 223 B |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><path d="M190.06 414l163.12-139.78a24 24 0 000-36.44L190.06 98c-15.57-13.34-39.62-2.28-39.62 18.22v279.6c0 20.5 24.05 31.56 39.62 18.18z"/></svg>
|
||||
|
Before Width: | Height: | Size: 223 B |
@ -1 +0,0 @@
|
||||
<svg t="1715954426124" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3305" width="200" height="200"><path d="M664.081597 1023.943114a78.246037 78.246037 0 0 1-78.985549-76.795456v-284.996471a78.27448 78.27448 0 0 1 78.985549-76.93767h280.843828A78.189152 78.189152 0 0 1 1023.939417 662.151187v284.996471a78.246037 78.246037 0 0 1-79.013992 76.795456z m-585.067605 0a78.246037 78.246037 0 0 1-78.985549-76.795456v-284.996471a78.160709 78.160709 0 0 1 78.985549-76.93767h280.786942a78.302923 78.302923 0 0 1 79.042434 76.93767v284.996471h-0.170656a78.246037 78.246037 0 0 1-78.985549 76.795456z m0-585.096048a78.217594 78.217594 0 0 1-78.985549-76.93767V76.912925a78.189152 78.189152 0 0 1 78.957106-76.795456h280.786942a78.27448 78.27448 0 0 1 79.042435 76.93767v284.996471a78.27448 78.27448 0 0 1-79.013992 76.795456z m589.675333-5.688552a77.193655 77.193655 0 0 1-77.990052-75.885288V75.888985a77.25054 77.25054 0 0 1 77.990052-75.942173h277.26004a77.25054 77.25054 0 0 1 77.961609 75.942173v281.384241a77.421197 77.421197 0 0 1-78.132266 75.885288z" p-id="3306" fill="currentColor"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1 +0,0 @@
|
||||
<svg t="1716006237008" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12400" width="200" height="200"><path d="M738.826039 1005.166431c-150.226824 0-272.00251-121.916235-272.00251-272.303686 0-150.407529 121.775686-272.323765 272.00251-272.323765 150.206745 0 271.982431 121.916235 271.982432 272.323765 0 150.387451-121.775686 272.303686-271.982432 272.303686z m-0.040157-508.225255c-128.582275 0-232.789333 104.347608-232.789333 233.09051s104.207059 233.110588 232.789333 233.110589c128.562196 0 232.769255-104.367686 232.769255-233.110589 0-128.742902-104.207059-233.09051-232.769255-233.09051z m10.561255 318.243138s-3.694431 3.674353-7.408941 3.674353a18.010353 18.010353 0 0 1-25.941333 0l-74.10949-80.916079a17.66902 17.66902 0 0 1 0-25.740549c7.408941-7.368784 22.246902-7.368784 25.941333 0l63.006118 69.872941 129.686588-117.699764a18.010353 18.010353 0 0 1 25.941333 0 17.709176 17.709176 0 0 1 0 25.760627L749.347137 815.184314zM391.529412 682.666667H190.745098a20.078431 20.078431 0 0 1 0-40.156863h200.784314a20.078431 20.078431 0 1 1 0 40.156863zM170.666667 261.019608a20.078431 20.078431 0 0 1 20.078431-20.078432h481.882353a20.078431 20.078431 0 0 1 0 40.156863H190.745098a20.078431 20.078431 0 0 1-20.078431-20.078431z m341.333333 200.784314H190.745098a20.078431 20.078431 0 0 1 0-40.156863h321.254902a20.078431 20.078431 0 0 1 0 40.156863zM813.176471 120.470588a80.313725 80.313725 0 0 0-80.313726-80.313725H130.509804a80.313725 80.313725 0 0 0-80.313726 80.313725v762.980392a80.313725 80.313725 0 0 0 80.313726 80.313726h366.832941a346.112 346.112 0 0 0 40.417882 40.779294H130.509804a120.470588 120.470588 0 0 1-120.470588-120.470588V120.470588a120.470588 120.470588 0 0 1 120.470588-120.470588h602.352941a120.470588 120.470588 0 0 1 120.470588 120.470588v293.667137a340.188863 340.188863 0 0 0-40.156862-8.533333V120.470588z" fill="currentColor" p-id="12401"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@ -1 +0,0 @@
|
||||
<svg t="1715953291934" class="icon" viewBox="0 0 1061 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1715" id="mx_n_1715953291935" width="200" height="200"><path d="M447.122465 467.332105L49.240301 268.161564A33.501036 33.501036 0 0 0 0.136043 300.744763v441.020484a33.042117 33.042117 0 0 0 16.06214 27.994016L413.162511 1018.034062a33.959954 33.959954 0 0 0 17.438895 5.50702 33.042117 33.042117 0 0 0 33.042117-33.042118V497.161795a33.042117 33.042117 0 0 0-17.438895-29.82969zM398.018207 931.298504l-331.339011-208.348907v-367.134638l331.339011 162.915996zM1046.010843 263.572381a33.042117 33.042117 0 0 0-31.665363 0L550.838 467.332105a33.042117 33.042117 0 0 0-19.733487 30.288608v493.33717a33.042117 33.042117 0 0 0 49.563176 28.452934l463.048562-265.254776a33.042117 33.042117 0 0 0 16.521059-28.452934V291.566398a33.042117 33.042117 0 0 0-14.685386-27.994017z m-50.939931 441.020484L596.72983 931.298504v-413.026468l397.882163-176.224626zM991.399565 178.672496a33.042117 33.042117 0 0 0-22.486996-29.829689L550.838 1.530034a32.583199 32.583199 0 0 0-19.733487 0L83.659173 158.021173a33.042117 33.042117 0 0 0-4.130264 61.036134l397.882163 199.170541a33.042117 33.042117 0 0 0 14.685386 3.212428 33.959954 33.959954 0 0 0 13.30863 0l463.966399-205.595398a33.042117 33.042117 0 0 0 22.028078-37.172382zM494.391049 349.849021L180.490934 195.193555l358.874108-125.743613 328.126583 112.434982z m0 0" fill="currentColor" p-id="1716"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@ -1 +0,0 @@
|
||||
<svg t="1716006583362" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="38505" width="200" height="200"><path d="M733.696 666.624l56.32-65.536-15.36-12.8c-41.472-34.816-87.552-61.44-136.192-79.36 75.264-49.152 124.928-134.144 124.928-230.912 0-152.576-123.904-276.48-276.48-276.48-74.24 0-143.872 28.672-195.584 80.384-52.224 51.712-80.896 121.344-80.896 195.584 0 92.16 45.568 174.08 115.2 224.256-81.408 26.624-156.672 74.752-215.552 144.896C34.304 736.768-4.096 850.944 0.512 968.192l1.024 20.48 86.528-4.608-1.024-19.968c-4.096-96.256 27.136-188.928 88.576-261.12 136.704-162.816 380.416-184.32 543.232-48.64l14.848 12.288zM296.96 278.016c0-106.496 83.456-189.952 189.952-189.952 104.96 0 189.952 84.992 189.952 189.952 0 106.496-83.456 189.952-189.952 189.952S296.96 384.512 296.96 278.016z m690.688 522.24H802.304c13.824-16.896 32.256-38.4 55.808-67.072 7.68-8.192 11.776-19.456 10.752-31.744-1.024-11.776-6.144-22.528-15.36-29.696-8.192-7.68-19.456-11.264-31.232-10.752-12.288 1.024-23.04 6.656-30.208 15.872-38.4 45.568-96.256 114.176-101.376 119.808-7.68 7.68-10.752 15.36-13.312 22.528-4.096 8.704-4.096 16.384-4.096 24.064 0 5.632 0 12.8 3.584 23.04 2.56 7.68 6.144 15.872 13.824 23.552l104.96 124.416 4.096 2.048c9.216 4.096 18.432 6.144 26.624 6.144 8.704 0 21.504-4.096 28.672-11.776 8.704-8.704 13.824-19.968 14.336-31.744 0-10.752-3.584-20.48-11.264-28.16l-54.272-63.488h183.296c19.456 0 35.84-18.944 36.352-43.008v-0.512c0.512-25.088-14.848-43.52-35.84-43.52z" fill="currentColor" p-id="38506"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1 +0,0 @@
|
||||
<svg t="1715953932254" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11266" width="200" height="200"><path d="M955.59576334 565.84816928C921.71190561 470.40769794 828.48968821 401.08719229 717.79871055 401.08719229c-111.30100029 0-204.91141024 70.09689085-238.29616047 166.36920831h-253.43576475c-26.23088067 0-47.5261393 24.84446618-47.5261329 55.45640711s21.2952586 55.4564006 47.5261329 55.45640054h242.73267482c6.54385326 41.3150179 23.95716606 79.02537397 49.30074631 110.91280755h-292.03342113c-26.23088067 0-47.5261393 24.84446618-47.5261329 55.45640061s21.2952586 55.4564006 47.5261329 55.45640059h214.0617167a376.93717152 376.93717152 0 0 0-33.44021086 110.91280754h-292.47706801a46.36155474 46.36155474 0 0 1-45.91790151-46.8052016V169.1685161c0-25.06629616 21.23980441-45.36333956 47.35977009-45.3633331h63.38666838v55.45640059c0 50.07713168 67.6013528 55.4564006 110.91280122 55.45640061 43.31144833 0 88.50841878 5.76746809 88.5084187-55.45640061v-55.45640059h44.53149358v55.45640059c0 61.22386864 38.15400297 55.4564006 88.84115713 55.45640061 50.74260854 0 88.56387296 5.76746809 88.56387308-55.45640061v-55.45640059h44.19875511v55.45640059c0 61.22386864 38.43128719 55.4564006 89.11844137 55.45640061s110.91280771-2.82827659 110.91280118-55.45640061v-55.45640059h63.44212904a47.69250853 47.69250853 0 0 1 47.74796275 47.63704778l-0.22182994 394.4059385zM407.96379074 345.63079175h-181.95245955c-26.23088067 0-47.5261393 24.84446618-47.52613946 55.45640054s21.2952586 55.4564006 47.52613946 55.45640711h181.95245955c26.23088067 0 47.5261393-24.84446618 47.52613268-55.45640711s-21.2952586-55.4564006-47.52613268-55.45640054z m325.75090957-166.36920816c-30.61193437 0-55.4564006-18.63335139-55.45640712-41.59230208v-83.18460405c0-22.95895071 24.84446618-41.59230206 55.45640712-41.592302s55.4564006 18.63335139 55.4564006 41.592302v83.18460405c0 22.95895071-24.84446618 41.59230206-55.4564006 41.59230208z m-222.71291552 0c-30.61193437 0-55.4009463-18.63335139-55.4009464-41.59230208v-83.18460405c0-22.95895071 24.84446618-41.59230206 55.4009464-41.592302 30.61193437 0 55.4564006 18.63335139 55.45640054 41.592302v83.18460405c-0.0554542 22.95895071-24.84446618 41.59230206-55.45640054 41.59230208z m-220.6610244 0c-30.61193437 0-55.4009463-18.63335139-55.40094634-41.59230208v-83.18460405c0-22.95895071 24.84446618-41.59230206 55.40094634-41.592302 30.61193437 0 55.4564006 18.63335139 55.45640063 41.592302v83.18460405c0 22.95895071-24.84446618 41.59230206-55.45640063 41.59230208z m443.31847922 665.92048622c-91.28124099 0-165.53736215-74.69977454-165.53736218-166.59103817 0-91.83580289 74.2561211-166.59103164 165.53736218-166.59103164s165.53736215 74.75522879 165.53736218 166.59103164-74.2561211 166.59103164-165.53736218 166.59103817z m-115.73750824-29.33644132c32.1647114 24.45627358 71.98241282 39.59587158 115.68205395 39.59587144 44.14329437 0 84.34918863-15.47233629 116.68026924-40.3722568a235.13514545 235.13514545 0 0 1 105.14533952 195.98292729h-443.6512175c0-80.35632762 41.92504052-153.94697186 106.14355479-195.20654193z" fill="currentColor" p-id="11267"></path></svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@ -1 +0,0 @@
|
||||
<svg t="1716005059256" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3268" width="200" height="200"><path d="M497.798958 952.225272A345.95419 345.95419 0 0 1 359.273733 892.652247a171.541601 171.541601 0 0 0 7.177473-47.37132A179.436821 179.436821 0 0 0 211.417793 665.126359a345.95419 345.95419 0 0 1 185.896546-380.40606 179.436821 179.436821 0 0 0 317.244299 0 351.696169 351.696169 0 0 1 143.549456 128.476763 35.169617 35.169617 0 0 0 30.145386 16.508188 37.322859 37.322859 0 0 0 19.379177-5.024231 36.605111 36.605111 0 0 0 10.766209-46.653574 424.188644 424.188644 0 0 0-183.743304-160.775391v-13.637198a180.872315 180.872315 0 1 0-358.873642 0 129.194511 129.194511 0 0 0 0 15.79044A423.470897 423.470897 0 0 0 132.465591 600.529103a467.253481 467.253481 0 0 0 6.459726 71.774728A180.154568 180.154568 0 0 0 187.014385 1024a178.001326 178.001326 0 0 0 139.96072-68.185992 430.64837 430.64837 0 0 0 158.62215 62.444014h6.459725a35.887364 35.887364 0 0 0 5.741978-71.774729z m57.419783-861.29674a109.097587 109.097587 0 1 1-108.37984 110.533082A109.097587 109.097587 0 0 1 555.218741 90.928532zM187.014385 952.225272a109.097587 109.097587 0 1 1 108.37984-108.37984A109.097587 109.097587 0 0 1 187.014385 952.225272zM933.471559 617.755038l-104.791103-71.774728a35.887364 35.887364 0 0 0-48.089068 8.612967L560.242972 858.918125a37.322859 37.322859 0 0 0-6.459725 24.403408l9.330714 104.073356a35.169617 35.169617 0 0 0 14.354946 25.838902 38.758353 38.758353 0 0 0 21.532418 7.177473h7.177473l98.331378-21.532419a38.758353 38.758353 0 0 0 22.250166-14.354946L945.673263 665.126359a36.605111 36.605111 0 0 0 5.741978-27.274397 37.322859 37.322859 0 0 0-17.943682-20.096924zM675.800285 930.692853l-45.218079 9.330715-4.306484-49.524563 193.791766-262.695505 45.218079 29.427638z m311.50232-399.067489l-103.355608-66.750497a35.887364 35.887364 0 0 0-49.524563 10.048462 35.169617 35.169617 0 0 0 10.766209 49.524562L947.826505 593.35163a34.45187 34.45187 0 0 0 20.096924 5.741979 37.322859 37.322859 0 0 0 30.145386-15.790441 36.605111 36.605111 0 0 0-10.76621-51.677804z" fill="currentColor" p-id="3269"></path></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |