diff --git a/README.zh-CN.md b/README.zh-CN.md
index d720ffe6..dbdeb729 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -1,126 +1,153 @@
-开发中:
-
-工作流模块等待后端重构后开发 暂时不开发
-
-**目前表格仅为测试使用 不代表最终版本**
-
-其他:
-
-1. 等待官方Table组件
-2. 已完成所有表单开发
-
-演示站: [点击前往](https://vben5.dapdap.top)
-
-贡献规范:
-
-文件夹/组件采用短横线命名法: 比如 `a-table.vue test-form.vue`
-
-组件导入采用手动导入&大写(button/input等常用除外 可正常使用a-button/a-input) 与html标签区分开
-
-```vue
-
-
-
-
-
-```
-
-
-
[](LICENSE)
-
Vue Vben Admin
-
+## 提示
-[](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin)    
+该仓库使用vben最新版本v5开发, 老版本v2地址 [前往](https://gitee.com/dapppp/ruoyi-plus-vben)
-**中文** | [English](./README.md) | [日本語](./README.ja-JP.md)
+v5版本采用分仓(包)目录结构, 具体开发路径为: `根目录/apps/web-antd`
+
+## 进度
+
+目前为beta版本 等待最后收尾
+
+**工作流相关模块等待后端重构后开发**
+
+基础功能大致完成,有一部分需要等待官方更新
+
+除文件上传(不包含图片上传) 基本功能都已完成
## 简介
-Vue Vben Admin 是 Vue Vben Admin 的升级版本。作为一个免费开源的中后台模板,它采用了最新的 Vue 3、Vite、TypeScript 等主流技术开发,开箱即用,可用于中后台前端开发,也适合学习参考。
+基于 [vben5 & ant-design-vue](https://github.com/vbenjs/vue-vben-admin) 的 RuoYi-Vue-Plus 前端项目
-## 升级提示
+| 组件/框架 | 版本 |
+| :------------- | :----- |
+| vben | 5.3.2 |
+| ant-design-vue | 4.2.5 |
+| vue | 3.5.11 |
-该版本为最新版本`5.0`, 与其他版本不兼容,如果你是新项目,建议使用最新版本。如果你想查看旧版本,请使用 [v2 分支](https://github.com/vbenjs/vue-vben-admin/tree/v2)
+对应后端项目: **(分布式 5.X 分支 微服务 2.分支)**
-## 特性
+分布式 [RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus/tree/5.X/)
-- **最新技术栈**:使用 Vue3/vite 等前端前沿技术开发
-- **TypeScript**: 应用程序级 JavaScript 的语言
-- **主题**:提供多套主题色彩,可配置自定义主题
-- **国际化**:内置完善的国际化方案
-- **权限** 内置完善的动态路由权限生成方案
+微服务 [RuoYi-Cloud-Plus](https://gitee.com/dromara/RuoYi-Cloud-Plus/tree/2.X/)
## 预览
-- [Vben Admin](https://vben.pro/) - 完整版中文站点
+admin 账号: admin admin123
-测试账号: vben/123456
+[预览地址点这里](http://vben5.dapdap.top)
-
-
-
-
-
+## WX Group
-### 使用 Gitpod
-
-在 Gitpod(适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码.
-
-[](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
+暂不开放
## 文档
-[文档地址](https://doc.vben.pro/)
+[vben 文档地址](https://doc.vvbin.cn/)
+
+[RuoYi-Plus 文档地址](https://plus-doc.dromara.org/#/)
+
+## 预览图
+
+         
## 安装使用
+前置准备环境(只能用pnpm)
+
+```json
+"packageManager": "pnpm",
+"engines": {
+ "node": ">=20.10.0",
+ "pnpm": ">=9.5.0"
+},
+```
+
- 获取项目代码
```bash
-git clone https://github.com/vbenjs/vue-vben-admin.git
+git clone https://gitee.com/dapppp/ruoyi-plus-vben5.git
```
- 安装依赖
```bash
-cd vue-vben-admin
-
-corepack enable
+cd ruoyi-plus-vben5
pnpm install
```
+- 关于代码生成
+
+v5版本代码生成模板为付费功能(暂未开放)
+
+- 关于一些监控的地址配置(微服务版本可以跳过这一小节)
+
+使用[RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus/tree/5.X/)注意 `已经去除 admin/snailjob 的.env 配置` 可自行修改 有两种方式
+
+1. 修改源码`/views/monitor/admin` `views/monitor/snailjob`
+
+```ts
+// 修改地址
+const url = ref('http://127.0.0.1:7700/#/oms/home');
+```
+
+2. **推荐** 使用菜单自行配置 (跟 cloud 版本打开方式一致)
+
+
+
+使用内嵌 iframe 方式需要解决跨域问题 可参考[nginx.conf](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/5.X/script/docker/nginx/conf/nginx.conf#LC87)配置
+
+- 修改.env.development 配置文件
+- **注意 RSA 公私钥一定要修改和后端匹配**
+- RSA 公私钥为两对 `前端请求加密-后端解密是一对` `后端响应加密 前端解密是一对`
+
+```properties
+# 端口号
+VITE_PORT=5666
+
+VITE_BASE=/
+# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
+VITE_NITRO_MOCK=false
+# 是否打开 devtools,true 为打开,false 为关闭
+VITE_DEVTOOLS=false
+# 是否注入全局loading
+VITE_INJECT_APP_LOADING=true
+
+# 后台请求路径 具体在vite.config.mts配置代理
+VITE_GLOB_API_URL=/api
+
+# 全局加密开关(即开启了加解密功能才会生效 不是全部接口加密 需要和后端对应)
+VITE_GLOB_ENABLE_ENCRYPT=true
+# RSA公钥 请求加密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
+VITE_GLOB_RSA_PUBLIC_KEY=
+# RSA私钥 响应解密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
+VITE_GLOB_RSA_PRIVATE_KEY=
+# 客户端id
+VITE_GLOB_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
+
+# 开启WEBSOCKET
+VITE_GLOB_WEBSOCKET_ENABLE=false
+```
+
- 运行
```bash
-pnpm dev
+pnpm dev:antd
```
- 打包
```bash
-pnpm build
+pnpm build:antd
```
-## 更新日志
+## 这是一个特性 而不是一个bug!
-[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
-
-## 如何贡献
-
-非常欢迎你的加入 或者提交一个 Pull Request。
-
-**Pull Request:**
-
-1. Fork 代码!
-2. 创建自己的分支: `git checkout -b feature/xxxx`
-3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
-4. 推送您的分支: `git push origin feature/xxxx`
-5. 提交`pull request`
+1. 菜单管理可分配 但只有`admin`/`superadmin`角色能访问 其他角色访问会到403页面
+2. 租户相关菜单可分配 但只有`superadmin`角色能访问 其他角色访问会到403页面
+3. 分配的租户管理员无法修改自己的角色的菜单(即管理员角色的菜单) 防止自己把自己权限弄没了
## Git 贡献提交规范
@@ -135,13 +162,16 @@ pnpm build
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
+ - `workflow` 工作流改进
- `ci` 持续集成
- `types` 类型定义文件更改
- `wip` 开发中
## 浏览器支持
-本地开发推荐使用`Chrome 80+` 浏览器
+最低适配应该为`Chrome 88+`以上浏览器 详见 [css - where](https://developer.mozilla.org/en-US/docs/Web/CSS/:where#browser_compatibility)
+
+本地开发推荐使用`Chrome` 最新版本浏览器
支持现代浏览器, 不支持 IE
@@ -149,33 +179,8 @@ pnpm build
| :-: | :-: | :-: | :-: | :-: |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
-## 维护者
-
-[@Vben](https://github.com/anncwb)
-
-## Star History
-
-[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
-
## 捐赠
-如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
+如果项目帮助到您 可以考虑请作者喝杯咖啡 万分感谢您对开源的支持!
-
-
-Paypal Me
-
-## Contributor
-
-
-
-
-
-## Discord
-
-- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
-
-## License
-
-[MIT © Vben-2020](./LICENSE)
+
diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json
index 48a8d727..2d22f369 100644
--- a/apps/web-antd/package.json
+++ b/apps/web-antd/package.json
@@ -26,6 +26,7 @@
"#/*": "./src/*"
},
"dependencies": {
+ "@ant-design/icons-vue": "^7.0.1",
"@tinymce/tinymce-vue": "^6.0.1",
"@vben/access": "workspace:*",
"@vben/common-ui": "workspace:*",
diff --git a/apps/web-antd/src/adapter/form.ts b/apps/web-antd/src/adapter/form.ts
index 3a9352fb..2bae74ac 100644
--- a/apps/web-antd/src/adapter/form.ts
+++ b/apps/web-antd/src/adapter/form.ts
@@ -36,6 +36,7 @@ import {
import { isArray } from 'lodash-es';
import { Tinymce as RichTextarea } from '#/components/tinymce';
+import { ImageUpload } from '#/components/upload';
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
export type FormComponentType =
@@ -44,6 +45,7 @@ export type FormComponentType =
| 'CheckboxGroup'
| 'DatePicker'
| 'Divider'
+ | 'ImageUpload'
| 'Input'
| 'InputNumber'
| 'InputPassword'
@@ -104,6 +106,7 @@ setupVbenForm({
TimePicker,
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
Upload,
+ ImageUpload,
},
config: {
// ant design vue组件库默认都是 v-model:value
diff --git a/apps/web-antd/src/api/core/upload.ts b/apps/web-antd/src/api/core/upload.ts
index aeb0328b..a7b7f91b 100644
--- a/apps/web-antd/src/api/core/upload.ts
+++ b/apps/web-antd/src/api/core/upload.ts
@@ -1,7 +1,13 @@
import { requestClient } from '#/api/request';
+/**
+ * 通过单文件上传接口
+ * @param file 上传的文件
+ * @returns 上传结果
+ */
export function uploadApi(file: Blob | File) {
- return requestClient.upload('/resource/oss/upload', file);
+ console.log('uploadApi', file);
+ return requestClient.upload('/resource/oss/upload', { file });
}
/**
* 默认上传结果
diff --git a/apps/web-antd/src/components/upload/index.ts b/apps/web-antd/src/components/upload/index.ts
new file mode 100644
index 00000000..89fac34a
--- /dev/null
+++ b/apps/web-antd/src/components/upload/index.ts
@@ -0,0 +1 @@
+export { default as ImageUpload } from './src/image-upload.vue';
diff --git a/apps/web-antd/src/components/upload/src/helper.ts b/apps/web-antd/src/components/upload/src/helper.ts
new file mode 100644
index 00000000..7c7c0078
--- /dev/null
+++ b/apps/web-antd/src/components/upload/src/helper.ts
@@ -0,0 +1,32 @@
+export function checkFileType(file: File, accepts: string[]) {
+ let reg;
+ if (!accepts || accepts.length === 0) {
+ reg = /.(?:jpg|jpeg|png|gif|webp)$/i;
+ } else {
+ const newTypes = accepts.join('|');
+ reg = new RegExp(`${String.raw`\.(` + newTypes})$`, 'i');
+ }
+ return reg.test(file.name);
+}
+
+export function checkImgType(file: File) {
+ return isImgTypeByName(file.name);
+}
+
+export function isImgTypeByName(name: string) {
+ return /\.(?:jpg|jpeg|png|gif|webp)$/i.test(name);
+}
+
+export function getBase64WithFile(file: File) {
+ return new Promise<{
+ file: File;
+ result: string;
+ }>((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.addEventListener('load', () =>
+ resolve({ result: reader.result as string, file }),
+ );
+ reader.addEventListener('error', (error) => reject(error));
+ });
+}
diff --git a/apps/web-antd/src/components/upload/src/image-upload.vue b/apps/web-antd/src/components/upload/src/image-upload.vue
new file mode 100644
index 00000000..aae5c37c
--- /dev/null
+++ b/apps/web-antd/src/components/upload/src/image-upload.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+
+
{{ $t('component.upload.upload') }}
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/components/upload/src/typing.ts b/apps/web-antd/src/components/upload/src/typing.ts
new file mode 100644
index 00000000..8f87fe28
--- /dev/null
+++ b/apps/web-antd/src/components/upload/src/typing.ts
@@ -0,0 +1,37 @@
+import type { Recordable } from '@vben/types';
+
+export enum UploadResultStatus {
+ DONE = 'done',
+ ERROR = 'error',
+ SUCCESS = 'success',
+ UPLOADING = 'uploading',
+}
+
+export interface FileItem {
+ thumbUrl?: string;
+ name: string;
+ size: number | string;
+ type?: string;
+ percent: number;
+ file: File;
+ status?: UploadResultStatus;
+ response?: { fileName: string; ossId: string; url: string } | Recordable;
+ uuid: string;
+}
+
+export interface Wrapper {
+ record: FileItem;
+ uidKey: string;
+ valueKey: string;
+}
+
+export interface BaseFileItem {
+ uid: number | string;
+ url: string;
+ name?: string;
+}
+export interface PreviewFileItem {
+ url: string;
+ name: string;
+ type: string;
+}
diff --git a/apps/web-antd/src/components/upload/src/use-upload.ts b/apps/web-antd/src/components/upload/src/use-upload.ts
new file mode 100644
index 00000000..b8710f14
--- /dev/null
+++ b/apps/web-antd/src/components/upload/src/use-upload.ts
@@ -0,0 +1,60 @@
+import { computed, unref } from 'vue';
+import type { Ref } from 'vue';
+
+import { $t } from '@vben/locales';
+
+export function useUploadType({
+ acceptRef,
+ helpTextRef,
+ maxNumberRef,
+ maxSizeRef,
+}: {
+ acceptRef: Ref;
+ helpTextRef: Ref;
+ maxNumberRef: Ref;
+ maxSizeRef: Ref;
+}) {
+ // 文件类型限制
+ const getAccept = computed(() => {
+ const accept = unref(acceptRef);
+ if (accept && accept.length > 0) {
+ return accept;
+ }
+ return [];
+ });
+ const getStringAccept = computed(() => {
+ return unref(getAccept)
+ .map((item) => {
+ return item.indexOf('/') > 0 || item.startsWith('.')
+ ? item
+ : `.${item}`;
+ })
+ .join(',');
+ });
+
+ // 支持jpg、jpeg、png格式,不超过2M,最多可选择10张图片,。
+ const getHelpText = computed(() => {
+ const helpText = unref(helpTextRef);
+ if (helpText) {
+ return helpText;
+ }
+ const helpTexts: string[] = [];
+
+ const accept = unref(acceptRef);
+ if (accept.length > 0) {
+ helpTexts.push($t('component.upload.accept', [accept.join(',')]));
+ }
+
+ const maxSize = unref(maxSizeRef);
+ if (maxSize) {
+ helpTexts.push($t('component.upload.maxSize', [maxSize]));
+ }
+
+ const maxNumber = unref(maxNumberRef);
+ if (maxNumber && maxNumber !== Infinity) {
+ helpTexts.push($t('component.upload.maxNumber', [maxNumber]));
+ }
+ return helpTexts.join(',');
+ });
+ return { getAccept, getStringAccept, getHelpText };
+}
diff --git a/apps/web-antd/src/locales/langs/en-US.json b/apps/web-antd/src/locales/langs/en-US.json
index 7049c320..45590224 100644
--- a/apps/web-antd/src/locales/langs/en-US.json
+++ b/apps/web-antd/src/locales/langs/en-US.json
@@ -29,6 +29,35 @@
"notice": {
"title": "Notice",
"received": "You have received a new message"
+ },
+ "upload": {
+ "save": "Save",
+ "upload": "Upload",
+ "imgUpload": "ImageUpload",
+ "uploaded": "Uploaded",
+ "operating": "Operating",
+ "del": "Delete",
+ "download": "download",
+ "saveWarn": "Please wait for the file to upload and save!",
+ "saveError": "There is no file successfully uploaded and cannot be saved!",
+ "preview": "Preview",
+ "choose": "Select the file",
+ "accept": "Support {0} format",
+ "acceptUpload": "Only upload files in {0} format",
+ "maxSize": "A single file does not exceed {0}MB ",
+ "maxSizeMultiple": "Only upload files up to {0}MB!",
+ "maxNumber": "Only upload up to {0} files",
+ "legend": "Legend",
+ "fileName": "File name",
+ "fileSize": "File size",
+ "fileStatue": "File status",
+ "pending": "Pending",
+ "startUpload": "Start upload",
+ "uploadSuccess": "Upload successfully",
+ "uploadError": "Upload failed",
+ "uploading": "Uploading",
+ "uploadWait": "Please wait for the file upload to finish",
+ "reUploadFailed": "Re-upload failed files"
}
},
"pages": {
diff --git a/apps/web-antd/src/locales/langs/zh-CN.json b/apps/web-antd/src/locales/langs/zh-CN.json
index 5c6e4986..c0df070b 100644
--- a/apps/web-antd/src/locales/langs/zh-CN.json
+++ b/apps/web-antd/src/locales/langs/zh-CN.json
@@ -29,6 +29,35 @@
"notice": {
"title": "消息",
"received": "收到新消息"
+ },
+ "upload": {
+ "save": "保存",
+ "upload": "上传",
+ "imgUpload": "图片上传",
+ "uploaded": "已上传",
+ "operating": "操作",
+ "del": "删除",
+ "download": "下载",
+ "saveWarn": "请等待文件上传后,保存!",
+ "saveError": "没有上传成功的文件,无法保存!",
+ "preview": "预览",
+ "choose": "选择文件",
+ "accept": "支持{0}格式",
+ "acceptUpload": "只能上传{0}格式文件",
+ "maxSize": "单个文件不超过{0}MB",
+ "maxSizeMultiple": "只能上传不超过{0}MB的文件!",
+ "maxNumber": "最多只能上传{0}个文件",
+ "legend": "略缩图",
+ "fileName": "文件名",
+ "fileSize": "文件大小",
+ "fileStatue": "状态",
+ "pending": "待上传",
+ "startUpload": "开始上传",
+ "uploadSuccess": "上传成功",
+ "uploadError": "上传失败",
+ "uploading": "上传中",
+ "uploadWait": "请等待文件上传结束后操作",
+ "reUploadFailed": "重新上传失败文件"
}
},
"pages": {
diff --git a/apps/web-antd/src/views/_core/profile/profile-panel.vue b/apps/web-antd/src/views/_core/profile/profile-panel.vue
index 93f57082..6501d0a0 100644
--- a/apps/web-antd/src/views/_core/profile/profile-panel.vue
+++ b/apps/web-antd/src/views/_core/profile/profile-panel.vue
@@ -3,7 +3,7 @@ import type { UserProfile } from '#/api/system/profile/model';
import { computed } from 'vue';
-import { usePreferences } from '@vben/preferences';
+import { preferences, usePreferences } from '@vben/preferences';
import {
Card,
@@ -24,9 +24,7 @@ defineEmits<{
}>();
const avatar = computed(
- () =>
- props.profile?.user.avatar ??
- 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
+ () => props.profile?.user.avatar ?? preferences.app.defaultAvatar,
);
const { isDark } = usePreferences();
diff --git a/apps/web-antd/src/views/demo/demo/api/index.ts b/apps/web-antd/src/views/demo/demo/api/index.ts
new file mode 100755
index 00000000..4590457c
--- /dev/null
+++ b/apps/web-antd/src/views/demo/demo/api/index.ts
@@ -0,0 +1,60 @@
+import type { DemoForm, DemoQuery, DemoVO } from './model';
+
+import type { ID, IDS, PageResult } from '#/api/common';
+
+import { commonExport } from '#/api/helper';
+import { requestClient } from '#/api/request';
+
+/**
+ * 查询测试单表列表
+ * @param params
+ * @returns 测试单表列表
+ */
+export function demoList(params?: DemoQuery) {
+ return requestClient.get>('/demo/demo/list', { params });
+}
+
+/**
+ * 导出测试单表列表
+ * @param params
+ * @returns 测试单表列表
+ */
+export function demoExport(params?: DemoQuery) {
+ return commonExport('/demo/demo/export', params ?? {});
+}
+
+/**
+ * 查询测试单表详情
+ * @param id id
+ * @returns 测试单表详情
+ */
+export function demoInfo(id: ID) {
+ return requestClient.get(`/demo/demo/${id}`);
+}
+
+/**
+ * 新增测试单表
+ * @param data
+ * @returns void
+ */
+export function demoAdd(data: DemoForm) {
+ return requestClient.postWithMsg('/demo/demo', data);
+}
+
+/**
+ * 更新测试单表
+ * @param data
+ * @returns void
+ */
+export function demoUpdate(data: DemoForm) {
+ return requestClient.putWithMsg('/demo/demo', data);
+}
+
+/**
+ * 删除测试单表
+ * @param id id
+ * @returns void
+ */
+export function demoRemove(id: ID | IDS) {
+ return requestClient.deleteWithMsg(`/demo/demo/${id}`);
+}
diff --git a/apps/web-antd/src/views/demo/demo/api/model.d.ts b/apps/web-antd/src/views/demo/demo/api/model.d.ts
new file mode 100755
index 00000000..e7f69c48
--- /dev/null
+++ b/apps/web-antd/src/views/demo/demo/api/model.d.ts
@@ -0,0 +1,82 @@
+import type { BaseEntity, PageQuery } from '#/api/common';
+
+export interface DemoVO {
+ /**
+ * 主键
+ */
+ id: number | string;
+
+ /**
+ * 排序号
+ */
+ orderNum: number;
+
+ /**
+ * key键
+ */
+ testKey: string;
+
+ /**
+ * 值
+ */
+ value: string;
+
+ /**
+ * 版本
+ */
+ version: number;
+}
+
+export interface DemoForm extends BaseEntity {
+ /**
+ * 主键
+ */
+ id?: number | string;
+
+ /**
+ * 排序号
+ */
+ orderNum?: number;
+
+ /**
+ * key键
+ */
+ testKey?: string;
+
+ /**
+ * 值
+ */
+ value?: string;
+
+ /**
+ * 版本
+ */
+ version?: number;
+}
+
+export interface DemoQuery extends PageQuery {
+ /**
+ * 排序号
+ */
+ orderNum?: number;
+
+ /**
+ * key键
+ */
+ testKey?: string;
+
+ /**
+ * 值
+ */
+ value?: string;
+
+ /**
+ * 版本
+ */
+ version?: number;
+
+ /**
+ * 日期范围参数
+ */
+ params?: any;
+}
diff --git a/apps/web-antd/src/views/demo/demo/data.ts b/apps/web-antd/src/views/demo/demo/data.ts
new file mode 100755
index 00000000..d745d5e9
--- /dev/null
+++ b/apps/web-antd/src/views/demo/demo/data.ts
@@ -0,0 +1,91 @@
+import type { FormSchemaGetter, VxeGridProps } from '#/adapter';
+
+export const querySchema: FormSchemaGetter = () => [
+ {
+ component: 'Input',
+ fieldName: 'orderNum',
+ label: '排序号',
+ },
+ {
+ component: 'Input',
+ fieldName: 'testKey',
+ label: 'key键',
+ },
+ {
+ component: 'Input',
+ fieldName: 'value',
+ label: '值',
+ },
+ {
+ component: 'Input',
+ fieldName: 'version',
+ label: '版本',
+ },
+];
+
+export const columns: VxeGridProps['columns'] = [
+ { type: 'checkbox', width: 60 },
+ {
+ title: '主键',
+ field: 'id',
+ },
+ {
+ title: '排序号',
+ field: 'orderNum',
+ },
+ {
+ title: 'key键',
+ field: 'testKey',
+ },
+ {
+ title: '值',
+ field: 'value',
+ },
+ {
+ title: '版本',
+ field: 'version',
+ },
+ {
+ field: 'action',
+ fixed: 'right',
+ slots: { default: 'action' },
+ title: '操作',
+ width: 180,
+ },
+];
+
+export const modalSchema: FormSchemaGetter = () => [
+ {
+ label: '主键',
+ fieldName: 'id',
+ component: 'Input',
+ dependencies: {
+ show: () => false,
+ triggerFields: [''],
+ },
+ },
+ {
+ label: '排序号',
+ fieldName: 'orderNum',
+ component: 'Input',
+ rules: 'required',
+ },
+ {
+ label: 'key键',
+ fieldName: 'testKey',
+ component: 'Input',
+ rules: 'required',
+ },
+ {
+ label: '值',
+ fieldName: 'value',
+ component: 'Input',
+ rules: 'required',
+ },
+ {
+ label: '版本',
+ fieldName: 'version',
+ component: 'Input',
+ rules: 'required',
+ },
+];
diff --git a/apps/web-antd/src/views/demo/demo/demo-modal.vue b/apps/web-antd/src/views/demo/demo/demo-modal.vue
new file mode 100755
index 00000000..758cc031
--- /dev/null
+++ b/apps/web-antd/src/views/demo/demo/demo-modal.vue
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/demo/demo/index.vue b/apps/web-antd/src/views/demo/demo/index.vue
index 06372a15..bf6ea62e 100644
--- a/apps/web-antd/src/views/demo/demo/index.vue
+++ b/apps/web-antd/src/views/demo/demo/index.vue
@@ -1,9 +1,183 @@
-
-
-
+
+
+
+ 测试单表列表
+
+
+
+
+ {{ $t('pages.common.export') }}
+
+
+ {{ $t('pages.common.delete') }}
+
+
+ {{ $t('pages.common.add') }}
+
+
+
+
+
+ {{ $t('pages.common.edit') }}
+
+
+
+ {{ $t('pages.common.delete') }}
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/demo/tree/api/index.ts b/apps/web-antd/src/views/demo/tree/api/index.ts
new file mode 100755
index 00000000..3df12a26
--- /dev/null
+++ b/apps/web-antd/src/views/demo/tree/api/index.ts
@@ -0,0 +1,50 @@
+import type { TreeForm, TreeQuery, TreeVO } from './model';
+
+import type { ID, IDS } from '#/api/common';
+
+import { requestClient } from '#/api/request';
+
+/**
+ * 查询测试树列表
+ * @param params
+ * @returns 测试树列表
+ */
+export function treeList(params?: TreeQuery) {
+ return requestClient.get('/demo/tree/list', { params });
+}
+
+/**
+ * 查询测试树详情
+ * @param id id
+ * @returns 测试树详情
+ */
+export function treeInfo(id: ID) {
+ return requestClient.get(`/demo/tree/${id}`);
+}
+
+/**
+ * 新增测试树
+ * @param data
+ * @returns void
+ */
+export function treeAdd(data: TreeForm) {
+ return requestClient.postWithMsg('/demo/tree', data);
+}
+
+/**
+ * 更新测试树
+ * @param data
+ * @returns void
+ */
+export function treeUpdate(data: TreeForm) {
+ return requestClient.putWithMsg('/demo/tree', data);
+}
+
+/**
+ * 删除测试树
+ * @param id id
+ * @returns void
+ */
+export function treeRemove(id: ID | IDS) {
+ return requestClient.deleteWithMsg(`/demo/tree/${id}`);
+}
diff --git a/apps/web-antd/src/views/demo/tree/api/model.d.ts b/apps/web-antd/src/views/demo/tree/api/model.d.ts
new file mode 100755
index 00000000..87ba83db
--- /dev/null
+++ b/apps/web-antd/src/views/demo/tree/api/model.d.ts
@@ -0,0 +1,102 @@
+import type { BaseEntity } from '#/api/common';
+
+export interface TreeVO {
+ /**
+ * 主键
+ */
+ id: number | string;
+
+ /**
+ * 父id
+ */
+ parentId: number | string;
+
+ /**
+ * 部门id
+ */
+ deptId: number | string;
+
+ /**
+ * 用户id
+ */
+ userId: number | string;
+
+ /**
+ * 值
+ */
+ treeName: string;
+
+ /**
+ * 版本
+ */
+ version: number;
+
+ /**
+ * 子对象
+ */
+ children: TreeVO[];
+}
+
+export interface TreeForm extends BaseEntity {
+ /**
+ * 主键
+ */
+ id?: number | string;
+
+ /**
+ * 父id
+ */
+ parentId?: number | string;
+
+ /**
+ * 部门id
+ */
+ deptId?: number | string;
+
+ /**
+ * 用户id
+ */
+ userId?: number | string;
+
+ /**
+ * 值
+ */
+ treeName?: string;
+
+ /**
+ * 版本
+ */
+ version?: number;
+}
+
+export interface TreeQuery {
+ /**
+ * 父id
+ */
+ parentId?: number | string;
+
+ /**
+ * 部门id
+ */
+ deptId?: number | string;
+
+ /**
+ * 用户id
+ */
+ userId?: number | string;
+
+ /**
+ * 值
+ */
+ treeName?: string;
+
+ /**
+ * 版本
+ */
+ version?: number;
+
+ /**
+ * 日期范围参数
+ */
+ params?: any;
+}
diff --git a/apps/web-antd/src/views/demo/tree/data.ts b/apps/web-antd/src/views/demo/tree/data.ts
new file mode 100755
index 00000000..5eaca015
--- /dev/null
+++ b/apps/web-antd/src/views/demo/tree/data.ts
@@ -0,0 +1,106 @@
+import type { FormSchemaGetter, VxeGridProps } from '#/adapter';
+
+export const querySchema: FormSchemaGetter = () => [
+ {
+ component: 'Input',
+ fieldName: 'parentId',
+ label: '父id',
+ },
+ {
+ component: 'Input',
+ fieldName: 'deptId',
+ label: '部门id',
+ },
+ {
+ component: 'Input',
+ fieldName: 'userId',
+ label: '用户id',
+ },
+ {
+ component: 'Input',
+ fieldName: 'treeName',
+ label: '值',
+ },
+ {
+ component: 'Input',
+ fieldName: 'version',
+ label: '版本',
+ },
+];
+
+export const columns: VxeGridProps['columns'] = [
+ {
+ title: '主键',
+ field: 'id',
+ treeNode: true,
+ },
+ {
+ title: '父id',
+ field: 'parentId',
+ },
+ {
+ title: '部门id',
+ field: 'deptId',
+ },
+ {
+ title: '用户id',
+ field: 'userId',
+ },
+ {
+ title: '值',
+ field: 'treeName',
+ },
+ {
+ title: '版本',
+ field: 'version',
+ },
+ {
+ field: 'action',
+ fixed: 'right',
+ slots: { default: 'action' },
+ title: '操作',
+ width: 180,
+ },
+];
+
+export const modalSchema: FormSchemaGetter = () => [
+ {
+ label: '主键',
+ fieldName: 'id',
+ component: 'Input',
+ dependencies: {
+ show: () => false,
+ triggerFields: [''],
+ },
+ },
+ {
+ label: '父id',
+ fieldName: 'parentId',
+ component: 'TreeSelect',
+ rules: 'required',
+ },
+ {
+ label: '部门id',
+ fieldName: 'deptId',
+ component: 'Input',
+ rules: 'required',
+ },
+ {
+ label: '用户id',
+ fieldName: 'userId',
+ component: 'Input',
+ rules: 'required',
+ },
+ {
+ label: '值',
+ fieldName: 'treeName',
+ component: 'Input',
+ rules: 'required',
+ },
+ {
+ label: '版本',
+ fieldName: 'version',
+ component: 'Input',
+ rules: 'required',
+ },
+];
diff --git a/apps/web-antd/src/views/demo/tree/index.vue b/apps/web-antd/src/views/demo/tree/index.vue
index 06372a15..95adccca 100644
--- a/apps/web-antd/src/views/demo/tree/index.vue
+++ b/apps/web-antd/src/views/demo/tree/index.vue
@@ -1,9 +1,147 @@
-
-
-
+
+
+
+ 测试树列表
+
+
+
+
+ {{ $t('pages.common.collapse') }}
+
+
+ {{ $t('pages.common.expand') }}
+
+
+ {{ $t('pages.common.add') }}
+
+
+
+
+
+ {{ $t('pages.common.edit') }}
+
+
+
+ {{ $t('pages.common.delete') }}
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/demo/tree/tree-modal.vue b/apps/web-antd/src/views/demo/tree/tree-modal.vue
new file mode 100755
index 00000000..00907d4d
--- /dev/null
+++ b/apps/web-antd/src/views/demo/tree/tree-modal.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
diff --git a/apps/web-antd/src/views/monitor/logininfor/index.vue b/apps/web-antd/src/views/monitor/logininfor/index.vue
index 090287c5..19720295 100644
--- a/apps/web-antd/src/views/monitor/logininfor/index.vue
+++ b/apps/web-antd/src/views/monitor/logininfor/index.vue
@@ -137,7 +137,10 @@ async function handleUnlock() {
-
+
{{ $t('pages.common.clear') }}
{{ $t('pages.common.delete') }}
-
+
解锁
diff --git a/apps/web-antd/src/views/system/menu/index.vue b/apps/web-antd/src/views/system/menu/index.vue
index 54525ed4..cce6e0af 100644
--- a/apps/web-antd/src/views/system/menu/index.vue
+++ b/apps/web-antd/src/views/system/menu/index.vue
@@ -1,7 +1,11 @@
-
+
菜单权限列表
@@ -136,4 +153,5 @@ function collapseAll() {
+
diff --git a/apps/web-antd/src/views/system/role/index.vue b/apps/web-antd/src/views/system/role/index.vue
index 02fe3d1f..2c5de524 100644
--- a/apps/web-antd/src/views/system/role/index.vue
+++ b/apps/web-antd/src/views/system/role/index.vue
@@ -1,7 +1,7 @@
-
+
租户列表
@@ -183,6 +199,19 @@ const { hasAccessByCodes } = useAccess();
>
{{ $t('pages.common.edit') }}
+
+
+ {{ $t('pages.common.sync') }}
+
+
+
diff --git a/apps/web-antd/src/views/system/tenantPackage/index.vue b/apps/web-antd/src/views/system/tenantPackage/index.vue
index cc3619dc..2dadde00 100644
--- a/apps/web-antd/src/views/system/tenantPackage/index.vue
+++ b/apps/web-antd/src/views/system/tenantPackage/index.vue
@@ -1,10 +1,11 @@
-
+
租户套餐列表
@@ -197,4 +206,5 @@ const { hasAccessByCodes } = useAccess();
+
diff --git a/apps/web-antd/src/views/system/user/index.vue b/apps/web-antd/src/views/system/user/index.vue
index 2bbc376a..4fa7a2d0 100644
--- a/apps/web-antd/src/views/system/user/index.vue
+++ b/apps/web-antd/src/views/system/user/index.vue
@@ -10,6 +10,7 @@ import {
type VbenFormProps,
} from '@vben/common-ui';
import { $t } from '@vben/locales';
+import { preferences } from '@vben/preferences';
import { getPopupContainer } from '@vben/utils';
import {
@@ -122,7 +123,6 @@ const gridOptions: VxeGridProps = {
align: 'center',
showOverflow: true,
};
-
const checked = ref(false);
const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
@@ -236,10 +236,7 @@ function handleResetPwd(record: Recordable) {
-
+
+import { ref } from 'vue';
+
+import { JsonPreview, Page } from '@vben/common-ui';
+
+import { RadioGroup } from 'ant-design-vue';
+
+import { ImageUpload } from '#/components/upload';
+
+const resultField = ref<'ossId' | 'url'>('ossId');
+
+const fileList = ref([]);
+const fieldOptions = [
+ { label: 'ossId', value: 'ossId' },
+ { label: '链接地址', value: 'url' },
+];
+
+
+
+
+
+
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9431dfdb..7f263087 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -621,6 +621,9 @@ importers:
apps/web-antd:
dependencies:
+ '@ant-design/icons-vue':
+ specifier: ^7.0.1
+ version: 7.0.1(vue@3.5.11(typescript@5.6.2))
'@tinymce/tinymce-vue':
specifier: ^6.0.1
version: 6.0.1(vue@3.5.11(typescript@5.6.2))
@@ -5926,9 +5929,6 @@ packages:
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
engines: {node: '>=12.13'}
- core-js-compat@3.38.0:
- resolution: {integrity: sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==}
-
core-js-compat@3.38.1:
resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==}
@@ -12029,7 +12029,7 @@ snapshots:
babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.2)
babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.2)
babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.2)
- core-js-compat: 3.38.0
+ core-js-compat: 3.38.1
semver: 6.3.1
transitivePeerDependencies:
- supports-color
@@ -15176,7 +15176,7 @@ snapshots:
dependencies:
'@babel/core': 7.25.2
'@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.2)
- core-js-compat: 3.38.0
+ core-js-compat: 3.38.1
transitivePeerDependencies:
- supports-color
@@ -15645,10 +15645,6 @@ snapshots:
dependencies:
is-what: 4.1.16
- core-js-compat@3.38.0:
- dependencies:
- browserslist: 4.23.3
-
core-js-compat@3.38.1:
dependencies:
browserslist: 4.23.3
diff --git a/scripts/preview/1.png b/scripts/preview/1.png
new file mode 100644
index 00000000..d538d124
Binary files /dev/null and b/scripts/preview/1.png differ
diff --git a/scripts/preview/10.png b/scripts/preview/10.png
new file mode 100644
index 00000000..30103d4e
Binary files /dev/null and b/scripts/preview/10.png differ
diff --git a/scripts/preview/2.png b/scripts/preview/2.png
new file mode 100644
index 00000000..3a4889b8
Binary files /dev/null and b/scripts/preview/2.png differ
diff --git a/scripts/preview/3.png b/scripts/preview/3.png
new file mode 100644
index 00000000..fd0ce943
Binary files /dev/null and b/scripts/preview/3.png differ
diff --git a/scripts/preview/4.png b/scripts/preview/4.png
new file mode 100644
index 00000000..822e7bda
Binary files /dev/null and b/scripts/preview/4.png differ
diff --git a/scripts/preview/5.png b/scripts/preview/5.png
new file mode 100644
index 00000000..5a58fd15
Binary files /dev/null and b/scripts/preview/5.png differ
diff --git a/scripts/preview/6.png b/scripts/preview/6.png
new file mode 100644
index 00000000..03f1038e
Binary files /dev/null and b/scripts/preview/6.png differ
diff --git a/scripts/preview/7.png b/scripts/preview/7.png
new file mode 100644
index 00000000..80ebb228
Binary files /dev/null and b/scripts/preview/7.png differ
diff --git a/scripts/preview/8.png b/scripts/preview/8.png
new file mode 100644
index 00000000..1e9f9b2d
Binary files /dev/null and b/scripts/preview/8.png differ
diff --git a/scripts/preview/9.png b/scripts/preview/9.png
new file mode 100644
index 00000000..20d497dc
Binary files /dev/null and b/scripts/preview/9.png differ