Pre Merge pull request !69 from puhui999/v-next-dev
commit
53d1dc6c65
|
|
@ -43,6 +43,7 @@
|
||||||
"@vueuse/core": "catalog:",
|
"@vueuse/core": "catalog:",
|
||||||
"ant-design-vue": "catalog:",
|
"ant-design-vue": "catalog:",
|
||||||
"dayjs": "catalog:",
|
"dayjs": "catalog:",
|
||||||
|
"highlight.js": "catalog:",
|
||||||
"pinia": "catalog:",
|
"pinia": "catalog:",
|
||||||
"vue": "catalog:",
|
"vue": "catalog:",
|
||||||
"vue-router": "catalog:"
|
"vue-router": "catalog:"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace InfraCodegenApi {
|
||||||
|
/** 代码生成表定义 */
|
||||||
|
export interface CodegenTable {
|
||||||
|
id: number;
|
||||||
|
tableId: number;
|
||||||
|
isParentMenuIdValid: boolean;
|
||||||
|
dataSourceConfigId: number;
|
||||||
|
scene: number;
|
||||||
|
tableName: string;
|
||||||
|
tableComment: string;
|
||||||
|
remark: string;
|
||||||
|
moduleName: string;
|
||||||
|
businessName: string;
|
||||||
|
className: string;
|
||||||
|
classComment: string;
|
||||||
|
author: string;
|
||||||
|
createTime: Date;
|
||||||
|
updateTime: Date;
|
||||||
|
templateType: number;
|
||||||
|
parentMenuId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 代码生成字段定义 */
|
||||||
|
export interface CodegenColumn {
|
||||||
|
id: number;
|
||||||
|
tableId: number;
|
||||||
|
columnName: string;
|
||||||
|
dataType: string;
|
||||||
|
columnComment: string;
|
||||||
|
nullable: number;
|
||||||
|
primaryKey: number;
|
||||||
|
ordinalPosition: number;
|
||||||
|
javaType: string;
|
||||||
|
javaField: string;
|
||||||
|
dictType: string;
|
||||||
|
example: string;
|
||||||
|
createOperation: number;
|
||||||
|
updateOperation: number;
|
||||||
|
listOperation: number;
|
||||||
|
listOperationCondition: string;
|
||||||
|
listOperationResult: number;
|
||||||
|
htmlType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 数据库表定义 */
|
||||||
|
export interface DatabaseTable {
|
||||||
|
name: string;
|
||||||
|
comment: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 代码生成详情 */
|
||||||
|
export interface CodegenDetail {
|
||||||
|
table: CodegenTable;
|
||||||
|
columns: CodegenColumn[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 代码预览 */
|
||||||
|
export interface CodegenPreview {
|
||||||
|
filePath: string;
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新代码生成请求 */
|
||||||
|
export interface CodegenUpdateReq {
|
||||||
|
table: any | CodegenTable;
|
||||||
|
columns: CodegenColumn[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建代码生成请求 */
|
||||||
|
export interface CodegenCreateListReq {
|
||||||
|
dataSourceConfigId: number;
|
||||||
|
tableNames: string[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询列表代码生成表定义 */
|
||||||
|
export function getCodegenTableList(dataSourceConfigId: number) {
|
||||||
|
return requestClient.get<InfraCodegenApi.CodegenTable[]>('/infra/codegen/table/list', {
|
||||||
|
params: { dataSourceConfigId },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询列表代码生成表定义 */
|
||||||
|
export function getCodegenTablePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<InfraCodegenApi.CodegenTable>>('/infra/codegen/table/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询详情代码生成表定义 */
|
||||||
|
export function getCodegenTable(id: number) {
|
||||||
|
return requestClient.get<InfraCodegenApi.CodegenDetail>('/infra/codegen/detail', {
|
||||||
|
params: { tableId: id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增代码生成表定义 */
|
||||||
|
export function createCodegenTable(data: InfraCodegenApi.CodegenCreateListReq) {
|
||||||
|
return requestClient.post('/infra/codegen/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改代码生成表定义 */
|
||||||
|
export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReq) {
|
||||||
|
return requestClient.put('/infra/codegen/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 基于数据库的表结构,同步数据库的表和字段定义 */
|
||||||
|
export function syncCodegenFromDB(id: number) {
|
||||||
|
return requestClient.put('/infra/codegen/sync-from-db', {
|
||||||
|
params: { tableId: id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 预览生成代码 */
|
||||||
|
export function previewCodegen(id: number) {
|
||||||
|
return requestClient.get<InfraCodegenApi.CodegenPreview[]>('/infra/codegen/preview', {
|
||||||
|
params: { tableId: id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 下载生成代码 */
|
||||||
|
export function downloadCodegen(id: number) {
|
||||||
|
return requestClient.download('/infra/codegen/download', {
|
||||||
|
params: { tableId: id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得表定义 */
|
||||||
|
export function getSchemaTableList(params: any) {
|
||||||
|
return requestClient.get<InfraCodegenApi.DatabaseTable[]>('/infra/codegen/db/table/list', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 基于数据库的表结构,创建代码生成器的表定义 */
|
||||||
|
export function createCodegenList(data: InfraCodegenApi.CodegenCreateListReq) {
|
||||||
|
return requestClient.post('/infra/codegen/create-list', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除代码生成表定义 */
|
||||||
|
export function deleteCodegenTable(id: number) {
|
||||||
|
return requestClient.delete('/infra/codegen/delete', {
|
||||||
|
params: { tableId: id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -11,8 +11,30 @@ const routes: RouteRecordRaw[] = [
|
||||||
activePath: '/infra/job',
|
activePath: '/infra/job',
|
||||||
keepAlive: false,
|
keepAlive: false,
|
||||||
hideInMenu: true,
|
hideInMenu: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: '/codegen',
|
||||||
|
name: 'CodegenEdit',
|
||||||
|
meta: {
|
||||||
|
icon: 'ic:baseline-view-in-ar',
|
||||||
|
keepAlive: true,
|
||||||
|
order: 1000,
|
||||||
|
title: '代码生成',
|
||||||
|
hideInMenu: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/codegen/edit',
|
||||||
|
name: 'InfraCodegenEdit',
|
||||||
|
component: () => import('#/views/infra/codegen/edit.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '修改生成配置',
|
||||||
|
activeMenu: '/infra/codegen',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default routes;
|
export default routes;
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@
|
||||||
// 全局通用状态枚举
|
// 全局通用状态枚举
|
||||||
export const CommonStatusEnum = {
|
export const CommonStatusEnum = {
|
||||||
ENABLE: 0, // 开启
|
ENABLE: 0, // 开启
|
||||||
DISABLE: 1 // 禁用
|
DISABLE: 1, // 禁用
|
||||||
}
|
};
|
||||||
|
|
||||||
// 全局用户类型枚举
|
// 全局用户类型枚举
|
||||||
export const UserTypeEnum = {
|
export const UserTypeEnum = {
|
||||||
MEMBER: 1, // 会员
|
MEMBER: 1, // 会员
|
||||||
ADMIN: 2 // 管理员
|
ADMIN: 2, // 管理员
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== SYSTEM 模块 ==========
|
// ========== SYSTEM 模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -25,16 +25,16 @@ export const UserTypeEnum = {
|
||||||
export const SystemMenuTypeEnum = {
|
export const SystemMenuTypeEnum = {
|
||||||
DIR: 1, // 目录
|
DIR: 1, // 目录
|
||||||
MENU: 2, // 菜单
|
MENU: 2, // 菜单
|
||||||
BUTTON: 3 // 按钮
|
BUTTON: 3, // 按钮
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色的类型枚举
|
* 角色的类型枚举
|
||||||
*/
|
*/
|
||||||
export const SystemRoleTypeEnum = {
|
export const SystemRoleTypeEnum = {
|
||||||
SYSTEM: 1, // 内置角色
|
SYSTEM: 1, // 内置角色
|
||||||
CUSTOM: 2 // 自定义角色
|
CUSTOM: 2, // 自定义角色
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据权限的范围枚举
|
* 数据权限的范围枚举
|
||||||
|
|
@ -44,8 +44,8 @@ export const SystemDataScopeEnum = {
|
||||||
DEPT_CUSTOM: 2, // 指定部门数据权限
|
DEPT_CUSTOM: 2, // 指定部门数据权限
|
||||||
DEPT_ONLY: 3, // 部门数据权限
|
DEPT_ONLY: 3, // 部门数据权限
|
||||||
DEPT_AND_CHILD: 4, // 部门及以下数据权限
|
DEPT_AND_CHILD: 4, // 部门及以下数据权限
|
||||||
DEPT_SELF: 5 // 仅本人数据权限
|
DEPT_SELF: 5, // 仅本人数据权限
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户的社交平台的类型枚举
|
* 用户的社交平台的类型枚举
|
||||||
|
|
@ -55,15 +55,15 @@ export const SystemUserSocialTypeEnum = {
|
||||||
title: '钉钉',
|
title: '钉钉',
|
||||||
type: 20,
|
type: 20,
|
||||||
source: 'dingtalk',
|
source: 'dingtalk',
|
||||||
img: 'https://s1.ax1x.com/2022/05/22/OzMDRs.png'
|
img: 'https://s1.ax1x.com/2022/05/22/OzMDRs.png',
|
||||||
},
|
},
|
||||||
WECHAT_ENTERPRISE: {
|
WECHAT_ENTERPRISE: {
|
||||||
title: '企业微信',
|
title: '企业微信',
|
||||||
type: 30,
|
type: 30,
|
||||||
source: 'wechat_enterprise',
|
source: 'wechat_enterprise',
|
||||||
img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png'
|
img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== INFRA 模块 ==========
|
// ========== INFRA 模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,8 +72,8 @@ export const SystemUserSocialTypeEnum = {
|
||||||
export const InfraCodegenTemplateTypeEnum = {
|
export const InfraCodegenTemplateTypeEnum = {
|
||||||
CRUD: 1, // 基础 CRUD
|
CRUD: 1, // 基础 CRUD
|
||||||
TREE: 2, // 树形 CRUD
|
TREE: 2, // 树形 CRUD
|
||||||
SUB: 3 // 主子表 CRUD
|
SUB: 15, // 主子表 CRUD
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务状态的枚举
|
* 任务状态的枚举
|
||||||
|
|
@ -81,8 +81,8 @@ export const InfraCodegenTemplateTypeEnum = {
|
||||||
export const InfraJobStatusEnum = {
|
export const InfraJobStatusEnum = {
|
||||||
INIT: 0, // 初始化中
|
INIT: 0, // 初始化中
|
||||||
NORMAL: 1, // 运行中
|
NORMAL: 1, // 运行中
|
||||||
STOP: 2 // 暂停运行
|
STOP: 2, // 暂停运行
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 异常数据的处理状态
|
* API 异常数据的处理状态
|
||||||
|
|
@ -90,8 +90,8 @@ export const InfraJobStatusEnum = {
|
||||||
export const InfraApiErrorLogProcessStatusEnum = {
|
export const InfraApiErrorLogProcessStatusEnum = {
|
||||||
INIT: 0, // 未处理
|
INIT: 0, // 未处理
|
||||||
DONE: 1, // 已处理
|
DONE: 1, // 已处理
|
||||||
IGNORE: 2 // 已忽略
|
IGNORE: 2, // 已忽略
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== PAY 模块 ==========
|
// ========== PAY 模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -100,78 +100,78 @@ export const InfraApiErrorLogProcessStatusEnum = {
|
||||||
export const PayChannelEnum = {
|
export const PayChannelEnum = {
|
||||||
WX_PUB: {
|
WX_PUB: {
|
||||||
code: 'wx_pub',
|
code: 'wx_pub',
|
||||||
name: '微信 JSAPI 支付'
|
name: '微信 JSAPI 支付',
|
||||||
},
|
},
|
||||||
WX_LITE: {
|
WX_LITE: {
|
||||||
code: 'wx_lite',
|
code: 'wx_lite',
|
||||||
name: '微信小程序支付'
|
name: '微信小程序支付',
|
||||||
},
|
},
|
||||||
WX_APP: {
|
WX_APP: {
|
||||||
code: 'wx_app',
|
code: 'wx_app',
|
||||||
name: '微信 APP 支付'
|
name: '微信 APP 支付',
|
||||||
},
|
},
|
||||||
WX_NATIVE: {
|
WX_NATIVE: {
|
||||||
code: 'wx_native',
|
code: 'wx_native',
|
||||||
name: '微信 Native 支付'
|
name: '微信 Native 支付',
|
||||||
},
|
},
|
||||||
WX_WAP: {
|
WX_WAP: {
|
||||||
code: 'wx_wap',
|
code: 'wx_wap',
|
||||||
name: '微信 WAP 网站支付'
|
name: '微信 WAP 网站支付',
|
||||||
},
|
},
|
||||||
WX_BAR: {
|
WX_BAR: {
|
||||||
code: 'wx_bar',
|
code: 'wx_bar',
|
||||||
name: '微信条码支付'
|
name: '微信条码支付',
|
||||||
},
|
},
|
||||||
ALIPAY_PC: {
|
ALIPAY_PC: {
|
||||||
code: 'alipay_pc',
|
code: 'alipay_pc',
|
||||||
name: '支付宝 PC 网站支付'
|
name: '支付宝 PC 网站支付',
|
||||||
},
|
},
|
||||||
ALIPAY_WAP: {
|
ALIPAY_WAP: {
|
||||||
code: 'alipay_wap',
|
code: 'alipay_wap',
|
||||||
name: '支付宝 WAP 网站支付'
|
name: '支付宝 WAP 网站支付',
|
||||||
},
|
},
|
||||||
ALIPAY_APP: {
|
ALIPAY_APP: {
|
||||||
code: 'alipay_app',
|
code: 'alipay_app',
|
||||||
name: '支付宝 APP 支付'
|
name: '支付宝 APP 支付',
|
||||||
},
|
},
|
||||||
ALIPAY_QR: {
|
ALIPAY_QR: {
|
||||||
code: 'alipay_qr',
|
code: 'alipay_qr',
|
||||||
name: '支付宝扫码支付'
|
name: '支付宝扫码支付',
|
||||||
},
|
},
|
||||||
ALIPAY_BAR: {
|
ALIPAY_BAR: {
|
||||||
code: 'alipay_bar',
|
code: 'alipay_bar',
|
||||||
name: '支付宝条码支付'
|
name: '支付宝条码支付',
|
||||||
},
|
},
|
||||||
WALLET: {
|
WALLET: {
|
||||||
code: 'wallet',
|
code: 'wallet',
|
||||||
name: '钱包支付'
|
name: '钱包支付',
|
||||||
},
|
},
|
||||||
MOCK: {
|
MOCK: {
|
||||||
code: 'mock',
|
code: 'mock',
|
||||||
name: '模拟支付'
|
name: '模拟支付',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付的展示模式每局
|
* 支付的展示模式每局
|
||||||
*/
|
*/
|
||||||
export const PayDisplayModeEnum = {
|
export const PayDisplayModeEnum = {
|
||||||
URL: {
|
URL: {
|
||||||
mode: 'url'
|
mode: 'url',
|
||||||
},
|
},
|
||||||
IFRAME: {
|
IFRAME: {
|
||||||
mode: 'iframe'
|
mode: 'iframe',
|
||||||
},
|
},
|
||||||
FORM: {
|
FORM: {
|
||||||
mode: 'form'
|
mode: 'form',
|
||||||
},
|
},
|
||||||
QR_CODE: {
|
QR_CODE: {
|
||||||
mode: 'qr_code'
|
mode: 'qr_code',
|
||||||
},
|
},
|
||||||
APP: {
|
APP: {
|
||||||
mode: 'app'
|
mode: 'app',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付类型枚举
|
* 支付类型枚举
|
||||||
|
|
@ -179,8 +179,8 @@ export const PayDisplayModeEnum = {
|
||||||
export const PayType = {
|
export const PayType = {
|
||||||
WECHAT: 'WECHAT',
|
WECHAT: 'WECHAT',
|
||||||
ALIPAY: 'ALIPAY',
|
ALIPAY: 'ALIPAY',
|
||||||
MOCK: 'MOCK'
|
MOCK: 'MOCK',
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付订单状态枚举
|
* 支付订单状态枚举
|
||||||
|
|
@ -188,17 +188,17 @@ export const PayType = {
|
||||||
export const PayOrderStatusEnum = {
|
export const PayOrderStatusEnum = {
|
||||||
WAITING: {
|
WAITING: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '未支付'
|
name: '未支付',
|
||||||
},
|
},
|
||||||
SUCCESS: {
|
SUCCESS: {
|
||||||
status: 10,
|
status: 10,
|
||||||
name: '已支付'
|
name: '已支付',
|
||||||
},
|
},
|
||||||
CLOSED: {
|
CLOSED: {
|
||||||
status: 20,
|
status: 20,
|
||||||
name: '未支付'
|
name: '未支付',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== MALL - 商品模块 ==========
|
// ========== MALL - 商品模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -207,17 +207,17 @@ export const PayOrderStatusEnum = {
|
||||||
export const ProductSpuStatusEnum = {
|
export const ProductSpuStatusEnum = {
|
||||||
RECYCLE: {
|
RECYCLE: {
|
||||||
status: -1,
|
status: -1,
|
||||||
name: '回收站'
|
name: '回收站',
|
||||||
},
|
},
|
||||||
DISABLE: {
|
DISABLE: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '下架'
|
name: '下架',
|
||||||
},
|
},
|
||||||
ENABLE: {
|
ENABLE: {
|
||||||
status: 1,
|
status: 1,
|
||||||
name: '上架'
|
name: '上架',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== MALL - 营销模块 ==========
|
// ========== MALL - 营销模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -226,13 +226,13 @@ export const ProductSpuStatusEnum = {
|
||||||
export const CouponTemplateValidityTypeEnum = {
|
export const CouponTemplateValidityTypeEnum = {
|
||||||
DATE: {
|
DATE: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '固定日期可用'
|
name: '固定日期可用',
|
||||||
},
|
},
|
||||||
TERM: {
|
TERM: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '领取之后可用'
|
name: '领取之后可用',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠劵模板的领取方式的枚举
|
* 优惠劵模板的领取方式的枚举
|
||||||
|
|
@ -240,17 +240,17 @@ export const CouponTemplateValidityTypeEnum = {
|
||||||
export const CouponTemplateTakeTypeEnum = {
|
export const CouponTemplateTakeTypeEnum = {
|
||||||
USER: {
|
USER: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '直接领取'
|
name: '直接领取',
|
||||||
},
|
},
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '指定发放'
|
name: '指定发放',
|
||||||
},
|
},
|
||||||
REGISTER: {
|
REGISTER: {
|
||||||
type: 3,
|
type: 3,
|
||||||
name: '新人券'
|
name: '新人券',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 营销的商品范围枚举
|
* 营销的商品范围枚举
|
||||||
|
|
@ -258,17 +258,17 @@ export const CouponTemplateTakeTypeEnum = {
|
||||||
export const PromotionProductScopeEnum = {
|
export const PromotionProductScopeEnum = {
|
||||||
ALL: {
|
ALL: {
|
||||||
scope: 1,
|
scope: 1,
|
||||||
name: '通用劵'
|
name: '通用劵',
|
||||||
},
|
},
|
||||||
SPU: {
|
SPU: {
|
||||||
scope: 2,
|
scope: 2,
|
||||||
name: '商品劵'
|
name: '商品劵',
|
||||||
},
|
},
|
||||||
CATEGORY: {
|
CATEGORY: {
|
||||||
scope: 3,
|
scope: 3,
|
||||||
name: '品类劵'
|
name: '品类劵',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 营销的条件类型枚举
|
* 营销的条件类型枚举
|
||||||
|
|
@ -276,13 +276,13 @@ export const PromotionProductScopeEnum = {
|
||||||
export const PromotionConditionTypeEnum = {
|
export const PromotionConditionTypeEnum = {
|
||||||
PRICE: {
|
PRICE: {
|
||||||
type: 10,
|
type: 10,
|
||||||
name: '满 N 元'
|
name: '满 N 元',
|
||||||
},
|
},
|
||||||
COUNT: {
|
COUNT: {
|
||||||
type: 20,
|
type: 20,
|
||||||
name: '满 N 件'
|
name: '满 N 件',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠类型枚举
|
* 优惠类型枚举
|
||||||
|
|
@ -290,13 +290,13 @@ export const PromotionConditionTypeEnum = {
|
||||||
export const PromotionDiscountTypeEnum = {
|
export const PromotionDiscountTypeEnum = {
|
||||||
PRICE: {
|
PRICE: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '满减'
|
name: '满减',
|
||||||
},
|
},
|
||||||
PERCENT: {
|
PERCENT: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '折扣'
|
name: '折扣',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== MALL - 交易模块 ==========
|
// ========== MALL - 交易模块 ==========
|
||||||
/**
|
/**
|
||||||
|
|
@ -305,89 +305,89 @@ export const PromotionDiscountTypeEnum = {
|
||||||
export const BrokerageBindModeEnum = {
|
export const BrokerageBindModeEnum = {
|
||||||
ANYTIME: {
|
ANYTIME: {
|
||||||
mode: 1,
|
mode: 1,
|
||||||
name: '首次绑定'
|
name: '首次绑定',
|
||||||
},
|
},
|
||||||
REGISTER: {
|
REGISTER: {
|
||||||
mode: 2,
|
mode: 2,
|
||||||
name: '注册绑定'
|
name: '注册绑定',
|
||||||
},
|
},
|
||||||
OVERRIDE: {
|
OVERRIDE: {
|
||||||
mode: 3,
|
mode: 3,
|
||||||
name: '覆盖绑定'
|
name: '覆盖绑定',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 分佣模式枚举
|
* 分佣模式枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageEnabledConditionEnum = {
|
export const BrokerageEnabledConditionEnum = {
|
||||||
ALL: {
|
ALL: {
|
||||||
condition: 1,
|
condition: 1,
|
||||||
name: '人人分销'
|
name: '人人分销',
|
||||||
},
|
},
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
condition: 2,
|
condition: 2,
|
||||||
name: '指定分销'
|
name: '指定分销',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 佣金记录业务类型枚举
|
* 佣金记录业务类型枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageRecordBizTypeEnum = {
|
export const BrokerageRecordBizTypeEnum = {
|
||||||
ORDER: {
|
ORDER: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '获得推广佣金'
|
name: '获得推广佣金',
|
||||||
},
|
},
|
||||||
WITHDRAW: {
|
WITHDRAW: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '提现申请'
|
name: '提现申请',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 佣金提现状态枚举
|
* 佣金提现状态枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageWithdrawStatusEnum = {
|
export const BrokerageWithdrawStatusEnum = {
|
||||||
AUDITING: {
|
AUDITING: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '审核中'
|
name: '审核中',
|
||||||
},
|
},
|
||||||
AUDIT_SUCCESS: {
|
AUDIT_SUCCESS: {
|
||||||
status: 10,
|
status: 10,
|
||||||
name: '审核通过'
|
name: '审核通过',
|
||||||
},
|
},
|
||||||
AUDIT_FAIL: {
|
AUDIT_FAIL: {
|
||||||
status: 20,
|
status: 20,
|
||||||
name: '审核不通过'
|
name: '审核不通过',
|
||||||
},
|
},
|
||||||
WITHDRAW_SUCCESS: {
|
WITHDRAW_SUCCESS: {
|
||||||
status: 11,
|
status: 11,
|
||||||
name: '提现成功'
|
name: '提现成功',
|
||||||
},
|
},
|
||||||
WITHDRAW_FAIL: {
|
WITHDRAW_FAIL: {
|
||||||
status: 21,
|
status: 21,
|
||||||
name: '提现失败'
|
name: '提现失败',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 佣金提现类型枚举
|
* 佣金提现类型枚举
|
||||||
*/
|
*/
|
||||||
export const BrokerageWithdrawTypeEnum = {
|
export const BrokerageWithdrawTypeEnum = {
|
||||||
WALLET: {
|
WALLET: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '钱包'
|
name: '钱包',
|
||||||
},
|
},
|
||||||
BANK: {
|
BANK: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '银行卡'
|
name: '银行卡',
|
||||||
},
|
},
|
||||||
WECHAT: {
|
WECHAT: {
|
||||||
type: 3,
|
type: 3,
|
||||||
name: '微信'
|
name: '微信',
|
||||||
},
|
},
|
||||||
ALIPAY: {
|
ALIPAY: {
|
||||||
type: 4,
|
type: 4,
|
||||||
name: '支付宝'
|
name: '支付宝',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配送方式枚举
|
* 配送方式枚举
|
||||||
|
|
@ -395,38 +395,38 @@ export const BrokerageWithdrawTypeEnum = {
|
||||||
export const DeliveryTypeEnum = {
|
export const DeliveryTypeEnum = {
|
||||||
EXPRESS: {
|
EXPRESS: {
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '快递发货'
|
name: '快递发货',
|
||||||
},
|
},
|
||||||
PICK_UP: {
|
PICK_UP: {
|
||||||
type: 2,
|
type: 2,
|
||||||
name: '到店自提'
|
name: '到店自提',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* 交易订单 - 状态
|
* 交易订单 - 状态
|
||||||
*/
|
*/
|
||||||
export const TradeOrderStatusEnum = {
|
export const TradeOrderStatusEnum = {
|
||||||
UNPAID: {
|
UNPAID: {
|
||||||
status: 0,
|
status: 0,
|
||||||
name: '待支付'
|
name: '待支付',
|
||||||
},
|
},
|
||||||
UNDELIVERED: {
|
UNDELIVERED: {
|
||||||
status: 10,
|
status: 10,
|
||||||
name: '待发货'
|
name: '待发货',
|
||||||
},
|
},
|
||||||
DELIVERED: {
|
DELIVERED: {
|
||||||
status: 20,
|
status: 20,
|
||||||
name: '已发货'
|
name: '已发货',
|
||||||
},
|
},
|
||||||
COMPLETED: {
|
COMPLETED: {
|
||||||
status: 30,
|
status: 30,
|
||||||
name: '已完成'
|
name: '已完成',
|
||||||
},
|
},
|
||||||
CANCELED: {
|
CANCELED: {
|
||||||
status: 40,
|
status: 40,
|
||||||
name: '已取消'
|
name: '已取消',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== ERP - 企业资源计划 ==========
|
// ========== ERP - 企业资源计划 ==========
|
||||||
|
|
||||||
|
|
@ -436,31 +436,31 @@ export const ErpBizType = {
|
||||||
PURCHASE_RETURN: 12,
|
PURCHASE_RETURN: 12,
|
||||||
SALE_ORDER: 20,
|
SALE_ORDER: 20,
|
||||||
SALE_OUT: 21,
|
SALE_OUT: 21,
|
||||||
SALE_RETURN: 22
|
SALE_RETURN: 22,
|
||||||
}
|
};
|
||||||
|
|
||||||
// ========== BPM 模块 ==========
|
// ========== BPM 模块 ==========
|
||||||
|
|
||||||
export const BpmModelType = {
|
export const BpmModelType = {
|
||||||
BPMN: 10, // BPMN 设计器
|
BPMN: 10, // BPMN 设计器
|
||||||
SIMPLE: 20 // 简易设计器
|
SIMPLE: 20, // 简易设计器
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BpmModelFormType = {
|
export const BpmModelFormType = {
|
||||||
NORMAL: 10, // 流程表单
|
NORMAL: 10, // 流程表单
|
||||||
CUSTOM: 20 // 业务表单
|
CUSTOM: 20, // 业务表单
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BpmProcessInstanceStatus = {
|
export const BpmProcessInstanceStatus = {
|
||||||
NOT_START: -1, // 未开始
|
NOT_START: -1, // 未开始
|
||||||
RUNNING: 1, // 审批中
|
RUNNING: 1, // 审批中
|
||||||
APPROVE: 2, // 审批通过
|
APPROVE: 2, // 审批通过
|
||||||
REJECT: 3, // 审批不通过
|
REJECT: 3, // 审批不通过
|
||||||
CANCEL: 4 // 已取消
|
CANCEL: 4, // 已取消
|
||||||
}
|
};
|
||||||
|
|
||||||
export const BpmAutoApproveType = {
|
export const BpmAutoApproveType = {
|
||||||
NONE: 0, // 不自动通过
|
NONE: 0, // 不自动通过
|
||||||
APPROVE_ALL: 1, // 仅审批一次,后续重复的审批节点均自动通过
|
APPROVE_ALL: 1, // 仅审批一次,后续重复的审批节点均自动通过
|
||||||
APPROVE_SEQUENT: 2, // 仅针对连续审批的节点自动通过
|
APPROVE_SEQUENT: 2, // 仅针对连续审批的节点自动通过
|
||||||
}
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,36 +2,24 @@ import dayjs from 'dayjs';
|
||||||
|
|
||||||
// TODO @芋艿:后续整理下
|
// TODO @芋艿:后续整理下
|
||||||
|
|
||||||
// TODO @puhui999:转成 function 方式哈
|
|
||||||
/** 时间段选择器拓展 */
|
/** 时间段选择器拓展 */
|
||||||
export const getRangePickerDefaultProps = () => {
|
export function getRangePickerDefaultProps() {
|
||||||
return {
|
return {
|
||||||
showTime: {
|
showTime: {
|
||||||
format: 'HH:mm:ss',
|
format: 'HH:mm:ss',
|
||||||
defaultValue: [
|
defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')],
|
||||||
dayjs('00:00:00', 'HH:mm:ss'),
|
|
||||||
dayjs('23:59:59', 'HH:mm:ss'),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
format: 'YYYY-MM-DD HH:mm:ss',
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
placeholder: ['开始时间', '结束时间'],
|
placeholder: ['开始时间', '结束时间'],
|
||||||
|
// prettier-ignore
|
||||||
ranges: {
|
ranges: {
|
||||||
'今天': [dayjs().startOf('day'), dayjs().endOf('day')],
|
'今天': [dayjs().startOf('day'), dayjs().endOf('day')],
|
||||||
'昨天': [
|
'昨天': [dayjs().subtract(1, 'day').startOf('day'), dayjs().subtract(1, 'day').endOf('day')],
|
||||||
dayjs().subtract(1, 'day').startOf('day'),
|
|
||||||
dayjs().subtract(1, 'day').endOf('day'),
|
|
||||||
],
|
|
||||||
'本周': [dayjs().startOf('week'), dayjs().endOf('day')],
|
'本周': [dayjs().startOf('week'), dayjs().endOf('day')],
|
||||||
'本月': [dayjs().startOf('month'), dayjs().endOf('day')],
|
'本月': [dayjs().startOf('month'), dayjs().endOf('day')],
|
||||||
'最近 7 天': [
|
'最近 7 天': [dayjs().subtract(7, 'day').startOf('day'), dayjs().endOf('day')],
|
||||||
dayjs().subtract(7, 'day').startOf('day'),
|
'最近 30 天': [dayjs().subtract(30, 'day').startOf('day'), dayjs().endOf('day')],
|
||||||
dayjs().endOf('day'),
|
|
||||||
],
|
|
||||||
'最近 30 天': [
|
|
||||||
dayjs().subtract(30, 'day').startOf('day'),
|
|
||||||
dayjs().endOf('day'),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
transformDateFunc: (dates: any) => {
|
transformDateFunc: (dates: any) => {
|
||||||
if (dates && dates.length === 2) {
|
if (dates && dates.length === 2) {
|
||||||
|
|
@ -40,4 +28,4 @@ export const getRangePickerDefaultProps = () => {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const dictStore = useDictStore();
|
||||||
*/
|
*/
|
||||||
function getDictLabel(dictType: string, value: any) {
|
function getDictLabel(dictType: string, value: any) {
|
||||||
const dictObj = dictStore.getDictData(dictType, value);
|
const dictObj = dictStore.getDictData(dictType, value);
|
||||||
return isObject(dictObj)? dictObj.label : '';
|
return isObject(dictObj) ? dictObj.label : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -38,10 +38,7 @@ function getDictObj(dictType: string, value: any) {
|
||||||
* @param dictType 字典类型
|
* @param dictType 字典类型
|
||||||
* @returns 字典数组
|
* @returns 字典数组
|
||||||
*/
|
*/
|
||||||
function getDictOptions(
|
function getDictOptions(dictType: string, valueType: 'boolean' | 'number' | 'string' = 'string') {
|
||||||
dictType: string,
|
|
||||||
valueType: 'boolean' | 'number' | 'string' = 'string',
|
|
||||||
) {
|
|
||||||
const dictOpts = dictStore.getDictOptions(dictType);
|
const dictOpts = dictStore.getDictOptions(dictType);
|
||||||
const dictOptions: DefaultOptionType = [];
|
const dictOptions: DefaultOptionType = [];
|
||||||
if (dictOpts.length > 0) {
|
if (dictOpts.length > 0) {
|
||||||
|
|
@ -72,137 +69,138 @@ function getDictOptions(
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DICT_TYPE {
|
enum DICT_TYPE {
|
||||||
AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式
|
USER_TYPE = 'user_type',
|
||||||
AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态
|
COMMON_STATUS = 'common_status',
|
||||||
AI_MUSIC_STATUS = 'ai_music_status', // AI 音乐状态
|
TERMINAL = 'terminal', // 终端
|
||||||
// ========== AI - 人工智能模块 ==========
|
DATE_INTERVAL = 'date_interval', // 数据间隔
|
||||||
AI_PLATFORM = 'ai_platform', // AI 平台
|
|
||||||
|
// ========== SYSTEM 模块 ==========
|
||||||
|
SYSTEM_USER_SEX = 'system_user_sex',
|
||||||
|
SYSTEM_MENU_TYPE = 'system_menu_type',
|
||||||
|
SYSTEM_ROLE_TYPE = 'system_role_type',
|
||||||
|
SYSTEM_DATA_SCOPE = 'system_data_scope',
|
||||||
|
SYSTEM_NOTICE_TYPE = 'system_notice_type',
|
||||||
|
SYSTEM_LOGIN_TYPE = 'system_login_type',
|
||||||
|
SYSTEM_LOGIN_RESULT = 'system_login_result',
|
||||||
|
SYSTEM_SMS_CHANNEL_CODE = 'system_sms_channel_code',
|
||||||
|
SYSTEM_SMS_TEMPLATE_TYPE = 'system_sms_template_type',
|
||||||
|
SYSTEM_SMS_SEND_STATUS = 'system_sms_send_status',
|
||||||
|
SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status',
|
||||||
|
SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type',
|
||||||
|
SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status',
|
||||||
|
SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type',
|
||||||
|
SYSTEM_SOCIAL_TYPE = 'system_social_type',
|
||||||
|
|
||||||
|
// ========== INFRA 模块 ==========
|
||||||
|
INFRA_BOOLEAN_STRING = 'infra_boolean_string',
|
||||||
|
INFRA_JOB_STATUS = 'infra_job_status',
|
||||||
|
INFRA_JOB_LOG_STATUS = 'infra_job_log_status',
|
||||||
|
INFRA_API_ERROR_LOG_PROCESS_STATUS = 'infra_api_error_log_process_status',
|
||||||
|
INFRA_CONFIG_TYPE = 'infra_config_type',
|
||||||
|
INFRA_CODEGEN_TEMPLATE_TYPE = 'infra_codegen_template_type',
|
||||||
|
INFRA_CODEGEN_FRONT_TYPE = 'infra_codegen_front_type',
|
||||||
|
INFRA_CODEGEN_SCENE = 'infra_codegen_scene',
|
||||||
|
INFRA_FILE_STORAGE = 'infra_file_storage',
|
||||||
|
INFRA_OPERATE_TYPE = 'infra_operate_type',
|
||||||
|
|
||||||
AI_WRITE_FORMAT = 'ai_write_format', // AI 写作格式
|
|
||||||
AI_WRITE_LANGUAGE = 'ai_write_language', // AI 写作语言
|
|
||||||
AI_WRITE_LENGTH = 'ai_write_length', // AI 写作长度
|
|
||||||
AI_WRITE_TONE = 'ai_write_tone', // AI 写作语气
|
|
||||||
AI_WRITE_TYPE = 'ai_write_type', // AI 写作类型
|
|
||||||
BPM_MODEL_FORM_TYPE = 'bpm_model_form_type',
|
|
||||||
// ========== BPM 模块 ==========
|
// ========== BPM 模块 ==========
|
||||||
BPM_MODEL_TYPE = 'bpm_model_type',
|
BPM_MODEL_TYPE = 'bpm_model_type',
|
||||||
BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type',
|
BPM_MODEL_FORM_TYPE = 'bpm_model_form_type',
|
||||||
|
BPM_TASK_CANDIDATE_STRATEGY = 'bpm_task_candidate_strategy',
|
||||||
BPM_PROCESS_INSTANCE_STATUS = 'bpm_process_instance_status',
|
BPM_PROCESS_INSTANCE_STATUS = 'bpm_process_instance_status',
|
||||||
|
BPM_TASK_STATUS = 'bpm_task_status',
|
||||||
|
BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type',
|
||||||
BPM_PROCESS_LISTENER_TYPE = 'bpm_process_listener_type',
|
BPM_PROCESS_LISTENER_TYPE = 'bpm_process_listener_type',
|
||||||
BPM_PROCESS_LISTENER_VALUE_TYPE = 'bpm_process_listener_value_type',
|
BPM_PROCESS_LISTENER_VALUE_TYPE = 'bpm_process_listener_value_type',
|
||||||
BPM_TASK_CANDIDATE_STRATEGY = 'bpm_task_candidate_strategy',
|
|
||||||
BPM_TASK_STATUS = 'bpm_task_status',
|
|
||||||
BROKERAGE_BANK_NAME = 'brokerage_bank_name', // 佣金提现银行
|
|
||||||
BROKERAGE_BIND_MODE = 'brokerage_bind_mode', // 分销关系绑定模式
|
|
||||||
|
|
||||||
|
// ========== PAY 模块 ==========
|
||||||
|
PAY_CHANNEL_CODE = 'pay_channel_code', // 支付渠道编码类型
|
||||||
|
PAY_ORDER_STATUS = 'pay_order_status', // 商户支付订单状态
|
||||||
|
PAY_REFUND_STATUS = 'pay_refund_status', // 退款订单状态
|
||||||
|
PAY_NOTIFY_STATUS = 'pay_notify_status', // 商户支付回调状态
|
||||||
|
PAY_NOTIFY_TYPE = 'pay_notify_type', // 商户支付回调状态
|
||||||
|
PAY_TRANSFER_STATUS = 'pay_transfer_status', // 转账订单状态
|
||||||
|
PAY_TRANSFER_TYPE = 'pay_transfer_type', // 转账订单状态
|
||||||
|
|
||||||
|
// ========== MP 模块 ==========
|
||||||
|
MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型
|
||||||
|
MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型
|
||||||
|
|
||||||
|
// ========== Member 会员模块 ==========
|
||||||
|
MEMBER_POINT_BIZ_TYPE = 'member_point_biz_type', // 积分的业务类型
|
||||||
|
MEMBER_EXPERIENCE_BIZ_TYPE = 'member_experience_biz_type', // 会员经验业务类型
|
||||||
|
|
||||||
|
// ========== MALL - 商品模块 ==========
|
||||||
|
PRODUCT_SPU_STATUS = 'product_spu_status', //商品状态
|
||||||
|
|
||||||
|
// ========== MALL - 交易模块 ==========
|
||||||
|
EXPRESS_CHARGE_MODE = 'trade_delivery_express_charge_mode', //快递的计费方式
|
||||||
|
TRADE_AFTER_SALE_STATUS = 'trade_after_sale_status', // 售后 - 状态
|
||||||
|
TRADE_AFTER_SALE_WAY = 'trade_after_sale_way', // 售后 - 方式
|
||||||
|
TRADE_AFTER_SALE_TYPE = 'trade_after_sale_type', // 售后 - 类型
|
||||||
|
TRADE_ORDER_TYPE = 'trade_order_type', // 订单 - 类型
|
||||||
|
TRADE_ORDER_STATUS = 'trade_order_status', // 订单 - 状态
|
||||||
|
TRADE_ORDER_ITEM_AFTER_SALE_STATUS = 'trade_order_item_after_sale_status', // 订单项 - 售后状态
|
||||||
|
TRADE_DELIVERY_TYPE = 'trade_delivery_type', // 配送方式
|
||||||
BROKERAGE_ENABLED_CONDITION = 'brokerage_enabled_condition', // 分佣模式
|
BROKERAGE_ENABLED_CONDITION = 'brokerage_enabled_condition', // 分佣模式
|
||||||
|
BROKERAGE_BIND_MODE = 'brokerage_bind_mode', // 分销关系绑定模式
|
||||||
|
BROKERAGE_BANK_NAME = 'brokerage_bank_name', // 佣金提现银行
|
||||||
|
BROKERAGE_WITHDRAW_TYPE = 'brokerage_withdraw_type', // 佣金提现类型
|
||||||
BROKERAGE_RECORD_BIZ_TYPE = 'brokerage_record_biz_type', // 佣金业务类型
|
BROKERAGE_RECORD_BIZ_TYPE = 'brokerage_record_biz_type', // 佣金业务类型
|
||||||
BROKERAGE_RECORD_STATUS = 'brokerage_record_status', // 佣金状态
|
BROKERAGE_RECORD_STATUS = 'brokerage_record_status', // 佣金状态
|
||||||
BROKERAGE_WITHDRAW_STATUS = 'brokerage_withdraw_status', // 佣金提现状态
|
BROKERAGE_WITHDRAW_STATUS = 'brokerage_withdraw_status', // 佣金提现状态
|
||||||
BROKERAGE_WITHDRAW_TYPE = 'brokerage_withdraw_type', // 佣金提现类型
|
|
||||||
COMMON_STATUS = 'common_status',
|
// ========== MALL - 营销模块 ==========
|
||||||
|
PROMOTION_DISCOUNT_TYPE = 'promotion_discount_type', // 优惠类型
|
||||||
|
PROMOTION_PRODUCT_SCOPE = 'promotion_product_scope', // 营销的商品范围
|
||||||
|
PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE = 'promotion_coupon_template_validity_type', // 优惠劵模板的有限期类型
|
||||||
|
PROMOTION_COUPON_STATUS = 'promotion_coupon_status', // 优惠劵的状态
|
||||||
|
PROMOTION_COUPON_TAKE_TYPE = 'promotion_coupon_take_type', // 优惠劵的领取方式
|
||||||
|
PROMOTION_CONDITION_TYPE = 'promotion_condition_type', // 营销的条件类型枚举
|
||||||
|
PROMOTION_BARGAIN_RECORD_STATUS = 'promotion_bargain_record_status', // 砍价记录的状态
|
||||||
|
PROMOTION_COMBINATION_RECORD_STATUS = 'promotion_combination_record_status', // 拼团记录的状态
|
||||||
|
PROMOTION_BANNER_POSITION = 'promotion_banner_position', // banner 定位
|
||||||
|
|
||||||
// ========== CRM - 客户管理模块 ==========
|
// ========== CRM - 客户管理模块 ==========
|
||||||
CRM_AUDIT_STATUS = 'crm_audit_status', // CRM 审批状态
|
CRM_AUDIT_STATUS = 'crm_audit_status', // CRM 审批状态
|
||||||
CRM_BIZ_TYPE = 'crm_biz_type', // CRM 业务类型
|
CRM_BIZ_TYPE = 'crm_biz_type', // CRM 业务类型
|
||||||
CRM_BUSINESS_END_STATUS_TYPE = 'crm_business_end_status_type', // CRM 商机结束状态类型
|
CRM_BUSINESS_END_STATUS_TYPE = 'crm_business_end_status_type', // CRM 商机结束状态类型
|
||||||
|
CRM_RECEIVABLE_RETURN_TYPE = 'crm_receivable_return_type', // CRM 回款的还款方式
|
||||||
CRM_CUSTOMER_INDUSTRY = 'crm_customer_industry', // CRM 客户所属行业
|
CRM_CUSTOMER_INDUSTRY = 'crm_customer_industry', // CRM 客户所属行业
|
||||||
|
|
||||||
CRM_CUSTOMER_LEVEL = 'crm_customer_level', // CRM 客户级别
|
CRM_CUSTOMER_LEVEL = 'crm_customer_level', // CRM 客户级别
|
||||||
CRM_CUSTOMER_SOURCE = 'crm_customer_source', // CRM 客户来源
|
CRM_CUSTOMER_SOURCE = 'crm_customer_source', // CRM 客户来源
|
||||||
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // CRM 跟进方式
|
|
||||||
CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别
|
|
||||||
CRM_PRODUCT_STATUS = 'crm_product_status', // CRM 商品状态
|
CRM_PRODUCT_STATUS = 'crm_product_status', // CRM 商品状态
|
||||||
|
CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别
|
||||||
CRM_PRODUCT_UNIT = 'crm_product_unit', // CRM 产品单位
|
CRM_PRODUCT_UNIT = 'crm_product_unit', // CRM 产品单位
|
||||||
CRM_RECEIVABLE_RETURN_TYPE = 'crm_receivable_return_type', // CRM 回款的还款方式
|
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // CRM 跟进方式
|
||||||
DATE_INTERVAL = 'date_interval', // 数据间隔
|
|
||||||
|
|
||||||
// ========== ERP - 企业资源计划模块 ==========
|
// ========== ERP - 企业资源计划模块 ==========
|
||||||
ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态
|
ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态
|
||||||
ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型
|
ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型
|
||||||
// ========== MALL - 交易模块 ==========
|
|
||||||
EXPRESS_CHARGE_MODE = 'trade_delivery_express_charge_mode', // 快递的计费方式
|
|
||||||
INFRA_API_ERROR_LOG_PROCESS_STATUS = 'infra_api_error_log_process_status',
|
|
||||||
// ========== INFRA 模块 ==========
|
|
||||||
INFRA_BOOLEAN_STRING = 'infra_boolean_string',
|
|
||||||
INFRA_CODEGEN_FRONT_TYPE = 'infra_codegen_front_type',
|
|
||||||
INFRA_CODEGEN_SCENE = 'infra_codegen_scene',
|
|
||||||
|
|
||||||
INFRA_CODEGEN_TEMPLATE_TYPE = 'infra_codegen_template_type',
|
// ========== AI - 人工智能模块 ==========
|
||||||
INFRA_CONFIG_TYPE = 'infra_config_type',
|
AI_PLATFORM = 'ai_platform', // AI 平台
|
||||||
|
AI_MODEL_TYPE = 'ai_model_type', // AI 模型类型
|
||||||
|
AI_IMAGE_STATUS = 'ai_image_status', // AI 图片状态
|
||||||
|
AI_MUSIC_STATUS = 'ai_music_status', // AI 音乐状态
|
||||||
|
AI_GENERATE_MODE = 'ai_generate_mode', // AI 生成模式
|
||||||
|
AI_WRITE_TYPE = 'ai_write_type', // AI 写作类型
|
||||||
|
AI_WRITE_LENGTH = 'ai_write_length', // AI 写作长度
|
||||||
|
AI_WRITE_FORMAT = 'ai_write_format', // AI 写作格式
|
||||||
|
AI_WRITE_TONE = 'ai_write_tone', // AI 写作语气
|
||||||
|
AI_WRITE_LANGUAGE = 'ai_write_language', // AI 写作语言
|
||||||
|
|
||||||
INFRA_FILE_STORAGE = 'infra_file_storage',
|
|
||||||
INFRA_JOB_LOG_STATUS = 'infra_job_log_status',
|
|
||||||
|
|
||||||
INFRA_JOB_STATUS = 'infra_job_status',
|
|
||||||
|
|
||||||
INFRA_OPERATE_TYPE = 'infra_operate_type',
|
|
||||||
IOT_DATA_FORMAT = 'iot_data_format', // IOT 数据格式
|
|
||||||
IOT_DATA_TYPE = 'iot_data_type', // IOT 数据类型
|
|
||||||
IOT_DEVICE_STATUS = 'iot_device_status', // IOT 设备状态
|
|
||||||
// ========== IOT - 物联网模块 ==========
|
// ========== IOT - 物联网模块 ==========
|
||||||
IOT_NET_TYPE = 'iot_net_type', // IOT 联网方式
|
IOT_NET_TYPE = 'iot_net_type', // IOT 联网方式
|
||||||
IOT_PRODUCT_DEVICE_TYPE = 'iot_product_device_type', // IOT 产品设备类型
|
|
||||||
IOT_PRODUCT_FUNCTION_TYPE = 'iot_product_function_type', // IOT 产品功能类型
|
|
||||||
IOT_PRODUCT_STATUS = 'iot_product_status', // IOT 产品状态
|
|
||||||
IOT_PROTOCOL_TYPE = 'iot_protocol_type', // IOT 接入网关协议
|
|
||||||
IOT_RW_TYPE = 'iot_rw_type', // IOT 读写类型
|
|
||||||
IOT_UNIT_TYPE = 'iot_unit_type', // IOT 单位类型
|
|
||||||
IOT_VALIDATE_TYPE = 'iot_validate_type', // IOT 数据校验级别
|
IOT_VALIDATE_TYPE = 'iot_validate_type', // IOT 数据校验级别
|
||||||
MEMBER_EXPERIENCE_BIZ_TYPE = 'member_experience_biz_type', // 会员经验业务类型
|
IOT_PRODUCT_STATUS = 'iot_product_status', // IOT 产品状态
|
||||||
// ========== Member 会员模块 ==========
|
IOT_PRODUCT_DEVICE_TYPE = 'iot_product_device_type', // IOT 产品设备类型
|
||||||
MEMBER_POINT_BIZ_TYPE = 'member_point_biz_type', // 积分的业务类型
|
IOT_DATA_FORMAT = 'iot_data_format', // IOT 数据格式
|
||||||
// ========== MP 模块 ==========
|
IOT_PROTOCOL_TYPE = 'iot_protocol_type', // IOT 接入网关协议
|
||||||
MP_AUTO_REPLY_REQUEST_MATCH = 'mp_auto_reply_request_match', // 自动回复请求匹配类型
|
IOT_DEVICE_STATUS = 'iot_device_status', // IOT 设备状态
|
||||||
|
IOT_PRODUCT_FUNCTION_TYPE = 'iot_product_function_type', // IOT 产品功能类型
|
||||||
MP_MESSAGE_TYPE = 'mp_message_type', // 消息类型
|
IOT_DATA_TYPE = 'iot_data_type', // IOT 数据类型
|
||||||
// ========== PAY 模块 ==========
|
IOT_UNIT_TYPE = 'iot_unit_type', // IOT 单位类型
|
||||||
PAY_CHANNEL_CODE = 'pay_channel_code', // 支付渠道编码类型
|
IOT_RW_TYPE = 'iot_rw_type', // IOT 读写类型
|
||||||
PAY_NOTIFY_STATUS = 'pay_notify_status', // 商户支付回调状态
|
|
||||||
PAY_NOTIFY_TYPE = 'pay_notify_type', // 商户支付回调状态
|
|
||||||
PAY_ORDER_STATUS = 'pay_order_status', // 商户支付订单状态
|
|
||||||
PAY_REFUND_STATUS = 'pay_refund_status', // 退款订单状态
|
|
||||||
PAY_TRANSFER_STATUS = 'pay_transfer_status', // 转账订单状态
|
|
||||||
PAY_TRANSFER_TYPE = 'pay_transfer_type', // 转账订单状态
|
|
||||||
// ========== MALL - 商品模块 ==========
|
|
||||||
PRODUCT_SPU_STATUS = 'product_spu_status', // 商品状态
|
|
||||||
|
|
||||||
PROMOTION_BANNER_POSITION = 'promotion_banner_position', // banner 定位
|
|
||||||
PROMOTION_BARGAIN_RECORD_STATUS = 'promotion_bargain_record_status', // 砍价记录的状态
|
|
||||||
PROMOTION_COMBINATION_RECORD_STATUS = 'promotion_combination_record_status', // 拼团记录的状态
|
|
||||||
PROMOTION_CONDITION_TYPE = 'promotion_condition_type', // 营销的条件类型枚举
|
|
||||||
PROMOTION_COUPON_STATUS = 'promotion_coupon_status', // 优惠劵的状态
|
|
||||||
PROMOTION_COUPON_TAKE_TYPE = 'promotion_coupon_take_type', // 优惠劵的领取方式
|
|
||||||
PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE = 'promotion_coupon_template_validity_type', // 优惠劵模板的有限期类型
|
|
||||||
// ========== MALL - 营销模块 ==========
|
|
||||||
PROMOTION_DISCOUNT_TYPE = 'promotion_discount_type', // 优惠类型
|
|
||||||
PROMOTION_PRODUCT_SCOPE = 'promotion_product_scope', // 营销的商品范围
|
|
||||||
SYSTEM_DATA_SCOPE = 'system_data_scope',
|
|
||||||
SYSTEM_LOGIN_RESULT = 'system_login_result',
|
|
||||||
|
|
||||||
SYSTEM_LOGIN_TYPE = 'system_login_type',
|
|
||||||
SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status',
|
|
||||||
|
|
||||||
SYSTEM_MENU_TYPE = 'system_menu_type',
|
|
||||||
SYSTEM_NOTICE_TYPE = 'system_notice_type',
|
|
||||||
SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type',
|
|
||||||
SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type',
|
|
||||||
SYSTEM_ROLE_TYPE = 'system_role_type',
|
|
||||||
SYSTEM_SMS_CHANNEL_CODE = 'system_sms_channel_code',
|
|
||||||
SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status',
|
|
||||||
SYSTEM_SMS_SEND_STATUS = 'system_sms_send_status',
|
|
||||||
SYSTEM_SMS_TEMPLATE_TYPE = 'system_sms_template_type',
|
|
||||||
|
|
||||||
SYSTEM_SOCIAL_TYPE = 'system_social_type',
|
|
||||||
// ========== SYSTEM 模块 ==========
|
|
||||||
SYSTEM_USER_SEX = 'system_user_sex',
|
|
||||||
TERMINAL = 'terminal', // 终端
|
|
||||||
TRADE_AFTER_SALE_STATUS = 'trade_after_sale_status', // 售后 - 状态
|
|
||||||
TRADE_AFTER_SALE_TYPE = 'trade_after_sale_type', // 售后 - 类型
|
|
||||||
TRADE_AFTER_SALE_WAY = 'trade_after_sale_way', // 售后 - 方式
|
|
||||||
TRADE_DELIVERY_TYPE = 'trade_delivery_type', // 配送方式
|
|
||||||
TRADE_ORDER_ITEM_AFTER_SALE_STATUS = 'trade_order_item_after_sale_status', // 订单项 - 售后状态
|
|
||||||
TRADE_ORDER_STATUS = 'trade_order_status', // 订单 - 状态
|
|
||||||
TRADE_ORDER_TYPE = 'trade_order_type', // 订单 - 类型
|
|
||||||
USER_TYPE = 'user_type',
|
|
||||||
}
|
}
|
||||||
export { DICT_TYPE, getDictObj, getDictLabel, getDictOptions };
|
export { DICT_TYPE, getDictLabel, getDictObj, getDictOptions };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,580 @@
|
||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
import type { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
||||||
|
import type { SystemMenuApi } from '#/api/system/menu';
|
||||||
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { z } from '#/adapter/form';
|
||||||
|
import { getMenuList } from '#/api/system/menu';
|
||||||
|
import { getRangePickerDefaultProps } from '#/utils/date';
|
||||||
|
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
|
||||||
|
import { handleTree } from '#/utils/tree';
|
||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
|
import { useAccess } from '@vben/access';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
|
const { hasAccessByCodes } = useAccess();
|
||||||
|
|
||||||
|
/** 导入数据库表的表单 */
|
||||||
|
export function useImportTableFormSchema(
|
||||||
|
dataSourceConfigList: InfraDataSourceConfigApi.InfraDataSourceConfig[],
|
||||||
|
): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'dataSourceConfigId',
|
||||||
|
label: '数据源',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
options: dataSourceConfigList.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.id,
|
||||||
|
})),
|
||||||
|
placeholder: '请选择数据源',
|
||||||
|
},
|
||||||
|
defaultValue: dataSourceConfigList[0]?.id,
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'name',
|
||||||
|
label: '表名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入表名称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'comment',
|
||||||
|
label: '表描述',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入表描述',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 基本信息表单的 schema */
|
||||||
|
export function useBasicInfoFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'tableName',
|
||||||
|
label: '表名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入仓库名称',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'tableComment',
|
||||||
|
label: '表描述',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'className',
|
||||||
|
label: '实体类名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
help: '默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'author',
|
||||||
|
label: '作者',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'remark',
|
||||||
|
label: '备注',
|
||||||
|
component: 'Textarea',
|
||||||
|
componentProps: {
|
||||||
|
rows: 3,
|
||||||
|
},
|
||||||
|
// 使用 Tailwind 的 col-span-2 让元素跨越两列
|
||||||
|
formItemClass: 'md:col-span-2',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 生成信息表单基础 schema */
|
||||||
|
export function useGenerationInfoBaseFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
fieldName: 'templateType',
|
||||||
|
label: '生成模板',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE, 'number'),
|
||||||
|
},
|
||||||
|
rules: z.number().min(1, { message: '生成模板不能为空' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
fieldName: 'frontType',
|
||||||
|
label: '前端类型',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_FRONT_TYPE, 'number'),
|
||||||
|
},
|
||||||
|
rules: z.number().min(1, { message: '前端类型不能为空' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
fieldName: 'scene',
|
||||||
|
label: '生成场景',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
options: getDictOptions(DICT_TYPE.INFRA_CODEGEN_SCENE, 'number'),
|
||||||
|
},
|
||||||
|
rules: z.number().min(1, { message: '生成场景不能为空' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'parentMenuId',
|
||||||
|
label: '上级菜单',
|
||||||
|
help: '分配到指定菜单下,例如 系统管理',
|
||||||
|
component: 'ApiTreeSelect',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
api: async () => {
|
||||||
|
const data = await getMenuList();
|
||||||
|
data.unshift({
|
||||||
|
id: 0,
|
||||||
|
name: '顶级菜单',
|
||||||
|
} as SystemMenuApi.SystemMenu);
|
||||||
|
return handleTree(data);
|
||||||
|
},
|
||||||
|
class: 'w-full',
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
childrenField: 'children',
|
||||||
|
placeholder: '请选择上级菜单',
|
||||||
|
filterTreeNode(input: string, node: Recordable<any>) {
|
||||||
|
if (!input || input.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const name: string = node.label ?? '';
|
||||||
|
if (!name) return false;
|
||||||
|
return name.includes(input) || $t(name).includes(input);
|
||||||
|
},
|
||||||
|
showSearch: true,
|
||||||
|
treeDefaultExpandedKeys: [0],
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
renderComponentContent() {
|
||||||
|
return {
|
||||||
|
title({ label, icon }: { icon: string; label: string }) {
|
||||||
|
const components = [];
|
||||||
|
if (!label) return '';
|
||||||
|
if (icon) {
|
||||||
|
components.push(h(IconifyIcon, { class: 'size-4', icon }));
|
||||||
|
}
|
||||||
|
components.push(h('span', { class: '' }, $t(label || '')));
|
||||||
|
return h('div', { class: 'flex items-center gap-1' }, components);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'moduleName',
|
||||||
|
label: '模块名',
|
||||||
|
help: '模块名,即一级目录,例如 system、infra、tool 等等',
|
||||||
|
rules: z.string().min(1, { message: '模块名不能为空' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'businessName',
|
||||||
|
label: '业务名',
|
||||||
|
help: '业务名,即二级目录,例如 user、permission、dict 等等',
|
||||||
|
rules: z.string().min(1, { message: '业务名不能为空' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'className',
|
||||||
|
label: '类名称',
|
||||||
|
help: '类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等',
|
||||||
|
rules: z.string().min(1, { message: '类名称不能为空' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'classComment',
|
||||||
|
label: '类描述',
|
||||||
|
help: '用作类描述,例如 用户',
|
||||||
|
rules: z.string().min(1, { message: '类描述不能为空' }),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 树表信息 schema */
|
||||||
|
export function useTreeTableFormSchema(columns: InfraCodegenApi.CodegenColumn[] = []): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
component: 'Divider',
|
||||||
|
fieldName: 'treeDivider',
|
||||||
|
label: '',
|
||||||
|
renderComponentContent: () => {
|
||||||
|
return {
|
||||||
|
default: () => ['树表信息'],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
formItemClass: 'md:col-span-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
fieldName: 'treeParentColumnId',
|
||||||
|
label: '父编号字段',
|
||||||
|
help: '树显示的父编码字段名, 如:parent_Id',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请选择',
|
||||||
|
options: columns.map((column) => ({
|
||||||
|
label: column.columnName,
|
||||||
|
value: column.id,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
fieldName: 'treeNameColumnId',
|
||||||
|
label: '名称字段',
|
||||||
|
help: '树节点显示的名称字段,一般是name',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请选择',
|
||||||
|
options: columns.map((column) => ({
|
||||||
|
label: column.columnName,
|
||||||
|
value: column.id,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 主子表信息 schema */
|
||||||
|
export function useSubTableFormSchema(
|
||||||
|
columns: InfraCodegenApi.CodegenColumn[] = [],
|
||||||
|
tables: InfraCodegenApi.CodegenTable[] = [],
|
||||||
|
): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
component: 'Divider',
|
||||||
|
fieldName: 'subDivider',
|
||||||
|
label: '',
|
||||||
|
renderComponentContent: () => {
|
||||||
|
return {
|
||||||
|
default: () => ['主子表信息'],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
formItemClass: 'md:col-span-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
fieldName: 'masterTableId',
|
||||||
|
label: '关联的主表',
|
||||||
|
help: '关联主表(父表)的表名, 如:system_user',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请选择',
|
||||||
|
options: tables.map((table) => ({
|
||||||
|
label: `${table.tableName}:${table.tableComment}`,
|
||||||
|
value: table.id,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'Select',
|
||||||
|
fieldName: 'subJoinColumnId',
|
||||||
|
label: '子表关联的字段',
|
||||||
|
help: '子表关联的字段, 如:user_id',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请选择',
|
||||||
|
options: columns.map((column) => ({
|
||||||
|
label: `${column.columnName}:${column.columnComment}`,
|
||||||
|
value: column.id,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
rules: 'selectRequired',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'RadioGroup',
|
||||||
|
fieldName: 'subJoinMany',
|
||||||
|
label: '关联关系',
|
||||||
|
help: '主表与子表的关联关系',
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请选择',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '一对多',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '一对一',
|
||||||
|
value: 'false',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的搜索表单 */
|
||||||
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'tableName',
|
||||||
|
label: '表名称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入表名称',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'tableComment',
|
||||||
|
label: '表描述',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
allowClear: true,
|
||||||
|
placeholder: '请输入表描述',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'createTime',
|
||||||
|
label: '创建时间',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的字段 */
|
||||||
|
export function useGridColumns<T = InfraCodegenApi.CodegenTable>(
|
||||||
|
onActionClick: OnActionClickFn<T>,
|
||||||
|
dataSourceConfigList: InfraDataSourceConfigApi.InfraDataSourceConfig[],
|
||||||
|
): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'dataSourceConfigId',
|
||||||
|
title: '数据源',
|
||||||
|
minWidth: 120,
|
||||||
|
formatter: ({ cellValue }) => {
|
||||||
|
const config = dataSourceConfigList.find((item) => item.id === cellValue);
|
||||||
|
return config ? config.name : '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'tableName',
|
||||||
|
title: '表名称',
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'tableComment',
|
||||||
|
title: '表描述',
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'className',
|
||||||
|
title: '实体',
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'createTime',
|
||||||
|
title: '创建时间',
|
||||||
|
minWidth: 180,
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'updateTime',
|
||||||
|
title: '更新时间',
|
||||||
|
minWidth: 180,
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'operation',
|
||||||
|
title: '操作',
|
||||||
|
width: 300,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
cellRender: {
|
||||||
|
attrs: {
|
||||||
|
nameField: 'tableName',
|
||||||
|
nameTitle: '代码生成',
|
||||||
|
onClick: onActionClick,
|
||||||
|
},
|
||||||
|
name: 'CellOperation',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
code: 'preview',
|
||||||
|
text: '预览',
|
||||||
|
show: hasAccessByCodes(['infra:codegen:preview']),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'edit',
|
||||||
|
show: hasAccessByCodes(['infra:codegen:update']),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'delete',
|
||||||
|
show: hasAccessByCodes(['infra:codegen:delete']),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'sync',
|
||||||
|
text: '同步',
|
||||||
|
show: hasAccessByCodes(['infra:codegen:update']),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: 'generate',
|
||||||
|
text: '生成代码',
|
||||||
|
show: hasAccessByCodes(['infra:codegen:download']),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 代码生成表格列定义 */
|
||||||
|
export function useCodegenColumnTableColumns(): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{ field: 'columnName', title: '字段列名', minWidth: 130 },
|
||||||
|
{
|
||||||
|
field: 'columnComment',
|
||||||
|
title: '字段描述',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'columnComment' },
|
||||||
|
},
|
||||||
|
{ field: 'dataType', title: '物理类型', minWidth: 100 },
|
||||||
|
{
|
||||||
|
field: 'javaType',
|
||||||
|
title: 'Java类型',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'javaType' },
|
||||||
|
params: {
|
||||||
|
options: [
|
||||||
|
{ label: 'Long', value: 'Long' },
|
||||||
|
{ label: 'String', value: 'String' },
|
||||||
|
{ label: 'Integer', value: 'Integer' },
|
||||||
|
{ label: 'Double', value: 'Double' },
|
||||||
|
{ label: 'BigDecimal', value: 'BigDecimal' },
|
||||||
|
{ label: 'LocalDateTime', value: 'LocalDateTime' },
|
||||||
|
{ label: 'Boolean', value: 'Boolean' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'javaField',
|
||||||
|
title: 'java属性',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'javaField' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'createOperation',
|
||||||
|
title: '插入',
|
||||||
|
width: 40,
|
||||||
|
slots: { default: 'createOperation' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'updateOperation',
|
||||||
|
title: '编辑',
|
||||||
|
width: 40,
|
||||||
|
slots: { default: 'updateOperation' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'listOperationResult',
|
||||||
|
title: '列表',
|
||||||
|
width: 40,
|
||||||
|
slots: { default: 'listOperationResult' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'listOperation',
|
||||||
|
title: '查询',
|
||||||
|
width: 40,
|
||||||
|
slots: { default: 'listOperation' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'listOperationCondition',
|
||||||
|
title: '查询方式',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'listOperationCondition' },
|
||||||
|
params: {
|
||||||
|
options: [
|
||||||
|
{ label: '=', value: '=' },
|
||||||
|
{ label: '!=', value: '!=' },
|
||||||
|
{ label: '>', value: '>' },
|
||||||
|
{ label: '>=', value: '>=' },
|
||||||
|
{ label: '<', value: '<' },
|
||||||
|
{ label: '<=', value: '<=' },
|
||||||
|
{ label: 'LIKE', value: 'LIKE' },
|
||||||
|
{ label: 'BETWEEN', value: 'BETWEEN' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'nullable',
|
||||||
|
title: '允许空',
|
||||||
|
width: 50,
|
||||||
|
slots: { default: 'nullable' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'htmlType',
|
||||||
|
title: '显示类型',
|
||||||
|
width: 120,
|
||||||
|
slots: { default: 'htmlType' },
|
||||||
|
params: {
|
||||||
|
options: [
|
||||||
|
{ label: '文本框', value: 'input' },
|
||||||
|
{ label: '文本域', value: 'textarea' },
|
||||||
|
{ label: '下拉框', value: 'select' },
|
||||||
|
{ label: '单选框', value: 'radio' },
|
||||||
|
{ label: '复选框', value: 'checkbox' },
|
||||||
|
{ label: '日期控件', value: 'datetime' },
|
||||||
|
{ label: '图片上传', value: 'imageUpload' },
|
||||||
|
{ label: '文件上传', value: 'fileUpload' },
|
||||||
|
{ label: '富文本控件', value: 'editor' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'dictType',
|
||||||
|
title: '字典类型',
|
||||||
|
width: 120,
|
||||||
|
slots: { default: 'dictType' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'example',
|
||||||
|
title: '示例',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'example' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
|
||||||
|
import BasicInfo from './modules/basic-info.vue';
|
||||||
|
import ColumnInfo from './modules/column-info.vue';
|
||||||
|
import GenerationInfo from './modules/generation-info.vue';
|
||||||
|
import { Page } from '@vben/common-ui';
|
||||||
|
import { ChevronsLeft } from '@vben/icons';
|
||||||
|
import { Button, message, Steps } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getCodegenTable, updateCodegenTable } from '#/api/infra/codegen';
|
||||||
|
import { $t } from '#/locales';
|
||||||
|
import { ref, unref } from 'vue';
|
||||||
|
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const loading = ref(false);
|
||||||
|
const currentStep = ref(0);
|
||||||
|
const formData = ref<InfraCodegenApi.CodegenDetail>({
|
||||||
|
table: {} as InfraCodegenApi.CodegenTable,
|
||||||
|
columns: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单引用
|
||||||
|
const basicInfoRef = ref<InstanceType<typeof BasicInfo>>();
|
||||||
|
const columnInfoRef = ref<InstanceType<typeof ColumnInfo>>();
|
||||||
|
const generateInfoRef = ref<InstanceType<typeof GenerationInfo>>();
|
||||||
|
|
||||||
|
// 获取详情数据
|
||||||
|
const getDetail = async () => {
|
||||||
|
const id = route.query.id as any;
|
||||||
|
if (!id) return;
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
formData.value = await getCodegenTable(id);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const submitForm = async () => {
|
||||||
|
// 表单验证
|
||||||
|
const basicInfoValid = await basicInfoRef.value?.validate();
|
||||||
|
if (!basicInfoValid) {
|
||||||
|
message.warn('保存失败,原因:基本信息表单校验失败请检查!!!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const generateInfoValid = await generateInfoRef.value?.validate();
|
||||||
|
if (!generateInfoValid) {
|
||||||
|
message.warn('保存失败,原因:生成信息表单校验失败请检查!!!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.updating'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
// 获取相关信息
|
||||||
|
const basicInfo = await basicInfoRef.value?.getValues();
|
||||||
|
const columns = columnInfoRef.value?.getData() || unref(formData).columns;
|
||||||
|
const generateInfo = await generateInfoRef.value?.getValues();
|
||||||
|
await updateCodegenTable({ table: { ...unref(formData).table, ...basicInfo, ...generateInfo }, columns });
|
||||||
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.operationSuccess'),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
close();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存失败', error);
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 返回列表
|
||||||
|
const close = () => {
|
||||||
|
router.push('/infra/codegen');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下一步
|
||||||
|
const nextStep = async () => {
|
||||||
|
currentStep.value += 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上一步
|
||||||
|
const prevStep = () => {
|
||||||
|
if (currentStep.value > 0) {
|
||||||
|
currentStep.value -= 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 步骤配置
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
title: '基本信息',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '字段信息',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '生成信息',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
getDetail();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page auto-content-height v-loading="loading">
|
||||||
|
<div class="flex h-[95%] flex-col rounded-md bg-white p-4 dark:bg-[#1f1f1f] dark:text-gray-300">
|
||||||
|
<Steps type="navigation" :current="currentStep" class="mb-8 rounded shadow-sm dark:bg-[#141414]">
|
||||||
|
<Steps.Step v-for="(step, index) in steps" :key="index" :title="step.title" />
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
<div class="flex-1 overflow-auto py-4">
|
||||||
|
<!-- 根据当前步骤显示对应的组件 -->
|
||||||
|
<BasicInfo v-show="currentStep === 0" ref="basicInfoRef" :table="formData.table" />
|
||||||
|
<ColumnInfo v-show="currentStep === 1" ref="columnInfoRef" :columns="formData.columns" />
|
||||||
|
<GenerationInfo
|
||||||
|
v-show="currentStep === 2"
|
||||||
|
ref="generateInfoRef"
|
||||||
|
:table="formData.table"
|
||||||
|
:columns="formData.columns"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 flex justify-end space-x-2">
|
||||||
|
<Button v-show="currentStep > 0" @click="prevStep">上一步</Button>
|
||||||
|
<Button v-show="currentStep < steps.length - 1" type="primary" @click="nextStep">下一步</Button>
|
||||||
|
<Button v-show="currentStep === steps.length - 1" type="primary" :loading="loading" @click="submitForm">
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button @click="close">
|
||||||
|
<ChevronsLeft class="mr-1" />
|
||||||
|
返回
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,207 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
import type { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
||||||
|
|
||||||
|
import { DocAlert } from '#/components/doc-alert';
|
||||||
|
import ImportTable from './modules/import-table.vue';
|
||||||
|
import PreviewCode from './modules/preview-code.vue';
|
||||||
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
import { Plus } from '@vben/icons';
|
||||||
|
import { Button, message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { deleteCodegenTable, downloadCodegen, getCodegenTablePage, syncCodegenFromDB } from '#/api/infra/codegen';
|
||||||
|
import { getDataSourceConfigList } from '#/api/infra/data-source-config';
|
||||||
|
import { $t } from '#/locales';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
|
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const dataSourceConfigList = ref<InfraDataSourceConfigApi.InfraDataSourceConfig[]>([]);
|
||||||
|
|
||||||
|
const [ImportModal, importModalApi] = useVbenModal({
|
||||||
|
connectedComponent: ImportTable,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [PreviewModal, previewModalApi] = useVbenModal({
|
||||||
|
connectedComponent: PreviewCode,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 刷新表格 */
|
||||||
|
function onRefresh() {
|
||||||
|
gridApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导入表格 */
|
||||||
|
function onImport() {
|
||||||
|
importModalApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 预览代码 */
|
||||||
|
function onPreview(row: InfraCodegenApi.CodegenTable) {
|
||||||
|
previewModalApi.setData(row).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 编辑表格 */
|
||||||
|
function onEdit(row: InfraCodegenApi.CodegenTable) {
|
||||||
|
router.push(`/codegen/edit?id=${row.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除代码生成配置 */
|
||||||
|
async function onDelete(row: InfraCodegenApi.CodegenTable) {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting', [row.tableName]),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteCodegenTable(row.id);
|
||||||
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.tableName]),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 同步数据库 */
|
||||||
|
async function onSync(row: InfraCodegenApi.CodegenTable) {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.updating', [row.tableName]),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await syncCodegenFromDB(row.id);
|
||||||
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.updateSuccess', [row.tableName]),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 生成代码 */
|
||||||
|
async function onGenerate(row: InfraCodegenApi.CodegenTable) {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: '正在生成代码...',
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const res = await downloadCodegen(row.id);
|
||||||
|
const blob = new Blob([res], { type: 'application/zip' });
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `codegen-${row.className}.zip`;
|
||||||
|
link.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
message.success({
|
||||||
|
content: '代码生成成功',
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表格操作按钮的回调函数 */
|
||||||
|
function onActionClick({ code, row }: OnActionClickParams<InfraCodegenApi.CodegenTable>) {
|
||||||
|
switch (code) {
|
||||||
|
case 'delete': {
|
||||||
|
onDelete(row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'edit': {
|
||||||
|
onEdit(row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'generate': {
|
||||||
|
onGenerate(row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'preview': {
|
||||||
|
onPreview(row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'sync': {
|
||||||
|
onSync(row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useGridColumns(onActionClick, dataSourceConfigList.value),
|
||||||
|
height: 'auto',
|
||||||
|
keepSource: true,
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getCodegenTablePage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: { code: 'query' },
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<InfraCodegenApi.CodegenTable>,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取数据源配置列表
|
||||||
|
async function initDataSourceConfig() {
|
||||||
|
try {
|
||||||
|
dataSourceConfigList.value = await getDataSourceConfigList();
|
||||||
|
gridApi.setState({
|
||||||
|
gridOptions: { columns: useGridColumns(onActionClick, dataSourceConfigList.value) },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据源配置失败', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
initDataSourceConfig();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Page auto-content-height>
|
||||||
|
<DocAlert title="代码生成(单表)" url="https://doc.iocoder.cn/new-feature/" />
|
||||||
|
<DocAlert title="代码生成(树表)" url="https://doc.iocoder.cn/new-feature/tree/" />
|
||||||
|
<DocAlert title="代码生成(主子表)" url="https://doc.iocoder.cn/new-feature/master-sub/" />
|
||||||
|
<DocAlert title="单元测试" url="https://doc.iocoder.cn/unit-test/" />
|
||||||
|
|
||||||
|
<ImportModal @success="onRefresh" />
|
||||||
|
<PreviewModal />
|
||||||
|
<Grid table-title="代码生成列表">
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<Button type="primary" @click="onImport" v-access:code="['infra:codegen:create']">
|
||||||
|
<Plus class="size-5" />
|
||||||
|
{{ $t('ui.actionTitle.create', ['导入']) }}
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
|
||||||
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
import { watch } from 'vue';
|
||||||
|
|
||||||
|
import { useBasicInfoFormSchema } from '../data';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
table: InfraCodegenApi.CodegenTable;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
/** 表单实例 */
|
||||||
|
const [Form, formApi] = useVbenForm({
|
||||||
|
// 配置表单布局为两列
|
||||||
|
wrapperClass: 'grid grid-cols-1 md:grid-cols-2 gap-4',
|
||||||
|
schema: useBasicInfoFormSchema(),
|
||||||
|
layout: 'horizontal',
|
||||||
|
showDefaultActions: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 动态更新表单值 */
|
||||||
|
watch(
|
||||||
|
() => props.table,
|
||||||
|
(val: any) => {
|
||||||
|
if (!val) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
formApi.setValues(val);
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 暴露出表单校验方法和表单值获取方法 */
|
||||||
|
defineExpose({
|
||||||
|
validate: async () => {
|
||||||
|
const { valid } = await formApi.validate();
|
||||||
|
return valid;
|
||||||
|
},
|
||||||
|
getValues: formApi.getValues,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<Form />
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
import type { SystemDictTypeApi } from '#/api/system/dict/type';
|
||||||
|
|
||||||
|
import { Checkbox, Input, Select } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getSimpleDictTypeList } from '#/api/system/dict/type';
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { useCodegenColumnTableColumns } from '../data';
|
||||||
|
|
||||||
|
defineOptions({ name: 'InfraCodegenColumInfoForm' });
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
columns?: InfraCodegenApi.CodegenColumn[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 表格配置
|
||||||
|
const [Grid, extendedApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
columns: useCodegenColumnTableColumns(),
|
||||||
|
border: true,
|
||||||
|
showOverflow: true,
|
||||||
|
height: 'auto',
|
||||||
|
autoResize: true,
|
||||||
|
keepSource: true,
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听外部传入的列数据
|
||||||
|
watch(
|
||||||
|
() => props.columns,
|
||||||
|
(columns) => {
|
||||||
|
if (!columns) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
extendedApi.grid?.loadData(columns);
|
||||||
|
}, 100);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 提供获取表格数据的方法供父组件调用
|
||||||
|
defineExpose({
|
||||||
|
getData: (): InfraCodegenApi.CodegenColumn[] => extendedApi.grid.getData(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 字典类型选项
|
||||||
|
const dictTypeOptions = ref<{ label: string; value: string }[]>([]);
|
||||||
|
const loadDictTypeOptions = async () => {
|
||||||
|
const dictTypes = await getSimpleDictTypeList();
|
||||||
|
dictTypeOptions.value = dictTypes.map((dict: SystemDictTypeApi.SystemDictType) => ({
|
||||||
|
label: dict.name,
|
||||||
|
value: dict.type,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
loadDictTypeOptions();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Grid>
|
||||||
|
<!-- 字段描述 -->
|
||||||
|
<template #columnComment="{ row }">
|
||||||
|
<Input v-model:value="row.columnComment" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Java类型 -->
|
||||||
|
<template #javaType="{ row, column }">
|
||||||
|
<Select v-model:value="row.javaType" style="width: 100%">
|
||||||
|
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
|
||||||
|
{{ option.label }}
|
||||||
|
</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Java属性 -->
|
||||||
|
<template #javaField="{ row }">
|
||||||
|
<Input v-model:value="row.javaField" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 插入 -->
|
||||||
|
<template #createOperation="{ row }">
|
||||||
|
<Checkbox v-model:checked="row.createOperation" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 编辑 -->
|
||||||
|
<template #updateOperation="{ row }">
|
||||||
|
<Checkbox v-model:checked="row.updateOperation" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<template #listOperationResult="{ row }">
|
||||||
|
<Checkbox v-model:checked="row.listOperationResult" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 查询 -->
|
||||||
|
<template #listOperation="{ row }">
|
||||||
|
<Checkbox v-model:checked="row.listOperation" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 查询方式 -->
|
||||||
|
<template #listOperationCondition="{ row, column }">
|
||||||
|
<Select v-model:value="row.listOperationCondition" style="width: 100%">
|
||||||
|
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
|
||||||
|
{{ option.label }}
|
||||||
|
</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 允许空 -->
|
||||||
|
<template #nullable="{ row }">
|
||||||
|
<Checkbox v-model:checked="row.nullable" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 显示类型 -->
|
||||||
|
<template #htmlType="{ row, column }">
|
||||||
|
<Select v-model:value="row.htmlType" style="width: 100%">
|
||||||
|
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
|
||||||
|
{{ option.label }}
|
||||||
|
</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 字典类型 -->
|
||||||
|
<template #dictType="{ row }">
|
||||||
|
<Select v-model:value="row.dictType" style="width: 100%" allow-clear show-search>
|
||||||
|
<Select.Option v-for="option in dictTypeOptions" :key="option.value" :value="option.value">
|
||||||
|
{{ option.label }}
|
||||||
|
</Select.Option>
|
||||||
|
</Select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 示例 -->
|
||||||
|
<template #example="{ row }">
|
||||||
|
<Input v-model:value="row.example" />
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
|
||||||
|
import { useVbenForm } from '#/adapter/form';
|
||||||
|
import { getCodegenTableList } from '#/api/infra/codegen';
|
||||||
|
import { InfraCodegenTemplateTypeEnum } from '#/utils/constants';
|
||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
|
import { useGenerationInfoBaseFormSchema, useSubTableFormSchema, useTreeTableFormSchema } from '../data';
|
||||||
|
|
||||||
|
defineOptions({ name: 'InfraCodegenGenerateInfoForm' });
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
columns?: InfraCodegenApi.CodegenColumn[];
|
||||||
|
table?: InfraCodegenApi.CodegenTable;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const tables = ref<InfraCodegenApi.CodegenTable[]>([]);
|
||||||
|
const currentTemplateType = ref<number>();
|
||||||
|
const wrapperClass = 'grid grid-cols-1 md:grid-cols-2 gap-4 mb-4'; // 一行两列布局
|
||||||
|
// 计算当前模板类型
|
||||||
|
const isTreeTable = computed(() => currentTemplateType.value === InfraCodegenTemplateTypeEnum.TREE);
|
||||||
|
const isSubTable = computed(() => currentTemplateType.value === InfraCodegenTemplateTypeEnum.SUB);
|
||||||
|
|
||||||
|
/** 基础表单实例 */
|
||||||
|
const [BaseForm, baseFormApi] = useVbenForm({
|
||||||
|
wrapperClass,
|
||||||
|
layout: 'horizontal',
|
||||||
|
showDefaultActions: false,
|
||||||
|
schema: useGenerationInfoBaseFormSchema(),
|
||||||
|
handleValuesChange: (values) => {
|
||||||
|
// 监听模板类型变化
|
||||||
|
if (values.templateType !== undefined && values.templateType !== currentTemplateType.value) {
|
||||||
|
currentTemplateType.value = values.templateType;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 树表信息表单实例 */
|
||||||
|
const [TreeForm, treeFormApi] = useVbenForm({
|
||||||
|
wrapperClass,
|
||||||
|
layout: 'horizontal',
|
||||||
|
showDefaultActions: false,
|
||||||
|
schema: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 主子表信息表单实例 */
|
||||||
|
const [SubForm, subFormApi] = useVbenForm({
|
||||||
|
wrapperClass,
|
||||||
|
layout: 'horizontal',
|
||||||
|
showDefaultActions: false,
|
||||||
|
schema: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 更新树表信息表单 schema */
|
||||||
|
function updateTreeSchema(): void {
|
||||||
|
const schema = useTreeTableFormSchema(props.columns);
|
||||||
|
treeFormApi.setState({ schema });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新主子表信息表单 schema */
|
||||||
|
function updateSubSchema(): void {
|
||||||
|
const schema = useSubTableFormSchema(props.columns, tables.value);
|
||||||
|
subFormApi.setState({ schema });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取合并的表单值 */
|
||||||
|
async function getAllFormValues(): Promise<Record<string, any>> {
|
||||||
|
// 基础表单值
|
||||||
|
const baseValues = await baseFormApi.getValues();
|
||||||
|
|
||||||
|
// 根据模板类型获取对应的额外表单值
|
||||||
|
let extraValues = {};
|
||||||
|
if (isTreeTable.value) {
|
||||||
|
extraValues = await treeFormApi.getValues();
|
||||||
|
} else if (isSubTable.value) {
|
||||||
|
extraValues = await subFormApi.getValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并表单值
|
||||||
|
return { ...baseValues, ...extraValues };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 验证所有表单 */
|
||||||
|
async function validateAllForms() {
|
||||||
|
let validateResult: boolean;
|
||||||
|
// 验证基础表单
|
||||||
|
const { valid: baseFormValid } = await baseFormApi.validate();
|
||||||
|
validateResult = baseFormValid;
|
||||||
|
// 根据模板类型验证对应的额外表单
|
||||||
|
if (isTreeTable.value) {
|
||||||
|
const { valid: treeFormValid } = await treeFormApi.validate();
|
||||||
|
validateResult = baseFormValid && treeFormValid;
|
||||||
|
} else if (isSubTable.value) {
|
||||||
|
const { valid: subFormValid } = await subFormApi.validate();
|
||||||
|
validateResult = baseFormValid && subFormValid;
|
||||||
|
}
|
||||||
|
return validateResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 设置表单值 */
|
||||||
|
function setAllFormValues(values: Record<string, any>): void {
|
||||||
|
if (!values) return;
|
||||||
|
|
||||||
|
// 记录模板类型
|
||||||
|
currentTemplateType.value = values.templateType;
|
||||||
|
|
||||||
|
// 设置基础表单值
|
||||||
|
baseFormApi.setValues(values);
|
||||||
|
|
||||||
|
// 根据模板类型设置对应的额外表单值
|
||||||
|
if (isTreeTable.value) {
|
||||||
|
treeFormApi.setValues(values);
|
||||||
|
} else if (isSubTable.value) {
|
||||||
|
subFormApi.setValues(values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 监听表格数据变化 */
|
||||||
|
watch(
|
||||||
|
() => props.table,
|
||||||
|
async (val) => {
|
||||||
|
if (!val || isEmpty(val)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 初始化树表的schema
|
||||||
|
updateTreeSchema();
|
||||||
|
// 设置表单值
|
||||||
|
setAllFormValues(val);
|
||||||
|
// 获取表数据,用于主子表选择
|
||||||
|
if (typeof val.dataSourceConfigId === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tables.value = await getCodegenTableList(val.dataSourceConfigId);
|
||||||
|
// 初始化子表 schema
|
||||||
|
updateSubSchema();
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 暴露出表单校验方法和表单值获取方法 */
|
||||||
|
defineExpose({
|
||||||
|
validate: validateAllForms,
|
||||||
|
getValues: getAllFormValues,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- 基础表单 -->
|
||||||
|
<BaseForm />
|
||||||
|
|
||||||
|
<!-- 树表信息表单 -->
|
||||||
|
<TreeForm v-if="isTreeTable" />
|
||||||
|
|
||||||
|
<!-- 主子表信息表单 -->
|
||||||
|
<SubForm v-if="isSubTable" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
import type { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { createCodegenList, getSchemaTableList } from '#/api/infra/codegen';
|
||||||
|
import { getDataSourceConfigList } from '#/api/infra/data-source-config';
|
||||||
|
import { reactive, ref, unref } from 'vue';
|
||||||
|
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
|
import { useImportTableFormSchema } from '#/views/infra/codegen/data';
|
||||||
|
|
||||||
|
/** 定义组件事件 */
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'success'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const dataSourceConfigList = ref<InfraDataSourceConfigApi.InfraDataSourceConfig[]>([]);
|
||||||
|
const formData = reactive<InfraCodegenApi.CodegenCreateListReq>({
|
||||||
|
dataSourceConfigId: undefined,
|
||||||
|
tableNames: [], // 已选择的表列表
|
||||||
|
});
|
||||||
|
/** 表格实例 */
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useImportTableFormSchema([]),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: [
|
||||||
|
{ type: 'checkbox', width: 40 },
|
||||||
|
{ field: 'name', title: '表名称', minWidth: 200 },
|
||||||
|
{ field: 'comment', title: '表描述', minWidth: 200 },
|
||||||
|
],
|
||||||
|
height: '600px',
|
||||||
|
keepSource: true,
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
if (formValues.dataSourceConfigId === undefined) {
|
||||||
|
if (unref(dataSourceConfigList).length > 0) {
|
||||||
|
formValues.dataSourceConfigId = unref(dataSourceConfigList)[0]?.id;
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formData.dataSourceConfigId = formValues.dataSourceConfigId;
|
||||||
|
return await getSchemaTableList({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'name',
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
checkboxConfig: {
|
||||||
|
highlight: true,
|
||||||
|
range: true,
|
||||||
|
},
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<InfraCodegenApi.DatabaseTable>,
|
||||||
|
gridEvents: {
|
||||||
|
checkboxChange: ({ records }: { records: InfraCodegenApi.DatabaseTable[] }) => {
|
||||||
|
formData.tableNames = records.map((item) => item.name);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 模态框实例 */
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
title: '导入表',
|
||||||
|
class: 'w-2/3',
|
||||||
|
async onConfirm() {
|
||||||
|
modalApi.lock();
|
||||||
|
// 1. 获取表单值
|
||||||
|
if (formData?.dataSourceConfigId === undefined) {
|
||||||
|
message.error('请选择数据源');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 2. 校验是否选择了表
|
||||||
|
if (formData.tableNames.length === 0) {
|
||||||
|
message.error('请选择需要导入的表');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 3. 提交请求
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: '导入中...',
|
||||||
|
duration: 0,
|
||||||
|
key: 'import_loading',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await createCodegenList(formData);
|
||||||
|
// 关闭并提示
|
||||||
|
await modalApi.close();
|
||||||
|
emit('success');
|
||||||
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.operationSuccess'),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
modalApi.lock(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取数据源配置列表
|
||||||
|
async function initDataSourceConfig() {
|
||||||
|
try {
|
||||||
|
dataSourceConfigList.value = await getDataSourceConfigList();
|
||||||
|
gridApi.setState({
|
||||||
|
formOptions: {
|
||||||
|
schema: useImportTableFormSchema(dataSourceConfigList.value),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据源配置失败', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
initDataSourceConfig();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal>
|
||||||
|
<Grid />
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,305 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { Copy } from '@vben/icons';
|
||||||
|
import { Button, message, Tree } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { previewCodegen } from '#/api/infra/codegen';
|
||||||
|
import { computed, h, ref } from 'vue';
|
||||||
|
|
||||||
|
import { useClipboard } from '@vueuse/core';
|
||||||
|
import hljs from 'highlight.js/lib/core';
|
||||||
|
import java from 'highlight.js/lib/languages/java';
|
||||||
|
import javascript from 'highlight.js/lib/languages/javascript';
|
||||||
|
import sql from 'highlight.js/lib/languages/sql';
|
||||||
|
import typescript from 'highlight.js/lib/languages/typescript';
|
||||||
|
import xml from 'highlight.js/lib/languages/xml';
|
||||||
|
|
||||||
|
/** 注册代码高亮语言 */
|
||||||
|
hljs.registerLanguage('java', java);
|
||||||
|
hljs.registerLanguage('xml', xml);
|
||||||
|
hljs.registerLanguage('html', xml);
|
||||||
|
hljs.registerLanguage('vue', xml);
|
||||||
|
hljs.registerLanguage('javascript', javascript);
|
||||||
|
hljs.registerLanguage('sql', sql);
|
||||||
|
hljs.registerLanguage('typescript', typescript);
|
||||||
|
|
||||||
|
/** 文件树类型 */
|
||||||
|
interface FileNode {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
parentKey: string;
|
||||||
|
isLeaf?: boolean;
|
||||||
|
children?: FileNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 组件状态 */
|
||||||
|
const loading = ref(false);
|
||||||
|
const fileTree = ref<FileNode[]>([]);
|
||||||
|
const previewFiles = ref<InfraCodegenApi.CodegenPreview[]>([]);
|
||||||
|
const activeKey = ref<string>('');
|
||||||
|
const highlightedCode = ref<string>('');
|
||||||
|
|
||||||
|
/** 当前活动文件的语言 */
|
||||||
|
const activeLanguage = computed(() => {
|
||||||
|
return activeKey.value.split('.').pop() || '';
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 复制代码 */
|
||||||
|
const copyCode = async () => {
|
||||||
|
const { copy } = useClipboard();
|
||||||
|
const file = previewFiles.value.find((item) => item.filePath === activeKey.value);
|
||||||
|
if (file) {
|
||||||
|
await copy(file.code);
|
||||||
|
message.success('复制成功');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 文件节点点击事件 */
|
||||||
|
const handleNodeClick = (_: any[], e: any) => {
|
||||||
|
if (e.node.isLeaf) {
|
||||||
|
activeKey.value = e.node.key;
|
||||||
|
const file = previewFiles.value.find((item) => item.filePath === activeKey.value);
|
||||||
|
if (file) {
|
||||||
|
const lang = file.filePath.split('.').pop() || '';
|
||||||
|
try {
|
||||||
|
highlightedCode.value = hljs.highlight(file.code, { language: lang }).value;
|
||||||
|
} catch {
|
||||||
|
highlightedCode.value = file.code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 处理文件树 */
|
||||||
|
const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => {
|
||||||
|
const exists: Record<string, boolean> = {};
|
||||||
|
const files: FileNode[] = [];
|
||||||
|
|
||||||
|
// 处理文件路径
|
||||||
|
for (const item of data) {
|
||||||
|
const paths = item.filePath.split('/');
|
||||||
|
let fullPath = '';
|
||||||
|
|
||||||
|
// 处理Java文件路径
|
||||||
|
const newPaths = [];
|
||||||
|
let i = 0;
|
||||||
|
while (i < paths.length) {
|
||||||
|
const path = paths[i];
|
||||||
|
|
||||||
|
if (path === 'java' && i + 1 < paths.length) {
|
||||||
|
newPaths.push(path);
|
||||||
|
|
||||||
|
// 合并包路径
|
||||||
|
let packagePath = '';
|
||||||
|
i++;
|
||||||
|
while (i < paths.length) {
|
||||||
|
const nextPath = paths[i] || '';
|
||||||
|
if (['controller', 'convert', 'dal', 'dataobject', 'enums', 'mysql', 'service', 'vo'].includes(nextPath)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
packagePath = packagePath ? `${packagePath}.${nextPath}` : nextPath;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packagePath) {
|
||||||
|
newPaths.push(packagePath);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
newPaths.push(path);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建文件树
|
||||||
|
for (let i = 0; i < newPaths.length; i++) {
|
||||||
|
const oldFullPath = fullPath;
|
||||||
|
fullPath = fullPath.length === 0 ? newPaths[i] || '' : `${fullPath.replaceAll('.', '/')}/${newPaths[i]}`;
|
||||||
|
|
||||||
|
if (exists[fullPath]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
exists[fullPath] = true;
|
||||||
|
files.push({
|
||||||
|
key: fullPath,
|
||||||
|
title: newPaths[i] || '',
|
||||||
|
parentKey: oldFullPath || '/',
|
||||||
|
isLeaf: i === newPaths.length - 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 构建树形结构 */
|
||||||
|
const buildTree = (parentKey: string): FileNode[] => {
|
||||||
|
return files
|
||||||
|
.filter((file) => file.parentKey === parentKey)
|
||||||
|
.map((file) => ({
|
||||||
|
...file,
|
||||||
|
children: buildTree(file.key),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
return buildTree('/');
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 模态框实例 */
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
footer: false,
|
||||||
|
class: 'w-3/5',
|
||||||
|
async onOpenChange(isOpen: boolean) {
|
||||||
|
if (!isOpen) {
|
||||||
|
previewFiles.value = [];
|
||||||
|
fileTree.value = [];
|
||||||
|
activeKey.value = '';
|
||||||
|
highlightedCode.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const row = modalApi.getData<InfraCodegenApi.CodegenTable>();
|
||||||
|
if (!row) return;
|
||||||
|
|
||||||
|
// 加载预览数据
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const data = await previewCodegen(row.id);
|
||||||
|
previewFiles.value = data;
|
||||||
|
fileTree.value = handleFiles(data);
|
||||||
|
|
||||||
|
// 默认选中第一个文件
|
||||||
|
if (data.length > 0) {
|
||||||
|
activeKey.value = data[0]?.filePath || '';
|
||||||
|
const lang = activeKey.value.split('.').pop() || '';
|
||||||
|
const code = data[0]?.code || '';
|
||||||
|
try {
|
||||||
|
highlightedCode.value = hljs.highlight(code, { language: lang }).value;
|
||||||
|
} catch {
|
||||||
|
highlightedCode.value = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal title="代码预览">
|
||||||
|
<div class="h-1/1 flex" v-loading="loading">
|
||||||
|
<!-- 文件树 -->
|
||||||
|
<div class="w-1/3 border-r border-gray-200 pr-4 dark:border-gray-700">
|
||||||
|
<Tree :selected-keys="[activeKey]" :tree-data="fileTree" @select="handleNodeClick" />
|
||||||
|
</div>
|
||||||
|
<!-- 代码预览 -->
|
||||||
|
<div class="w-2/3 pl-4">
|
||||||
|
<div class="mb-2 flex justify-between">
|
||||||
|
<div class="text-lg font-medium dark:text-gray-200">
|
||||||
|
{{ activeKey.split('/').pop() }}
|
||||||
|
<span class="ml-2 text-xs text-gray-500 dark:text-gray-400">({{ activeLanguage }})</span>
|
||||||
|
</div>
|
||||||
|
<Button type="primary" ghost @click="copyCode" :icon="h(Copy)"> 复制代码 </Button>
|
||||||
|
</div>
|
||||||
|
<div class="h-[calc(100%-40px)] overflow-auto">
|
||||||
|
<pre class="overflow-auto rounded-md bg-gray-50 p-4 text-gray-800 dark:bg-gray-800 dark:text-gray-200">
|
||||||
|
<code v-html="highlightedCode" class="code-highlight"></code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 代码高亮样式 - 支持暗黑模式 */
|
||||||
|
:deep(.code-highlight) {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 关键字 */
|
||||||
|
:deep(.hljs-keyword) {
|
||||||
|
@apply text-purple-600 dark:text-purple-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 字符串 */
|
||||||
|
:deep(.hljs-string) {
|
||||||
|
@apply text-green-600 dark:text-green-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 注释 */
|
||||||
|
:deep(.hljs-comment) {
|
||||||
|
@apply text-gray-500 dark:text-gray-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 函数 */
|
||||||
|
:deep(.hljs-function) {
|
||||||
|
@apply text-blue-600 dark:text-blue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 数字 */
|
||||||
|
:deep(.hljs-number) {
|
||||||
|
@apply text-orange-600 dark:text-orange-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 类 */
|
||||||
|
:deep(.hljs-class) {
|
||||||
|
@apply text-yellow-600 dark:text-yellow-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 标题/函数名 */
|
||||||
|
:deep(.hljs-title) {
|
||||||
|
@apply font-bold text-blue-600 dark:text-blue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 参数 */
|
||||||
|
:deep(.hljs-params) {
|
||||||
|
@apply text-gray-700 dark:text-gray-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内置对象 */
|
||||||
|
:deep(.hljs-built_in) {
|
||||||
|
@apply text-teal-600 dark:text-teal-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTML标签 */
|
||||||
|
:deep(.hljs-tag) {
|
||||||
|
@apply text-blue-600 dark:text-blue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 属性 */
|
||||||
|
:deep(.hljs-attribute),
|
||||||
|
:deep(.hljs-attr) {
|
||||||
|
@apply text-green-600 dark:text-green-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 字面量 */
|
||||||
|
:deep(.hljs-literal) {
|
||||||
|
@apply text-purple-600 dark:text-purple-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 元信息 */
|
||||||
|
:deep(.hljs-meta) {
|
||||||
|
@apply text-gray-500 dark:text-gray-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选择器标签 */
|
||||||
|
:deep(.hljs-selector-tag) {
|
||||||
|
@apply text-blue-600 dark:text-blue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XML/HTML名称 */
|
||||||
|
:deep(.hljs-name) {
|
||||||
|
@apply text-blue-600 dark:text-blue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 变量 */
|
||||||
|
:deep(.hljs-variable) {
|
||||||
|
@apply text-orange-600 dark:text-orange-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 属性 */
|
||||||
|
:deep(.hljs-property) {
|
||||||
|
@apply text-red-600 dark:text-red-400;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -33,7 +33,7 @@ function isBoolean(value: unknown): value is boolean {
|
||||||
* @param {T} value 要检查的值。
|
* @param {T} value 要检查的值。
|
||||||
* @returns {boolean} 如果值为空,返回true,否则返回false。
|
* @returns {boolean} 如果值为空,返回true,否则返回false。
|
||||||
*/
|
*/
|
||||||
function isEmpty<T = unknown>(value?: T): value is T {
|
function isEmpty<T = unknown>(value?: T): boolean {
|
||||||
if (value === null || value === undefined) {
|
if (value === null || value === undefined) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -75,9 +75,7 @@ function isHttpUrl(url?: string): boolean {
|
||||||
* @returns {boolean} 如果值是window对象,返回true,否则返回false。
|
* @returns {boolean} 如果值是window对象,返回true,否则返回false。
|
||||||
*/
|
*/
|
||||||
function isWindow(value: any): value is Window {
|
function isWindow(value: any): value is Window {
|
||||||
return (
|
return typeof window !== 'undefined' && value !== null && value === value.window;
|
||||||
typeof window !== 'undefined' && value !== null && value === value.window
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -137,9 +135,7 @@ function isNumber(value: any): value is number {
|
||||||
* // Returns undefined because all values are either null or undefined.
|
* // Returns undefined because all values are either null or undefined.
|
||||||
* getFirstNonNullOrUndefined(undefined, null); // undefined
|
* getFirstNonNullOrUndefined(undefined, null); // undefined
|
||||||
*/
|
*/
|
||||||
function getFirstNonNullOrUndefined<T>(
|
function getFirstNonNullOrUndefined<T>(...values: (null | T | undefined)[]): T | undefined {
|
||||||
...values: (null | T | undefined)[]
|
|
||||||
): T | undefined {
|
|
||||||
for (const value of values) {
|
for (const value of values) {
|
||||||
if (value !== undefined && value !== null) {
|
if (value !== undefined && value !== null) {
|
||||||
return value;
|
return value;
|
||||||
|
|
|
||||||
|
|
@ -191,3 +191,4 @@ catalog:
|
||||||
watermark-js-plus: ^1.5.8
|
watermark-js-plus: ^1.5.8
|
||||||
zod: ^3.24.2
|
zod: ^3.24.2
|
||||||
zod-defaults: ^0.1.3
|
zod-defaults: ^0.1.3
|
||||||
|
highlight.js: ^11.11.1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue