!233 【antd】【ele】Mall 迁移 80%

Merge pull request !233 from 芋道源码/dev
This commit is contained in:
芋道源码
2025-10-18 11:30:44 +00:00
committed by Gitee
531 changed files with 19838 additions and 35009 deletions

View File

@@ -55,7 +55,6 @@
"diagram-js": "catalog:",
"fast-xml-parser": "catalog:",
"highlight.js": "catalog:",
"min-dash": "catalog:",
"pinia": "catalog:",
"steady-xml": "catalog:",
"tinymce": "catalog:",

View File

@@ -350,6 +350,18 @@ setupVbenVxeTable({
return `${erpNumberFormatter(fenToYuan(cellValue), digits)}`;
},
});
// add by 星语:文件大小格式化
vxeUI.formats.add('formatFileSize', {
tableCellFormatMethod({ cellValue }, digits = 2) {
if (!cellValue) return '0 B';
const unitArr = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const index = Math.floor(Math.log(cellValue) / Math.log(1024));
const size = cellValue / 1024 ** index;
const formattedSize = size.toFixed(digits);
return `${formattedSize} ${unitArr[index]}`;
},
});
},
useVbenForm,
});

View File

@@ -20,18 +20,12 @@ export namespace MallCouponTemplateApi {
fixedStartTerm: number; // 领取日期-开始天数
fixedEndTerm: number; // 领取日期-结束天数
discountType: number; // 优惠类型
discountPercent: number; // 折扣百分比
discountPercent?: number; // 折扣百分比
discountPrice: number; // 优惠金额
discountLimitPrice: number; // 折扣上限
discountLimitPrice?: number; // 折扣上限
takeCount: number; // 已领取数量
useCount: number; // 已使用数量
}
/** 优惠券模板状态更新 */
export interface StatusUpdate {
id: number; // 模板编号
status: 0 | 1; // 状态
}
}
/** 创建优惠劵模板 */
@@ -49,9 +43,11 @@ export function updateCouponTemplate(
}
/** 更新优惠劵模板的状态 */
export function updateCouponTemplateStatus(id: number, status: 0 | 1) {
const data: MallCouponTemplateApi.StatusUpdate = { id, status };
return requestClient.put('/promotion/coupon-template/update-status', data);
export function updateCouponTemplateStatus(id: number, status: number) {
return requestClient.put('/promotion/coupon-template/update-status', {
id,
status,
});
}
/** 删除优惠劵模板 */
@@ -80,11 +76,3 @@ export function getCouponTemplateList(ids: number[]) {
`/promotion/coupon-template/list?ids=${ids}`,
);
}
/** 导出优惠劵模板 Excel */
export function exportCouponTemplateExcel(params: PageParam) {
return requestClient.get('/promotion/coupon-template/export-excel', {
params,
responseType: 'blob',
});
}

View File

@@ -1,5 +1,7 @@
import type { PageParam, PageResult } from '@vben/request';
import type { MallOrderApi } from '#/api/mall/trade/order';
import { requestClient } from '#/api/request';
export namespace MallAfterSaleApi {
@@ -75,6 +77,9 @@ export namespace MallAfterSaleApi {
receiveTime?: Date;
/** 收货备注 */
receiveReason?: string;
order?: MallOrderApi.Order; // 关联订单
orderItem?: MallOrderApi.OrderItem; // 关联订单项
logs?: any[]; // 关联售后日志
}
/** 拒绝售后请求 */
@@ -102,26 +107,26 @@ export function getAfterSale(id: number) {
}
/** 同意售后 */
export function agree(id: number) {
export function agreeAfterSale(id: number) {
return requestClient.put(`/trade/after-sale/agree?id=${id}`);
}
/** 拒绝售后 */
export function disagree(data: MallAfterSaleApi.DisagreeRequest) {
export function disagreeAfterSale(data: MallAfterSaleApi.DisagreeRequest) {
return requestClient.put('/trade/after-sale/disagree', data);
}
/** 确认收货 */
export function receive(id: number) {
export function receiveAfterSale(id: number) {
return requestClient.put(`/trade/after-sale/receive?id=${id}`);
}
/** 拒绝收货 */
export function refuse(id: number) {
export function refuseAfterSale(id: number) {
return requestClient.put(`/trade/after-sale/refuse?id=${id}`);
}
/** 确认退款 */
export function refund(id: number) {
export function refundAfterSale(id: number) {
return requestClient.put(`/trade/after-sale/refund?id=${id}`);
}

View File

@@ -6,11 +6,11 @@ export namespace MallOrderApi {
/** 商品属性 */
export interface ProductProperty {
/** 属性的编号 */
propertyId?: null | number;
propertyId?: number;
/** 属性的名称 */
propertyName?: string;
/** 属性值的编号 */
valueId?: null | number;
valueId?: number;
/** 属性值的名称 */
valueName?: string;
}
@@ -18,37 +18,38 @@ export namespace MallOrderApi {
/** 订单项 */
export interface OrderItem {
/** 编号 */
id?: null | number;
id?: number;
/** 用户编号 */
userId?: null | number;
userId?: number;
/** 订单编号 */
orderId?: null | number;
orderId?: number;
/** 商品 SPU 编号 */
spuId?: null | number;
spuId?: number;
/** 商品 SPU 名称 */
spuName?: string;
/** 商品 SKU 编号 */
skuId?: null | number;
skuId?: number;
/** 商品图片 */
picUrl?: string;
/** 购买数量 */
count?: null | number;
count?: number;
/** 商品原价(总) */
originalPrice?: null | number;
originalPrice?: number;
/** 商品原价(单) */
originalUnitPrice?: null | number;
originalUnitPrice?: number;
/** 商品优惠(总) */
discountPrice?: null | number;
discountPrice?: number;
/** 商品实付金额(总) */
payPrice?: null | number;
payPrice?: number;
/** 子订单分摊金额(总) */
orderPartPrice?: null | number;
orderPartPrice?: number;
/** 分摊后子订单实付金额(总) */
orderDividePrice?: null | number;
orderDividePrice?: number;
/** 售后状态 */
afterSaleStatus?: null | number;
afterSaleStatus?: number;
/** 属性数组 */
properties?: ProductProperty[];
price?: number;
}
/** 订单日志 */
@@ -59,96 +60,98 @@ export namespace MallOrderApi {
createTime?: Date;
/** 用户类型 */
userType?: number;
/** 用户编号 */
userId?: number;
}
/** 订单 */
export interface Order {
/** 订单编号 */
id?: null | number;
id?: number;
/** 订单流水号 */
no?: string;
/** 下单时间 */
createTime?: Date | null;
createTime?: Date;
/** 订单类型 */
type?: null | number;
type?: number;
/** 订单来源 */
terminal?: null | number;
terminal?: number;
/** 用户编号 */
userId?: null | number;
userId?: number;
/** 用户 IP */
userIp?: string;
/** 用户备注 */
userRemark?: string;
/** 订单状态 */
status?: null | number;
status?: number;
/** 购买的商品数量 */
productCount?: null | number;
productCount?: number;
/** 订单完成时间 */
finishTime?: Date | null;
finishTime?: Date;
/** 订单取消时间 */
cancelTime?: Date | null;
cancelTime?: Date;
/** 取消类型 */
cancelType?: null | number;
cancelType?: number;
/** 商家备注 */
remark?: string;
/** 支付订单编号 */
payOrderId?: null | number;
payOrderId?: number;
/** 是否已支付 */
payStatus?: boolean;
/** 付款时间 */
payTime?: Date | null;
payTime?: Date;
/** 支付渠道 */
payChannelCode?: string;
/** 商品原价(总) */
totalPrice?: null | number;
totalPrice?: number;
/** 订单优惠(总) */
discountPrice?: null | number;
discountPrice?: number;
/** 运费金额 */
deliveryPrice?: null | number;
deliveryPrice?: number;
/** 订单调价(总) */
adjustPrice?: null | number;
adjustPrice?: number;
/** 应付金额(总) */
payPrice?: null | number;
payPrice?: number;
/** 发货方式 */
deliveryType?: null | number;
deliveryType?: number;
/** 自提门店编号 */
pickUpStoreId?: number;
/** 自提核销码 */
pickUpVerifyCode?: string;
/** 配送模板编号 */
deliveryTemplateId?: null | number;
deliveryTemplateId?: number;
/** 发货物流公司编号 */
logisticsId?: null | number;
logisticsId?: number;
/** 发货物流单号 */
logisticsNo?: string;
/** 发货时间 */
deliveryTime?: Date | null;
deliveryTime?: Date;
/** 收货时间 */
receiveTime?: Date | null;
receiveTime?: Date;
/** 收件人名称 */
receiverName?: string;
/** 收件人手机 */
receiverMobile?: string;
/** 收件人邮编 */
receiverPostCode?: null | number;
receiverPostCode?: number;
/** 收件人地区编号 */
receiverAreaId?: null | number;
receiverAreaId?: number;
/** 收件人地区名字 */
receiverAreaName?: string;
/** 收件人详细地址 */
receiverDetailAddress?: string;
/** 售后状态 */
afterSaleStatus?: null | number;
afterSaleStatus?: number;
/** 退款金额 */
refundPrice?: null | number;
refundPrice?: number;
/** 优惠劵编号 */
couponId?: null | number;
couponId?: number;
/** 优惠劵减免金额 */
couponPrice?: null | number;
couponPrice?: number;
/** 积分抵扣的金额 */
pointPrice?: null | number;
pointPrice?: number;
/** VIP 减免金额 */
vipPrice?: null | number;
vipPrice?: number;
/** 订单项列表 */
items?: OrderItem[];
/** 下单用户信息 */
@@ -156,7 +159,7 @@ export namespace MallOrderApi {
/** 用户头像 */
avatar?: string;
/** 用户编号 */
id?: null | number;
id?: number;
/** 用户昵称 */
nickname?: string;
};
@@ -165,7 +168,7 @@ export namespace MallOrderApi {
/** 用户头像 */
avatar?: string;
/** 用户编号 */
id?: null | number;
id?: number;
/** 用户昵称 */
nickname?: string;
};
@@ -192,7 +195,7 @@ export namespace MallOrderApi {
/** 发货方式 */
expressType: string;
/** 物流公司编号 */
logisticsId: null | number;
logisticsId: number;
/** 物流编号 */
logisticsNo: string;
}
@@ -239,7 +242,7 @@ export function getOrderPage(params: PageParam) {
}
/** 查询交易订单统计 */
export function getOrderSummary(params: PageParam) {
export function getOrderSummary(params: any) {
return requestClient.get<MallOrderApi.OrderSummary>('/trade/order/summary', {
params,
});
@@ -284,7 +287,7 @@ export function pickUpOrder(id: number) {
/** 订单核销 */
export function pickUpOrderByVerifyCode(pickUpVerifyCode: string) {
return requestClient.put('/trade/order/pick-up-by-verify-code', {
return requestClient.put('/trade/order/pick-up-by-verify-code', undefined, {
params: { pickUpVerifyCode },
});
}

View File

@@ -3,7 +3,6 @@ import { isAny } from 'bpmn-js/lib/features/modeling/util/ModelingUtil';
import { isEventSubProcess, isExpanded } from 'bpmn-js/lib/util/DiUtil';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import { hasPrimaryModifier } from 'diagram-js/lib/util/Mouse';
import { assign, forEach, isArray } from 'min-dash';
/**
* A provider for BPMN 2.0 elements context pad
@@ -139,7 +138,9 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
}
function appendStart(event, element) {
const shape = elementFactory.createShape(assign({ type }, options));
const shape = elementFactory.createShape(
Object.assign({ type }, options),
);
create.start(event, shape, {
source: element,
});
@@ -147,7 +148,9 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
const append = autoPlace
? function (event, element) {
const shape = elementFactory.createShape(assign({ type }, options));
const shape = elementFactory.createShape(
Object.assign({ type }, options),
);
autoPlace.append(element, shape);
}
@@ -181,7 +184,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
) {
const childLanes = getChildLanes(element);
assign(actions, {
Object.assign(actions, {
'lane-insert-above': {
group: 'lane-insert-above',
className: 'bpmn-icon-lane-insert-above',
@@ -196,7 +199,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
if (childLanes.length < 2) {
if (element.height >= 120) {
assign(actions, {
Object.assign(actions, {
'lane-divide-two': {
group: 'lane-divide',
className: 'bpmn-icon-lane-divide-two',
@@ -209,7 +212,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
}
if (element.height >= 180) {
assign(actions, {
Object.assign(actions, {
'lane-divide-three': {
group: 'lane-divide',
className: 'bpmn-icon-lane-divide-three',
@@ -222,7 +225,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
}
}
assign(actions, {
Object.assign(actions, {
'lane-insert-below': {
group: 'lane-insert-below',
className: 'bpmn-icon-lane-insert-below',
@@ -238,7 +241,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
if (is(businessObject, 'bpmn:FlowNode')) {
if (is(businessObject, 'bpmn:EventBasedGateway')) {
assign(actions, {
Object.assign(actions, {
'append.receive-task': appendAction(
'bpmn:ReceiveTask',
'bpmn-icon-receive-task',
@@ -276,7 +279,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
'bpmn:CompensateEventDefinition',
)
) {
assign(actions, {
Object.assign(actions, {
'append.compensation-activity': appendAction(
'bpmn:Task',
'bpmn-icon-task',
@@ -296,7 +299,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
) &&
!isEventSubProcess(businessObject)
) {
assign(actions, {
Object.assign(actions, {
'append.end-event': appendAction(
'bpmn:EndEvent',
'bpmn-icon-end-event-none',
@@ -323,14 +326,14 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
if (!popupMenu.isEmpty(element, 'bpmn-replace')) {
// Replace menu entry
assign(actions, {
Object.assign(actions, {
replace: {
group: 'edit',
className: 'bpmn-icon-screw-wrench',
title: '修改类型',
action: {
click(event, element) {
const position = assign(getReplaceMenuPosition(element), {
const position = Object.assign(getReplaceMenuPosition(element), {
cursor: { x: event.x, y: event.y },
});
@@ -349,7 +352,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
'bpmn:DataStoreReference',
])
) {
assign(actions, {
Object.assign(actions, {
'append.text-annotation': appendAction(
'bpmn:TextAnnotation',
'bpmn-icon-text-annotation',
@@ -377,7 +380,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
'bpmn:DataStoreReference',
])
) {
assign(actions, {
Object.assign(actions, {
connect: {
group: 'connect',
className: 'bpmn-icon-connection-multi',
@@ -391,7 +394,7 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
}
if (is(businessObject, 'bpmn:Group')) {
assign(actions, {
Object.assign(actions, {
'append.text-annotation': appendAction(
'bpmn:TextAnnotation',
'bpmn-icon-text-annotation',
@@ -402,13 +405,13 @@ ContextPadProvider.prototype.getContextPadEntries = function (element) {
// delete element entry, only show if allowed by rules
let deleteAllowed = rules.allowed('elements.delete', { elements: [element] });
if (isArray(deleteAllowed)) {
if (Array.isArray(deleteAllowed)) {
// was the element returned as a deletion candidate?
deleteAllowed = deleteAllowed[0] === element;
}
if (deleteAllowed) {
assign(actions, {
Object.assign(actions, {
delete: {
group: 'edit',
className: 'bpmn-icon-trash',
@@ -430,7 +433,7 @@ function isEventType(eventBo, type, definition) {
let isDefinition = false;
const definitions = eventBo.eventDefinitions || [];
forEach(definitions, (def) => {
definitions.forEach((def) => {
if (def.$type === definition) {
isDefinition = true;
}

View File

@@ -1,10 +1,3 @@
'use strict';
import { some } from 'min-dash';
// const some = require('min-dash').some
// const some = some
const ALLOWED_TYPES = {
FailedJobRetryTimeCycle: [
'bpmn:StartEvent',
@@ -25,20 +18,20 @@ function is(element, type) {
}
function exists(element) {
return element && element.length;
return element && element.length > 0;
}
function includesType(collection, type) {
return (
exists(collection) &&
some(collection, (element) => {
collection.some((element) => {
return is(element, type);
})
);
}
function anyType(element, types) {
return some(types, (type) => {
return types.some((type) => {
return is(element, type);
});
}

View File

@@ -1,18 +1,9 @@
'use strict';
import { isFunction, isObject, some } from 'min-dash';
// const isFunction = isFunction,
// isObject = isObject,
// some = some
// const isFunction = require('min-dash').isFunction,
// isObject = require('min-dash').isObject,
// some = require('min-dash').some
import { isFunction, isObject } from '@vben/utils';
const WILDCARD = '*';
function CamundaModdleExtension(eventBus) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
// eslint-disable-next-line unicorn/no-this-assignment, @typescript-eslint/no-this-alias
const self = this;
eventBus.on('moddleCopy.canCopyProperty', (context) => {
@@ -122,7 +113,7 @@ function is(element, type) {
}
function isAny(element, types) {
return some(types, (t) => {
return types.some((t) => {
return is(element, t);
});
}
@@ -155,7 +146,7 @@ function isAllowedInParent(property, parent) {
}
// (2) check wether property has parent of allowed type
return some(allowedIn, (type) => {
return allowedIn.some((type) => {
return getParent(parent, type);
});
}

View File

@@ -1,10 +1,3 @@
'use strict';
import { some } from 'min-dash';
// const some = some
// const some = require('min-dash').some
const ALLOWED_TYPES = {
FailedJobRetryTimeCycle: [
'bpmn:StartEvent',
@@ -25,20 +18,20 @@ function is(element, type) {
}
function exists(element) {
return element && element.length;
return element && element.length > 0;
}
function includesType(collection, type) {
return (
exists(collection) &&
some(collection, (element) => {
collection.some((element) => {
return is(element, type);
})
);
}
function anyType(element, types) {
return some(types, (type) => {
return types.some((type) => {
return is(element, type);
});
}

View File

@@ -1,5 +1,4 @@
import PaletteProvider from 'bpmn-js/lib/features/palette/PaletteProvider';
import { assign } from 'min-dash';
export default function CustomPalette(
palette,
@@ -41,7 +40,9 @@ F.prototype.getPaletteEntries = function () {
function createAction(type, group, className, title, options) {
function createListener(event) {
const shape = elementFactory.createShape(assign({ type }, options));
const shape = Object.assign(
elementFactory.createShape({ type }, options),
);
if (options) {
shape.businessObject.di.isExpanded = options.isExpanded;
@@ -89,7 +90,7 @@ F.prototype.getPaletteEntries = function () {
create.start(event, elementFactory.createParticipantShape());
}
assign(actions, {
Object.assign(actions, {
'hand-tool': {
group: 'tools',
className: 'bpmn-icon-hand-tool',

View File

@@ -1,5 +1,3 @@
import { assign } from 'min-dash';
/**
* A palette provider for BPMN 2.0 elements.
*/
@@ -48,7 +46,9 @@ PaletteProvider.prototype.getPaletteEntries = function () {
function createAction(type, group, className, title, options) {
function createListener(event) {
const shape = elementFactory.createShape(assign({ type }, options));
const shape = elementFactory.createShape(
Object.assign({ type }, options),
);
if (options) {
shape.businessObject.di.isExpanded = options.isExpanded;
@@ -96,7 +96,7 @@ PaletteProvider.prototype.getPaletteEntries = function () {
create.start(event, elementFactory.createParticipantShape());
}
assign(actions, {
Object.assign(actions, {
'hand-tool': {
group: 'tools',
className: 'bpmn-icon-hand-tool',

View File

@@ -1,6 +1,5 @@
<script lang="ts" setup>
import { Button } from 'ant-design-vue';
import { assign } from 'min-dash';
defineOptions({ name: 'MyProcessPalette' });
@@ -11,7 +10,7 @@ const addTask = (event: MouseEvent, options: any = {}) => {
const create = bpmnInstances().modeler.get('create');
const shape = ElementFactory.createShape(
assign({ type: 'bpmn:UserTask' }, options),
Object.assign({ type: 'bpmn:UserTask' }, options),
);
if (options) {
@@ -26,12 +25,6 @@ const addTask = (event: MouseEvent, options: any = {}) => {
<Button type="primary" @click="addTask" @mousedown="addTask">
测试任务
</Button>
<div class="test-container" id="palette-container">1</div>
<div class="mt-4" id="palette-container">1</div>
</div>
</template>
<style scoped>
.test-container {
margin-top: 16px;
}
</style>

View File

@@ -238,7 +238,7 @@ watch(
<IconifyIcon
icon="ant-design:check-circle-filled"
v-if="valid"
style="color: green; margin-left: 8px"
style=" margin-left: 8px;color: green"
/>
</div>
<div style="display: flex; align-items: center; margin-top: 10px">

View File

@@ -1,6 +1,8 @@
<script lang="ts" setup>
import type { PropType } from 'vue';
import type { CronData, CronValue, ShortcutsType } from './types';
import { computed, onMounted, reactive, ref, watch } from 'vue';
import {
@@ -16,6 +18,8 @@ import {
Tabs,
} from 'ant-design-vue';
import { CronDataDefault, CronValueDefault } from './types';
defineOptions({ name: 'Crontab' });
const props = defineProps({
@@ -31,276 +35,12 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']);
interface ShortcutsType {
text: string;
value: string;
}
interface CronRange {
start: number | string | undefined;
end: number | string | undefined;
}
interface CronLoop {
start: number | string | undefined;
end: number | string | undefined;
}
interface CronItem {
type: string;
range: CronRange;
loop: CronLoop;
appoint: string[];
last?: string;
}
interface CronValue {
second: CronItem;
minute: CronItem;
hour: CronItem;
day: CronItem;
month: CronItem;
week: CronItem & { last: string };
year: CronItem;
}
interface WeekOption {
value: string;
label: string;
}
interface CronData {
second: string[];
minute: string[];
hour: string[];
day: string[];
month: string[];
week: WeekOption[];
year: number[];
}
const defaultValue = ref('');
const dialogVisible = ref(false);
const getYear = (): number[] => {
const v: number[] = [];
const y = new Date().getFullYear();
for (let i = 0; i < 11; i++) {
v.push(y + i);
}
return v;
};
const cronValue = reactive<CronValue>({
second: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 0,
end: 1,
},
appoint: [],
},
minute: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 0,
end: 1,
},
appoint: [],
},
hour: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 0,
end: 1,
},
appoint: [],
},
day: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 1,
end: 1,
},
appoint: [],
},
month: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 1,
end: 1,
},
appoint: [],
},
week: {
type: '5',
range: {
start: '2',
end: '3',
},
loop: {
start: 0,
end: '2',
},
last: '2',
appoint: [],
},
year: {
type: '-1',
range: {
start: getYear()[0],
end: getYear()[1],
},
loop: {
start: getYear()[0],
end: 1,
},
appoint: [],
},
});
const data = reactive<CronData>({
second: [
'0',
'5',
'15',
'20',
'25',
'30',
'35',
'40',
'45',
'50',
'55',
'59',
],
minute: [
'0',
'5',
'15',
'20',
'25',
'30',
'35',
'40',
'45',
'50',
'55',
'59',
],
hour: [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
],
day: [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'28',
'29',
'30',
'31',
],
month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
week: [
{
value: '1',
label: '周日',
},
{
value: '2',
label: '周一',
},
{
value: '3',
label: '周二',
},
{
value: '4',
label: '周三',
},
{
value: '5',
label: '周四',
},
{
value: '6',
label: '周五',
},
{
value: '7',
label: '周六',
},
],
year: getYear(),
});
const cronValue = reactive<CronValue>(CronValueDefault);
const data = reactive<CronData>(CronDataDefault);
const value_second = computed(() => {
const v = cronValue.second;
switch (v.type) {

View File

@@ -0,0 +1,266 @@
export interface ShortcutsType {
text: string;
value: string;
}
export interface CronRange {
start: number | string | undefined;
end: number | string | undefined;
}
export interface CronLoop {
start: number | string | undefined;
end: number | string | undefined;
}
export interface CronItem {
type: string;
range: CronRange;
loop: CronLoop;
appoint: string[];
last?: string;
}
export interface CronValue {
second: CronItem;
minute: CronItem;
hour: CronItem;
day: CronItem;
month: CronItem;
week: CronItem & { last: string };
year: CronItem;
}
export interface WeekOption {
value: string;
label: string;
}
export interface CronData {
second: string[];
minute: string[];
hour: string[];
day: string[];
month: string[];
week: WeekOption[];
year: number[];
}
const getYear = (): number[] => {
const v: number[] = [];
const y = new Date().getFullYear();
for (let i = 0; i < 11; i++) {
v.push(y + i);
}
return v;
};
export const CronValueDefault: CronValue = {
second: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 0,
end: 1,
},
appoint: [],
},
minute: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 0,
end: 1,
},
appoint: [],
},
hour: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 0,
end: 1,
},
appoint: [],
},
day: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 1,
end: 1,
},
appoint: [],
},
month: {
type: '0',
range: {
start: 1,
end: 2,
},
loop: {
start: 1,
end: 1,
},
appoint: [],
},
week: {
type: '5',
range: {
start: '2',
end: '3',
},
loop: {
start: 0,
end: '2',
},
last: '2',
appoint: [],
},
year: {
type: '-1',
range: {
start: getYear()[0],
end: getYear()[1],
},
loop: {
start: getYear()[0],
end: 1,
},
appoint: [],
},
};
export const CronDataDefault: CronData = {
second: [
'0',
'5',
'15',
'20',
'25',
'30',
'35',
'40',
'45',
'50',
'55',
'59',
],
minute: [
'0',
'5',
'15',
'20',
'25',
'30',
'35',
'40',
'45',
'50',
'55',
'59',
],
hour: [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
],
day: [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'28',
'29',
'30',
'31',
],
month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
week: [
{
value: '1',
label: '周日',
},
{
value: '2',
label: '周一',
},
{
value: '3',
label: '周二',
},
{
value: '4',
label: '周三',
},
{
value: '5',
label: '周四',
},
{
value: '6',
label: '周五',
},
{
value: '7',
label: '周六',
},
],
year: getYear(),
};

View File

@@ -7,6 +7,8 @@ import type { DescriptionItemSchema, DescriptionsOptions } from './typing';
import { defineComponent } from 'vue';
import { get } from '@vben/utils';
import { Descriptions, DescriptionsItem } from 'ant-design-vue';
/** 对 Descriptions 进行二次封装 */
@@ -45,7 +47,7 @@ const Description = defineComponent({
? item.content(props.data)
: item.content;
}
return item.field ? props.data?.[item.field] : null;
return item.field ? get(props.data, item.field) : null;
};
return () => (

View File

@@ -15,7 +15,7 @@ import {
import { requestClient } from '#/api/request';
export const useApiSelect = (option: ApiSelectProps) => {
export function useApiSelect(option: ApiSelectProps) {
return defineComponent({
name: option.name,
props: {
@@ -317,4 +317,4 @@ export const useApiSelect = (option: ApiSelectProps) => {
);
},
});
};
}

View File

@@ -2,7 +2,7 @@ import { defineComponent } from 'vue';
import ImageUpload from '#/components/upload/image-upload.vue';
export const useImagesUpload = () => {
export function useImagesUpload() {
return defineComponent({
name: 'ImagesUpload',
props: {
@@ -22,4 +22,4 @@ export const useImagesUpload = () => {
);
},
});
};
}

View File

@@ -2,7 +2,9 @@ import type { Ref } from 'vue';
import type { Menu } from '#/components/form-create/typing';
import { nextTick, onMounted } from 'vue';
import { isRef, nextTick, onMounted } from 'vue';
import formCreate from '@form-create/ant-design-vue';
import { apiSelectRule } from '#/components/form-create/rules/data';
@@ -15,6 +17,59 @@ import {
useUploadImagesRule,
} from './rules';
// 编码表单 Conf
export function encodeConf(designerRef: any) {
return JSON.stringify(designerRef.value.getOption());
}
// 编码表单 Fields
export function encodeFields(designerRef: any) {
const rule = JSON.parse(designerRef.value.getJson());
const fields: string[] = [];
rule.forEach((item: unknown) => {
fields.push(JSON.stringify(item));
});
return fields;
}
// 解码表单 Fields
export function decodeFields(fields: string[]) {
const rule: object[] = [];
fields.forEach((item) => {
rule.push(formCreate.parseJson(item));
});
return rule;
}
// 设置表单的 Conf 和 Fields适用 FcDesigner 场景
export function setConfAndFields(
designerRef: any,
conf: string,
fields: string | string[],
) {
designerRef.value.setOption(formCreate.parseJson(conf));
// 处理 fields 参数类型,确保传入 decodeFields 的是 string[] 类型
const fieldsArray = Array.isArray(fields) ? fields : [fields];
designerRef.value.setRule(decodeFields(fieldsArray));
}
// 设置表单的 Conf 和 Fields适用 form-create 场景
export function setConfAndFields2(
detailPreview: any,
conf: string,
fields: string[],
value?: any,
) {
if (isRef(detailPreview)) {
detailPreview = detailPreview.value;
}
detailPreview.option = formCreate.parseJson(conf);
detailPreview.rule = decodeFields(fields);
if (value) {
detailPreview.value = value;
}
}
export function makeRequiredRule() {
return {
type: 'Required',
@@ -23,11 +78,11 @@ export function makeRequiredRule() {
};
}
export const localeProps = (
export function localeProps(
t: (msg: string) => any,
prefix: string,
rules: any[],
) => {
) {
return rules.map((rule: { field: string; title: any }) => {
if (rule.field === 'formCreate$required') {
rule.title = t('props.required') || rule.title;
@@ -36,7 +91,7 @@ export const localeProps = (
}
return rule;
});
};
}
/**
* 解析表单组件的 field, title 等字段(递归,如果组件包含子组件)
@@ -45,11 +100,11 @@ export const localeProps = (
* @param fields 解析后表单组件字段
* @param parentTitle 如果是子表单,子表单的标题,默认为空
*/
export const parseFormFields = (
export function parseFormFields(
rule: Record<string, any>,
fields: Array<Record<string, any>> = [],
parentTitle: string = '',
) => {
) {
const { type, field, $required, title: tempTitle, children } = rule;
if (field && tempTitle) {
let title = tempTitle;
@@ -79,7 +134,7 @@ export const parseFormFields = (
parseFormFields(rule, fields);
});
}
};
}
/**
* 表单设计器增强 hook
@@ -92,7 +147,7 @@ export const parseFormFields = (
* - 部门选择器
* - 富文本
*/
export const useFormCreateDesigner = async (designer: Ref) => {
export async function useFormCreateDesigner(designer: Ref) {
const editorRule = useEditorRule();
const uploadFileRule = useUploadFileRule();
const uploadImageRule = useUploadImageRule();
@@ -101,7 +156,7 @@ export const useFormCreateDesigner = async (designer: Ref) => {
/**
* 构建表单组件
*/
const buildFormComponents = () => {
function buildFormComponents() {
// 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
designer.value?.removeMenuItem('upload');
// 移除自带的富文本组件规则,使用 editorRule 替代
@@ -122,7 +177,7 @@ export const useFormCreateDesigner = async (designer: Ref) => {
label: component.label,
});
});
};
}
const userSelectRule = useSelectRule({
name: 'UserSelect',
@@ -146,7 +201,7 @@ export const useFormCreateDesigner = async (designer: Ref) => {
/**
* 构建系统字段菜单
*/
const buildSystemMenu = () => {
function buildSystemMenu() {
// 移除自带的下拉选择器组件,使用 currencySelectRule 替代
// designer.value?.removeMenuItem('select')
// designer.value?.removeMenuItem('radio')
@@ -172,11 +227,11 @@ export const useFormCreateDesigner = async (designer: Ref) => {
}),
};
designer.value?.addMenu(menu);
};
}
onMounted(async () => {
await nextTick();
buildFormComponents();
buildSystemMenu();
});
};
}

View File

@@ -1,3 +1,3 @@
export { useApiSelect } from './components/use-api-select';
export { useFormCreateDesigner } from './helpers';
export * from './helpers';

View File

@@ -12,7 +12,7 @@ import { selectRule } from '#/components/form-create/rules/data';
/**
* 字典选择器规则,如果规则使用到动态数据则需要单独配置不能使用 useSelectRule
*/
export const useDictSelectRule = () => {
export function useDictSelectRule() {
const label = '字典选择器';
const name = 'DictSelect';
const rules = cloneDeep(selectRule);
@@ -67,4 +67,4 @@ export const useDictSelectRule = () => {
]);
},
};
};
}

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule,
} from '#/components/form-create/helpers';
export const useEditorRule = () => {
export function useEditorRule() {
const label = '富文本';
const name = 'Tinymce';
return {
@@ -33,4 +33,4 @@ export const useEditorRule = () => {
]);
},
};
};
}

View File

@@ -13,7 +13,7 @@ import { selectRule } from '#/components/form-create/rules/data';
*
* @param option 规则配置
*/
export const useSelectRule = (option: SelectRuleOption) => {
export function useSelectRule(option: SelectRuleOption) {
const label = option.label;
const name = option.name;
const rules = cloneDeep(selectRule);
@@ -42,4 +42,4 @@ export const useSelectRule = (option: SelectRuleOption) => {
]);
},
};
};
}

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule,
} from '#/components/form-create/helpers';
export const useUploadFileRule = () => {
export function useUploadFileRule() {
const label = '文件上传';
const name = 'FileUpload';
return {
@@ -81,4 +81,4 @@ export const useUploadFileRule = () => {
]);
},
};
};
}

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule,
} from '#/components/form-create/helpers';
export const useUploadImageRule = () => {
export function useUploadImageRule() {
const label = '单图上传';
const name = 'ImageUpload';
return {
@@ -90,4 +90,4 @@ export const useUploadImageRule = () => {
]);
},
};
};
}

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule,
} from '#/components/form-create/helpers';
export const useUploadImagesRule = () => {
export function useUploadImagesRule() {
const label = '多图上传';
const name = 'ImagesUpload';
return {
@@ -86,4 +86,4 @@ export const useUploadImagesRule = () => {
]);
},
};
};
}

View File

@@ -15,26 +15,14 @@ withDefaults(defineProps<OperateLogProps>(), {
function getUserTypeColor(userType: number) {
const dict = getDictObj(DICT_TYPE.USER_TYPE, userType);
switch (dict?.colorType) {
case 'danger': {
return '#F56C6C';
}
case 'info': {
return '#909399';
}
case 'success': {
return '#67C23A';
}
case 'warning': {
return '#E6A23C';
}
if (dict && dict.colorType) {
return `hsl(var(--${dict.colorType}))`;
}
return '#409EFF';
return 'hsl(var(--primary))';
}
</script>
<template>
<div>
<!-- TODO @xingyu有没可能美化下 -->
<Timeline>
<Timeline.Item
v-for="log in logList"
@@ -44,13 +32,13 @@ function getUserTypeColor(userType: number) {
<template #dot>
<p
:style="{ backgroundColor: getUserTypeColor(log.userType) }"
class="absolute left--1 flex h-5 w-5 items-center justify-center rounded-full text-xs text-white"
class="absolute left-1 top-0 flex h-5 w-5 items-center justify-center rounded-full text-xs text-white"
>
{{ getDictLabel(DICT_TYPE.USER_TYPE, log.userType)[0] }}
</p>
</template>
<p>{{ formatDateTime(log.createTime) }}</p>
<p>
<p class="ml-2">{{ formatDateTime(log.createTime) }}</p>
<p class="ml-2 mt-2">
<Tag :color="getUserTypeColor(log.userType)">
{{ log.userName }}
</Tag>

View File

@@ -40,17 +40,17 @@ const { showInput, changeNodeName, clickTitle, inputRef } = useNodeName2(
const nodeConfigRef = ref();
/** 打开节点配置 */
const openNodeConfig = () => {
function openNodeConfig() {
if (readonly) {
return;
}
nodeConfigRef.value.showChildProcessNodeConfig(currentNode.value);
};
}
/** 删除节点。更新当前节点为孩子节点 */
const deleteNode = () => {
function deleteNode() {
emits('update:flowNode', currentNode.value.childNode);
};
}
</script>
<template>
@@ -125,5 +125,3 @@ const deleteNode = () => {
/>
</div>
</template>
<style scoped></style>

View File

@@ -33,7 +33,7 @@ const emits = defineEmits<{
findParentNode: [nodeList: SimpleFlowNode[], nodeType: number];
recursiveFindParentNode: [
nodeList: SimpleFlowNode[],
curentNode: SimpleFlowNode,
currentNode: SimpleFlowNode,
nodeType: number,
];
'update:modelValue': [node: SimpleFlowNode | undefined];

View File

@@ -38,7 +38,7 @@ const emits = defineEmits<{
findParentNode: [nodeList: SimpleFlowNode[], nodeType: number];
recursiveFindParentNode: [
nodeList: SimpleFlowNode[],
curentNode: SimpleFlowNode,
currentNode: SimpleFlowNode,
nodeType: number,
];
'update:modelValue': [node: SimpleFlowNode | undefined];

View File

@@ -1,4 +1,4 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { DICT_TYPE } from '@vben/constants';

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import { useVbenModal } from '@vben/common-ui';
import { useVbenVxeGrid } from '@vben/plugins/vxe-table';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { useGridColumns } from './process-instance-data';

View File

@@ -1,4 +1,4 @@
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { DICT_TYPE } from '@vben/constants';

View File

@@ -1,6 +1,7 @@
<script lang="ts" setup>
import { useVbenModal } from '@vben/common-ui';
import { useVbenVxeGrid } from '@vben/plugins/vxe-table';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { useGridColumns } from './task-list-data';

View File

@@ -28,7 +28,7 @@ const emits = defineEmits<{
findParnetNode: [nodeList: SimpleFlowNode[], nodeType: number];
recursiveFindParentNode: [
nodeList: SimpleFlowNode[],
curentNode: SimpleFlowNode,
currentNode: SimpleFlowNode,
nodeType: number,
];
'update:modelValue': [node: SimpleFlowNode | undefined];

View File

@@ -32,7 +32,7 @@ const props = defineProps({
const emits = defineEmits<{
recursiveFindParentNode: [
nodeList: SimpleFlowNode[],
curentNode: SimpleFlowNode,
currentNode: SimpleFlowNode,
nodeType: number,
];
'update:flowNode': [node: SimpleFlowNode | undefined];

View File

@@ -8,7 +8,7 @@ import type { AxiosProgressEvent } from '#/api/infra/file';
import { computed, ref, toRefs, watch } from 'vue';
import { CloudUpload } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { isFunction, isObject, isString } from '@vben/utils';
@@ -285,7 +285,7 @@ function getValue() {
>
<div v-if="drag" class="upload-drag-area">
<p class="ant-upload-drag-icon">
<CloudUpload />
<IconifyIcon icon="lucide:cloud-upload" />
</p>
<p class="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p class="ant-upload-hint">
@@ -294,7 +294,7 @@ function getValue() {
</div>
<div v-else-if="fileList && fileList.length < maxNumber">
<Button>
<CloudUpload />
<IconifyIcon icon="lucide:cloud-upload" />
{{ $t('ui.upload.upload') }}
</Button>
</div>

View File

@@ -1,8 +1,36 @@
import type { App } from 'vue';
// import install from '@form-create/ant-design-vue/auto-import';
import formCreate from '@form-create/ant-design-vue';
import install from '@form-create/ant-design-vue/auto-import';
import FcDesigner from '@form-create/antd-designer';
import Antd from 'ant-design-vue';
// 👇使用 form-create 需额外全局引入 ant-design-vue 组件
import {
Alert,
Badge,
Card,
Collapse,
CollapsePanel,
ConfigProvider,
Divider,
Dropdown,
Image,
Layout,
LayoutContent,
LayoutFooter,
LayoutHeader,
LayoutSider,
Menu,
MenuDivider,
MenuItem,
message,
Popconfirm,
Table,
TableColumn,
TabPane,
Tabs,
Tag,
Transfer,
} from 'ant-design-vue';
// ======================= 自定义组件 =======================
import { useApiSelect } from '#/components/form-create';
@@ -29,23 +57,46 @@ const ApiSelect = useApiSelect({
const ImagesUpload = useImagesUpload();
const components = [
ImageUpload,
ImagesUpload,
FileUpload,
Tinymce,
DictSelect,
Alert,
Badge,
Card,
Collapse,
CollapsePanel,
ConfigProvider,
Divider,
Dropdown,
Image,
Layout,
LayoutContent,
LayoutFooter,
LayoutHeader,
LayoutSider,
Menu,
MenuDivider,
MenuItem,
Popconfirm,
Table,
TableColumn,
TabPane,
Tabs,
Tag,
Transfer,
UserSelect,
DeptSelect,
ApiSelect,
ImagesUpload,
DictSelect,
Tinymce,
ImageUpload,
FileUpload,
];
// TODO: @dhb52 按需导入而不是app.use(Antd);
// 参考 http://www.form-create.com/v3/ant-design-vue/auto-import.html 文档
export const setupFormCreate = (app: App) => {
export function setupFormCreate(app: App) {
components.forEach((component) => {
app.component(component.name as string, component);
});
app.use(Antd);
app.component('AMessage', message);
formCreate.use(install);
app.use(formCreate);
app.use(FcDesigner);
app.use(FcDesigner.formCreate);
};
}

View File

@@ -57,7 +57,7 @@ const routes: RouteRecordRaw[] = [
title: '订单详情',
activePath: '/mall/trade/order',
},
component: () => import('#/views/mall/trade/order/modules/detail.vue'),
component: () => import('#/views/mall/trade/order/detail/index.vue'),
},
{
path: String.raw`after-sale/detail/:id(\d+)`,
@@ -67,7 +67,7 @@ const routes: RouteRecordRaw[] = [
activePath: '/mall/trade/after-sale',
},
component: () =>
import('#/views/mall/trade/afterSale/modules/detail.vue'),
import('#/views/mall/trade/afterSale/detail/index.vue'),
},
],
},

View File

@@ -1,59 +0,0 @@
/**
* 针对 https://github.com/xaboy/form-create-designer 封装的工具类
*/
// TODO @芋艿:后续这些 form-create 的优化;另外需要使用 form-create-helper 会好点
import { isRef } from 'vue';
import formCreate from '@form-create/ant-design-vue';
// 编码表单 Conf
export const encodeConf = (designerRef: any) => {
return JSON.stringify(designerRef.value.getOption());
};
// 编码表单 Fields
export const encodeFields = (designerRef: any) => {
const rule = JSON.parse(designerRef.value.getJson());
const fields: string[] = [];
rule.forEach((item: unknown) => {
fields.push(JSON.stringify(item));
});
return fields;
};
// 解码表单 Fields
export const decodeFields = (fields: string[]) => {
const rule: object[] = [];
fields.forEach((item) => {
rule.push(formCreate.parseJson(item));
});
return rule;
};
// 设置表单的 Conf 和 Fields适用 FcDesigner 场景
export const setConfAndFields = (
designerRef: any,
conf: string,
fields: string | string[],
) => {
designerRef.value.setOption(formCreate.parseJson(conf));
// 处理 fields 参数类型,确保传入 decodeFields 的是 string[] 类型
const fieldsArray = Array.isArray(fields) ? fields : [fields];
designerRef.value.setRule(decodeFields(fieldsArray));
};
// 设置表单的 Conf 和 Fields适用 form-create 场景
export const setConfAndFields2 = (
detailPreview: any,
conf: string,
fields: string[],
value?: any,
) => {
if (isRef(detailPreview)) {
detailPreview = detailPreview.value;
}
detailPreview.option = formCreate.parseJson(conf);
detailPreview.rule = decodeFields(fields);
if (value) {
detailPreview.value = value;
}
};

View File

@@ -1,3 +1,2 @@
export * from './formCreate';
export * from './rangePickerProps';
export * from './routerHelper';

View File

@@ -1,45 +1,62 @@
import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
import { $t } from '#/locales';
/** 时间段选择器拓展 */
/** 时间段选择器拓展 */
export function getRangePickerDefaultProps() {
return {
// 设置日期格式,为数组时支持多格式匹配,展示以第一个为准。配置参考 dayjs支持自定义格式
format: 'YYYY-MM-DD HH:mm:ss',
// 绑定值的格式,对 value、defaultValue、defaultPickerValue 起作用。不指定则绑定值为 dayjs 对象
valueFormat: 'YYYY-MM-DD HH:mm:ss',
// 输入框提示文字
placeholder: [
$t('utils.rangePicker.beginTime'),
$t('utils.rangePicker.endTime'),
],
ranges: {
[$t('utils.rangePicker.today')]: () =>
[dayjs().startOf('day'), dayjs().endOf('day')] as [Dayjs, Dayjs],
[$t('utils.rangePicker.last7Days')]: () =>
[dayjs().subtract(7, 'day').startOf('day'), dayjs().endOf('day')] as [
Dayjs,
Dayjs,
// 快捷时间范围
presets: [
{
label: $t('utils.rangePicker.today'),
value: [dayjs().startOf('day'), dayjs().endOf('day')],
},
{
label: $t('utils.rangePicker.last7Days'),
value: [
dayjs().subtract(7, 'day').startOf('day'),
dayjs().endOf('day'),
],
[$t('utils.rangePicker.last30Days')]: () =>
[dayjs().subtract(30, 'day').startOf('day'), dayjs().endOf('day')] as [
Dayjs,
Dayjs,
},
{
label: $t('utils.rangePicker.last30Days'),
value: [
dayjs().subtract(30, 'day').startOf('day'),
dayjs().endOf('day'),
],
[$t('utils.rangePicker.yesterday')]: () =>
[
},
{
label: $t('utils.rangePicker.yesterday'),
value: [
dayjs().subtract(1, 'day').startOf('day'),
dayjs().subtract(1, 'day').endOf('day'),
] as [Dayjs, Dayjs],
[$t('utils.rangePicker.thisWeek')]: () =>
[dayjs().startOf('week'), dayjs().endOf('day')] as [Dayjs, Dayjs],
[$t('utils.rangePicker.thisMonth')]: () =>
[dayjs().startOf('month'), dayjs().endOf('day')] as [Dayjs, Dayjs],
[$t('utils.rangePicker.lastWeek')]: () =>
[dayjs().subtract(1, 'week').startOf('day'), dayjs().endOf('day')] as [
Dayjs,
Dayjs,
],
},
},
{
label: $t('utils.rangePicker.thisWeek'),
value: [dayjs().startOf('week'), dayjs().endOf('day')],
},
{
label: $t('utils.rangePicker.thisMonth'),
value: [dayjs().startOf('month'), dayjs().endOf('day')],
},
{
label: $t('utils.rangePicker.lastWeek'),
value: [
dayjs().subtract(1, 'week').startOf('day'),
dayjs().endOf('day'),
],
},
],
showTime: {
defaultValue: [
dayjs('00:00:00', 'HH:mm:ss'),
@@ -47,14 +64,5 @@ export function getRangePickerDefaultProps() {
],
format: 'HH:mm:ss',
},
transformDateFunc: (dates: any) => {
// TODO @xingyu貌似这个没用
if (dates && dates.length === 2) {
// 格式化为后台支持的时间格式
return [dates.createTime[0], dates.createTime[1]].join(',');
}
return {};
},
valueFormat: 'YYYY-MM-DD HH:mm:ss',
};
}

View File

@@ -6,11 +6,11 @@ const modules = import.meta.glob('../views/**/*.{vue,tsx}');
* 注册一个异步组件
* @param componentPath 例:/bpm/oa/leave/detail
*/
export const registerComponent = (componentPath: string) => {
export function registerComponent(componentPath: string) {
for (const item in modules) {
if (item.includes(componentPath)) {
// 使用异步组件的方式来动态加载组件
return defineAsyncComponent(modules[item] as any);
}
}
};
}

View File

@@ -86,7 +86,7 @@ async function copyContent(content: string) {
message.success('复制成功!');
}
/** 删除 */
async function onDelete(id: number) {
async function handleDelete(id: number) {
// 删除 message
await deleteChatMessage(id);
message.success('删除成功!');
@@ -95,12 +95,12 @@ async function onDelete(id: number) {
}
/** 刷新 */
async function onRefresh(message: AiChatMessageApi.ChatMessage) {
async function handleRefresh(message: AiChatMessageApi.ChatMessage) {
emits('onRefresh', message);
}
/** 编辑 */
async function onEdit(message: AiChatMessageApi.ChatMessage) {
async function handleEdit(message: AiChatMessageApi.ChatMessage) {
emits('onEdit', message);
}
@@ -150,7 +150,7 @@ onMounted(async () => {
v-if="item.id > 0"
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
type="text"
@click="onDelete(item.id)"
@click="handleDelete(item.id)"
>
<IconifyIcon icon="lucide:trash" />
</Button>
@@ -185,21 +185,21 @@ onMounted(async () => {
<Button
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
type="text"
@click="onDelete(item.id)"
@click="handleDelete(item.id)"
>
<IconifyIcon icon="lucide:trash" />
</Button>
<Button
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
type="text"
@click="onRefresh(item)"
@click="handleRefresh(item)"
>
<IconifyIcon icon="lucide:refresh-cw" />
</Button>
<Button
class="flex items-center bg-transparent px-1.5 hover:bg-gray-100"
type="text"
@click="onEdit(item)"
@click="handleEdit(item)"
>
<IconifyIcon icon="lucide:edit" />
</Button>

View File

@@ -24,7 +24,7 @@ import {
const userList = ref<SystemUserApi.User[]>([]); // 用户列表
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -39,7 +39,7 @@ async function handleDelete(row: AiChatConversationApi.ChatConversation) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}

View File

@@ -21,7 +21,7 @@ import { useGridColumnsMessage, useGridFormSchemaMessage } from '../data';
const userList = ref<SystemUserApi.User[]>([]); // 用户列表
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -36,7 +36,7 @@ async function handleDelete(row: AiChatConversationApi.ChatConversation) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}

View File

@@ -19,7 +19,7 @@ import { useGridColumns, useGridFormSchema } from './data';
const userList = ref<SystemUserApi.User[]>([]); // 用户列表
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -34,7 +34,7 @@ async function handleDelete(row: AiImageApi.Image) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -49,7 +49,7 @@ const handleUpdatePublicStatusChange = async (row: AiImageApi.Image) => {
id: row.id,
publicStatus: row.publicStatus,
});
onRefresh();
handleRefresh();
});
} catch {
row.publicStatus = !row.publicStatus;

View File

@@ -10,7 +10,7 @@ import { useRoute, useRouter } from 'vue-router';
import { Page } from '@vben/common-ui';
import { useTabs } from '@vben/hooks';
import { ArrowLeft } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { Card } from 'ant-design-vue';
@@ -135,7 +135,8 @@ defineExpose({
>
<!-- 左侧标题 -->
<div class="flex w-48 items-center overflow-hidden">
<ArrowLeft
<IconifyIcon
icon="lucide:arrow-left"
class="size-5 flex-shrink-0 cursor-pointer"
@click="handleBack"
/>

View File

@@ -28,7 +28,7 @@ const { hasAccessByCodes } = useAccess();
const route = useRoute(); // 路由
const router = useRouter(); // 路由
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -59,7 +59,7 @@ async function handleDelete(row: AiKnowledgeDocumentApi.KnowledgeDocument) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -83,7 +83,7 @@ const handleStatusChange = async (
id: row.id,
status: row.status,
});
onRefresh();
handleRefresh();
});
} catch {
row.status =

View File

@@ -24,7 +24,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -49,7 +49,7 @@ async function handleDelete(row: AiKnowledgeKnowledgeApi.Knowledge) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -106,7 +106,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<template #doc>
<DocAlert title="AI 手册" url="https://doc.iocoder.cn/ai/build/" />
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="AI 知识库列表">
<template #toolbar-tools>
<TableAction

View File

@@ -31,7 +31,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -56,7 +56,7 @@ async function handleDelete(row: AiKnowledgeKnowledgeApi.Knowledge) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -118,7 +118,7 @@ onMounted(() => {
<template>
<Page auto-content-height>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="分段列表">
<template #toolbar-tools>
<TableAction

View File

@@ -26,7 +26,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
destroyOnClose: true,
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -41,7 +41,7 @@ async function handleDelete(row: AiMindmapApi.MindMap) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}

View File

@@ -19,7 +19,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -44,7 +44,7 @@ async function handleDelete(row: AiModelApiKeyApi.ApiKey) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -85,7 +85,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<template #doc>
<DocAlert title="AI 手册" url="https://doc.iocoder.cn/ai/build/" />
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="API 密钥列表">
<template #toolbar-tools>
<TableAction

View File

@@ -19,7 +19,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -44,7 +44,7 @@ async function handleDelete(row: AiModelChatRoleApi.ChatRole) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -85,7 +85,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<template #doc>
<DocAlert title="AI 对话聊天" url="https://doc.iocoder.cn/ai/chat/" />
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="聊天角色列表">
<template #toolbar-tools>
<TableAction

View File

@@ -24,7 +24,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -49,7 +49,7 @@ async function handleDelete(row: AiModelModelApi.Model) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -94,7 +94,7 @@ onMounted(async () => {
<template #doc>
<DocAlert title="AI 手册" url="https://doc.iocoder.cn/ai/build/" />
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="模型配置列表">
<template #toolbar-tools>
<TableAction

View File

@@ -19,7 +19,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -44,7 +44,7 @@ async function handleDelete(row: AiModelToolApi.Tool) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -88,7 +88,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
url="https://doc.iocoder.cn/ai/tool/"
/>
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="工具列表">
<template #toolbar-tools>
<TableAction

View File

@@ -19,7 +19,7 @@ import { useGridColumns, useGridFormSchema } from './data';
const userList = ref<SystemUserApi.User[]>([]); // 用户列表
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -34,7 +34,7 @@ async function handleDelete(row: AiMusicApi.Music) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -49,7 +49,7 @@ const handleUpdatePublicStatusChange = async (row: AiMusicApi.Music) => {
id: row.id,
publicStatus: row.publicStatus,
});
onRefresh();
handleRefresh();
});
} catch {
row.publicStatus = !row.publicStatus;

View File

@@ -5,7 +5,7 @@ import { useRoute, useRouter } from 'vue-router';
import { confirm, Page } from '@vben/common-ui';
import { AiModelTypeEnum, CommonStatusEnum } from '@vben/constants';
import { useTabs } from '@vben/hooks';
import { ArrowLeft } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { Button, Card, message } from 'ant-design-vue';
@@ -212,7 +212,8 @@ onBeforeUnmount(() => {
>
<!-- 左侧标题 -->
<div class="flex w-48 items-center overflow-hidden">
<ArrowLeft
<IconifyIcon
icon="lucide:arrow-left"
class="size-5 flex-shrink-0 cursor-pointer"
@click="handleBack"
/>

View File

@@ -13,7 +13,7 @@ import { router } from '#/router';
import { useGridColumns, useGridFormSchema } from './data';
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -46,7 +46,7 @@ async function handleDelete(row: any) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}

View File

@@ -18,7 +18,7 @@ import { useGridColumns, useGridFormSchema } from './data';
const userList = ref<SystemUserApi.User[]>([]); // 用户列表
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -33,7 +33,7 @@ async function handleDelete(row: AiWriteApi.AiWritePageReq) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}

View File

@@ -19,7 +19,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -44,7 +44,7 @@ async function handleDelete(row: BpmCategoryApi.Category) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.code]),
});
onRefresh();
handleRefresh();
} catch {
hideLoading();
}
@@ -86,7 +86,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" />
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="流程分类">
<template #toolbar-tools>
<TableAction

View File

@@ -8,9 +8,11 @@ import FcDesigner from '@form-create/antd-designer';
import { Button, message } from 'ant-design-vue';
import { getFormDetail } from '#/api/bpm/form';
import { useFormCreateDesigner } from '#/components/form-create';
import {
setConfAndFields,
useFormCreateDesigner,
} from '#/components/form-create';
import { router } from '#/router';
import { setConfAndFields } from '#/utils';
import Form from '#/views/bpm/form/modules/form.vue';
defineOptions({ name: 'BpmFormEditor' });

View File

@@ -20,7 +20,7 @@ import Detail from './modules/detail.vue';
defineOptions({ name: 'BpmForm' });
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -67,7 +67,7 @@ async function handleDelete(row: BpmFormApi.Form) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -121,7 +121,7 @@ watch(
() => route.query.refresh,
(val) => {
if (val === '1') {
onRefresh();
handleRefresh();
}
},
{ immediate: true },

View File

@@ -6,7 +6,7 @@ import { useVbenModal } from '@vben/common-ui';
import FormCreate from '@form-create/ant-design-vue';
import { getFormDetail } from '#/api/bpm/form';
import { setConfAndFields2 } from '#/utils';
import { setConfAndFields2 } from '#/components/form-create';
/** 详情 */
const formConfig = ref<any>({});

View File

@@ -11,8 +11,8 @@ import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { createForm, updateForm } from '#/api/bpm/form';
import { encodeConf, encodeFields } from '#/components/form-create';
import { $t } from '#/locales';
import { encodeConf, encodeFields } from '#/utils';
import { useFormSchema } from '../data';

View File

@@ -23,7 +23,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -48,7 +48,7 @@ async function handleDelete(row: BpmUserGroupApi.UserGroup) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} catch {
hideLoading();
}
@@ -97,7 +97,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<DocAlert title="工作流手册" url="https://doc.iocoder.cn/bpm/" />
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="用户分组">
<template #toolbar-tools>
<TableAction

View File

@@ -46,7 +46,7 @@ async function openModelForm(id?: number) {
}
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -83,7 +83,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
/** 初始化 */
onMounted(() => {
onRefresh();
handleRefresh();
});
</script>

View File

@@ -15,7 +15,7 @@ import {
BpmModelType,
} from '@vben/constants';
import { useTabs } from '@vben/hooks';
import { ArrowLeft } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useUserStore } from '@vben/stores';
import { Button, Card, message } from 'ant-design-vue';
@@ -419,7 +419,8 @@ onBeforeUnmount(() => {
>
<!-- 左侧标题 -->
<div class="flex w-48 items-center overflow-hidden">
<ArrowLeft
<IconifyIcon
icon="lucide:arrow-left"
class="size-5 flex-shrink-0 cursor-pointer"
@click="handleBack"
/>
@@ -455,9 +456,9 @@ onBeforeUnmount(() => {
>
{{ index + 1 }}
</div>
<span class="whitespace-nowrap text-base font-bold">{{
step.title
}}</span>
<span class="whitespace-nowrap text-base font-bold">
{{ step.title }}
</span>
</div>
</div>
</div>

View File

@@ -78,7 +78,7 @@ const rules: Record<string, Rule[]> = {
callback();
return;
}
if (!/^[a-z_][\-\w.$]*$/i.test(value)) {
if (!/^[a-z_][-\w.$]*$/i.test(value)) {
callback(
new Error(
'只能包含字母、数字、下划线、连字符和点号,且必须以字母或下划线开头',
@@ -460,7 +460,6 @@ defineExpose({ validate });
class="w-3/5"
v-model:value="selectedUsers"
:multiple="true"
title="选择用户"
@confirm="handleUserSelectConfirm"
@closed="handleUserSelectClosed"
@cancel="handleUserSelectCancel"
@@ -468,7 +467,6 @@ defineExpose({ validate });
<!-- 部门选择对话框 -->
<DeptSelectModalComp
class="w-3/5"
title="发起人部门选择"
:check-strictly="true"
@confirm="handleDeptSelectConfirm"
/>

View File

@@ -6,7 +6,7 @@ import {
BpmModelFormType,
ProcessVariableEnum,
} from '@vben/constants';
import { CircleHelp } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import {
Checkbox,
@@ -369,7 +369,10 @@ defineExpose({ initData, validate });
title="输入字符 '{' 即可插入表单字段"
placement="top"
>
<CircleHelp class="ml-1 size-4 text-gray-500" />
<IconifyIcon
icon="lucide:circle-help"
class="ml-1 size-4 text-gray-500"
/>
</Tooltip>
</div>
</Radio>

View File

@@ -7,7 +7,7 @@ import { ref, watch } from 'vue';
import { BpmModelFormType, DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { CircleHelp } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import FormCreate from '@form-create/ant-design-vue';
import {
@@ -22,7 +22,7 @@ import {
} from 'ant-design-vue';
import { getFormDetail } from '#/api/bpm/form';
import { setConfAndFields2 } from '#/utils';
import { setConfAndFields2 } from '#/components/form-create';
const props = defineProps({
formList: {
@@ -138,7 +138,10 @@ defineExpose({ validate });
title="自定义表单的提交路径,使用 Vue 的路由地址, 例如说: bpm/oa/leave/create.vue"
placement="top"
>
<CircleHelp class="ml-1 size-5 text-gray-900" />
<IconifyIcon
icon="lucide:circle-help"
class="ml-1 size-5 text-gray-900"
/>
</Tooltip>
</div>
</FormItem>
@@ -157,7 +160,10 @@ defineExpose({ validate });
title="自定义表单的查看组件地址,使用 Vue 的组件地址例如说bpm/oa/leave/detail.vue"
placement="top"
>
<CircleHelp class="ml-1 size-5 text-gray-900" />
<IconifyIcon
icon="lucide:circle-help"
class="ml-1 size-5 text-gray-900"
/>
</Tooltip>
</div>
</FormItem>

View File

@@ -71,7 +71,7 @@ function handleCancel(row: BpmOALeaveApi.Leave) {
try {
await cancelProcessInstanceByStartUser(row.id, scope.value);
message.success('取消成功');
onRefresh();
handleRefresh();
} catch {
return false;
}
@@ -104,7 +104,7 @@ function handleProgress(row: BpmOALeaveApi.Leave) {
}
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
</script>

View File

@@ -22,7 +22,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -47,7 +47,7 @@ async function handleDelete(row: BpmProcessExpressionApi.ProcessExpression) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -92,7 +92,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
/>
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="流程表达式">
<template #toolbar-tools>
<TableAction

View File

@@ -22,8 +22,8 @@ import {
createProcessInstance,
getApprovalDetail as getApprovalDetailApi,
} from '#/api/bpm/processInstance';
import { decodeFields, setConfAndFields2 } from '#/components/form-create';
import { router } from '#/router';
import { decodeFields, setConfAndFields2 } from '#/utils';
import ProcessInstanceSimpleViewer from '#/views/bpm/processInstance/detail/modules/simple-bpm-viewer.vue';
import ProcessInstanceTimeline from '#/views/bpm/processInstance/detail/modules/time-line.vue';

View File

@@ -21,7 +21,8 @@ import {
} from '#/api/bpm/processInstance';
import { getSimpleUserList } from '#/api/system/user';
import DictTag from '#/components/dict-tag/dict-tag.vue';
import { registerComponent, setConfAndFields2 } from '#/utils';
import { setConfAndFields2 } from '#/components/form-create';
import { registerComponent } from '#/utils';
import {
SvgBpmApproveIcon,
SvgBpmCancelIcon,

View File

@@ -43,7 +43,7 @@ import {
} from '#/api/bpm/processInstance';
import * as TaskApi from '#/api/bpm/task';
import * as UserApi from '#/api/system/user';
import { setConfAndFields2 } from '#/utils';
import { setConfAndFields2 } from '#/components/form-create';
import Signature from './signature.vue';
import ProcessInstanceTimeline from './time-line.vue';

View File

@@ -1,8 +1,7 @@
<script setup lang="ts">
import type { formCreate } from '@form-create/antd-designer';
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { BpmTaskApi } from '#/api/bpm/task';
import { nextTick, onMounted, ref, shallowRef } from 'vue';
@@ -15,7 +14,7 @@ import { Button } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getTaskListByProcessInstanceId } from '#/api/bpm/task';
import { setConfAndFields2 } from '#/utils';
import { setConfAndFields2 } from '#/components/form-create';
defineOptions({
name: 'BpmProcessInstanceTaskList',

View File

@@ -22,7 +22,7 @@ import { useGridColumns, useGridFormSchema } from './data';
defineOptions({ name: 'BpmProcessInstanceMy' });
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -43,7 +43,7 @@ function handleCancel(row: BpmTaskApi.Task) {
try {
await cancelProcessInstanceByStartUser(row.id, scope.value);
message.success('取消成功');
onRefresh();
handleRefresh();
} catch {
return false;
}

View File

@@ -22,7 +22,7 @@ import { useGridColumns, useGridFormSchema } from './data';
defineOptions({ name: 'BpmProcessInstanceManager' });
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -50,7 +50,7 @@ function handleCancel(row: BpmProcessInstanceApi.ProcessInstance) {
try {
await cancelProcessInstanceByAdmin(row.id, scope.value);
message.success('取消成功');
onRefresh();
handleRefresh();
} catch {
return false;
}

View File

@@ -62,7 +62,7 @@ const parseFormCreateFields = (formFields?: string[]) => {
};
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
if (gridApi) {
gridApi.query();
}
@@ -97,7 +97,7 @@ const handleCancel = async (row: BpmProcessInstanceApi.ProcessInstance) => {
},
}).then(() => {
message.success('取消成功');
onRefresh();
handleRefresh();
});
};

View File

@@ -22,7 +22,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -47,7 +47,7 @@ async function handleDelete(row: BpmProcessListenerApi.ProcessListener) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} catch {
hideLoading();
}
@@ -92,7 +92,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
/>
</template>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="流程监听器">
<template #toolbar-tools>
<TableAction

View File

@@ -40,7 +40,7 @@ function setCheckedRows({ records }: { records: CrmContractApi.Contract[] }) {
}
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -108,7 +108,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<template>
<div>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid>
<template #toolbar-tools>
<TableAction

View File

@@ -188,4 +188,4 @@ export function useFollowUpDetailSchema(): DescriptionItemSchema[] {
content: (data) => formatDateTime(data?.updateTime) as string,
},
];
}
}

View File

@@ -1,32 +1,17 @@
<script lang="ts" setup>
// TODO @芋艿待定vben2.0 有 CodeEditor不确定官方后续会不会迁移
import type { InfraCodegenApi } from '#/api/infra/codegen';
import { h, ref } from 'vue';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { Copy } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { CodeEditor } from '@vben/plugins/code-editor';
import { useClipboard } from '@vueuse/core';
import { Button, DirectoryTree, message, Tabs } from 'ant-design-vue';
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';
import { previewCodegen } from '#/api/infra/codegen';
/** 注册代码高亮语言 */
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;
@@ -44,21 +29,14 @@ const activeKey = ref<string>('');
/** 代码地图 */
const codeMap = ref<Map<string, string>>(new Map<string, string>());
function setCodeMap(key: string, lang: string, code: string) {
function setCodeMap(key: string, code: string) {
// 处理可能的缩进问题特别是对Java文件
const trimmedCode = code.trimStart();
// 如果已有缓存则不重新构建
if (codeMap.value.has(key)) {
return;
}
try {
const highlightedCode = hljs.highlight(trimmedCode, {
language: lang,
}).value;
codeMap.value.set(key, highlightedCode);
} catch {
codeMap.value.set(key, trimmedCode);
}
codeMap.value.set(key, trimmedCode);
}
/** 删除代码地图 */
@@ -104,8 +82,7 @@ function handleNodeClick(_: any[], e: any) {
return;
}
const lang = file.filePath.split('.').pop() || '';
setCodeMap(activeKey.value, lang, file.code);
setCodeMap(activeKey.value, file.code);
}
/** 处理文件树 */
@@ -220,9 +197,8 @@ const [Modal, modalApi] = useVbenModal({
fileTree.value = handleFiles(data);
if (data.length > 0) {
activeKey.value = data[0]?.filePath || '';
const lang = activeKey.value.split('.').pop() || '';
const code = data[0]?.code || '';
setCodeMap(activeKey.value, lang, code);
setCodeMap(activeKey.value, code);
}
} finally {
loading.value = false;
@@ -262,15 +238,19 @@ const [Modal, modalApi] = useVbenModal({
<div
class="h-full rounded-md bg-gray-50 !p-0 text-gray-800 dark:bg-gray-800 dark:text-gray-200"
>
<!-- eslint-disable-next-line vue/no-v-html -->
<code
v-html="codeMap.get(activeKey)"
class="code-highlight"
></code>
<CodeEditor
class="max-h-200"
:value="codeMap.get(activeKey)"
mode="application/json"
:readonly="true"
:bordered="true"
:auto-format="false"
/>
</div>
</Tabs.TabPane>
<template #rightExtra>
<Button type="primary" ghost @click="copyCode" :icon="h(Copy)">
<Button type="primary" ghost @click="copyCode">
<IconifyIcon icon="lucide:copy" />
复制代码
</Button>
</template>
@@ -279,101 +259,3 @@ const [Modal, modalApi] = useVbenModal({
</div>
</Modal>
</template>
<style scoped>
/* stylelint-disable selector-class-pattern */
/* 代码高亮样式 - 支持暗黑模式 */
:deep(.code-highlight) {
display: block;
white-space: pre;
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;
}
/* stylelint-enable selector-class-pattern */
</style>

View File

@@ -1,9 +1,9 @@
<script lang="ts" setup>
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/inner';
import { h, nextTick, watch } from 'vue';
import { nextTick, watch } from 'vue';
import { Plus } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { Button, Input } from 'ant-design-vue';
@@ -108,12 +108,12 @@ watch(
</Grid>
<div class="-mt-4 flex justify-center">
<Button
:icon="h(Plus)"
type="primary"
ghost
@click="handleAdd"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生课程']) }}
</Button>
</div>

View File

@@ -1,9 +1,9 @@
<script lang="ts" setup>
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
import { h, nextTick, watch } from 'vue';
import { nextTick, watch } from 'vue';
import { Plus } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { Button, Input } from 'ant-design-vue';
@@ -107,12 +107,12 @@ watch(
</Grid>
<div class="-mt-4 flex justify-center">
<Button
:icon="h(Plus)"
type="primary"
ghost
@click="handleAdd"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生课程']) }}
</Button>
</div>

View File

@@ -1,12 +1,12 @@
<script lang="ts" setup>
import type { Demo01ContactApi } from '#/api/infra/demo/demo01';
import { h, onMounted, reactive, ref } from 'vue';
import { onMounted, reactive, ref } from 'vue';
import { ContentWrap, Page, useVbenModal } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { Download, Plus, Trash2 } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
import {
cloneDeep,
@@ -141,7 +141,7 @@ function handleRowCheckboxChange({
}
/** 导出表格 */
async function onExport() {
async function handleExport() {
try {
exportLoading.value = true;
const data = await exportDemo01Contact(queryParams);
@@ -218,25 +218,24 @@ onMounted(() => {
>
<Button
class="ml-2"
:icon="h(Plus)"
type="primary"
@click="handleCreate"
v-access:code="['infra:demo01-contact:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['示例联系人']) }}
</Button>
<Button
:icon="h(Download)"
type="primary"
class="ml-2"
:loading="exportLoading"
@click="onExport"
@click="handleExport"
v-access:code="['infra:demo01-contact:export']"
>
<IconifyIcon icon="lucide:download" />
{{ $t('ui.actionTitle.export') }}
</Button>
<Button
:icon="h(Trash2)"
type="primary"
danger
class="ml-2"
@@ -244,6 +243,7 @@ onMounted(() => {
@click="handleDeleteBatch"
v-access:code="['infra:demo01-contact:delete']"
>
<IconifyIcon icon="lucide:trash-2" />
批量删除
</Button>
</VbenVxeTableToolbar>

View File

@@ -1,10 +1,10 @@
<script lang="ts" setup>
import type { Demo02CategoryApi } from '#/api/infra/demo/demo02';
import { h, onMounted, reactive, ref } from 'vue';
import { onMounted, reactive, ref } from 'vue';
import { ContentWrap, Page, useVbenModal } from '@vben/common-ui';
import { Download, Plus } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
import {
cloneDeep,
@@ -68,22 +68,22 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 创建示例分类 */
function onCreate() {
function handleCreate() {
formModalApi.setData(null).open();
}
/** 编辑示例分类 */
function onEdit(row: Demo02CategoryApi.Demo02Category) {
function handleEdit(row: Demo02CategoryApi.Demo02Category) {
formModalApi.setData(row).open();
}
/** 新增下级示例分类 */
function onAppend(row: Demo02CategoryApi.Demo02Category) {
function handleAppend(row: Demo02CategoryApi.Demo02Category) {
formModalApi.setData({ parentId: row.id }).open();
}
/** 删除示例分类 */
async function onDelete(row: Demo02CategoryApi.Demo02Category) {
async function handleDelete(row: Demo02CategoryApi.Demo02Category) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.id]),
duration: 0,
@@ -100,7 +100,7 @@ async function onDelete(row: Demo02CategoryApi.Demo02Category) {
}
/** 导出表格 */
async function onExport() {
async function handleExport() {
try {
exportLoading.value = true;
const data = await exportDemo02Category(queryParams);
@@ -177,21 +177,21 @@ onMounted(() => {
</Button>
<Button
class="ml-2"
:icon="h(Plus)"
type="primary"
@click="onCreate"
@click="handleCreate"
v-access:code="['infra:demo02-category:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['示例分类']) }}
</Button>
<Button
:icon="h(Download)"
type="primary"
class="ml-2"
:loading="exportLoading"
@click="onExport"
@click="handleExport"
v-access:code="['infra:demo02-category:export']"
>
<IconifyIcon icon="lucide:download" />
{{ $t('ui.actionTitle.export') }}
</Button>
</VbenVxeTableToolbar>
@@ -222,7 +222,7 @@ onMounted(() => {
<Button
size="small"
type="link"
@click="onAppend(row)"
@click="handleAppend(row)"
v-access:code="['infra:demo02-category:create']"
>
新增下级
@@ -230,7 +230,7 @@ onMounted(() => {
<Button
size="small"
type="link"
@click="onEdit(row)"
@click="handleEdit(row)"
v-access:code="['infra:demo02-category:update']"
>
{{ $t('ui.actionTitle.edit') }}
@@ -241,7 +241,7 @@ onMounted(() => {
danger
class="ml-2"
:disabled="!isEmpty(row.children)"
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo02-category:delete']"
>
{{ $t('ui.actionTitle.delete') }}

View File

@@ -1,12 +1,12 @@
<script lang="ts" setup>
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
import { h, onMounted, reactive, ref } from 'vue';
import { onMounted, reactive, ref } from 'vue';
import { ContentWrap, Page, useVbenModal } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { Download, Plus, Trash2 } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
import {
cloneDeep,
@@ -97,17 +97,17 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 创建学生 */
function onCreate() {
function handleCreate() {
formModalApi.setData(null).open();
}
/** 编辑学生 */
function onEdit(row: Demo03StudentApi.Demo03Student) {
function handleEdit(row: Demo03StudentApi.Demo03Student) {
formModalApi.setData(row).open();
}
/** 删除学生 */
async function onDelete(row: Demo03StudentApi.Demo03Student) {
async function handleDelete(row: Demo03StudentApi.Demo03Student) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.id]),
duration: 0,
@@ -126,7 +126,7 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
}
/** 批量删除学生 */
async function onDeleteBatch() {
async function handleDeleteBatch() {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting'),
duration: 0,
@@ -152,7 +152,7 @@ function handleRowCheckboxChange({
}
/** 导出表格 */
async function onExport() {
async function handleExport() {
try {
exportLoading.value = true;
const data = await exportDemo03Student(queryParams);
@@ -229,32 +229,32 @@ onMounted(() => {
>
<Button
class="ml-2"
:icon="h(Plus)"
type="primary"
@click="onCreate"
@click="handleCreate"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生']) }}
</Button>
<Button
:icon="h(Download)"
type="primary"
class="ml-2"
:loading="exportLoading"
@click="onExport"
@click="handleExport"
v-access:code="['infra:demo03-student:export']"
>
<IconifyIcon icon="lucide:download" />
{{ $t('ui.actionTitle.export') }}
</Button>
<Button
:icon="h(Trash2)"
type="primary"
danger
class="ml-2"
:disabled="isEmpty(checkedIds)"
@click="onDeleteBatch"
@click="handleDeleteBatch"
v-access:code="['infra:demo03-student:delete']"
>
<IconifyIcon icon="lucide:trash-2" />
批量删除
</Button>
</VbenVxeTableToolbar>
@@ -297,7 +297,7 @@ onMounted(() => {
<Button
size="small"
type="link"
@click="onEdit(row)"
@click="handleEdit(row)"
v-access:code="['infra:demo03-student:update']"
>
{{ $t('ui.actionTitle.edit') }}
@@ -307,7 +307,7 @@ onMounted(() => {
type="link"
danger
class="ml-2"
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo03-student:delete']"
>
{{ $t('ui.actionTitle.delete') }}

View File

@@ -1,10 +1,10 @@
<script lang="ts" setup>
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
import { h, nextTick, onMounted, reactive, ref, watch } from 'vue';
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
import { ContentWrap, useVbenModal } from '@vben/common-ui';
import { Plus, Trash2 } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
import { cloneDeep, formatDateTime, isEmpty } from '@vben/utils';
@@ -38,7 +38,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 创建学生课程 */
function onCreate() {
function handleCreate() {
if (!props.studentId) {
message.warning('请先选择一个学生!');
return;
@@ -47,12 +47,12 @@ function onCreate() {
}
/** 编辑学生课程 */
function onEdit(row: Demo03StudentApi.Demo03Course) {
function handleEdit(row: Demo03StudentApi.Demo03Course) {
formModalApi.setData(row).open();
}
/** 删除学生课程 */
async function onDelete(row: Demo03StudentApi.Demo03Course) {
async function handleDelete(row: Demo03StudentApi.Demo03Course) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.id]),
duration: 0,
@@ -71,7 +71,7 @@ async function onDelete(row: Demo03StudentApi.Demo03Course) {
}
/** 批量删除学生课程 */
async function onDeleteBatch() {
async function handleDeleteBatch() {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting'),
duration: 0,
@@ -218,22 +218,22 @@ onMounted(() => {
>
<Button
class="ml-2"
:icon="h(Plus)"
type="primary"
@click="onCreate"
@click="handleCreate"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生']) }}
</Button>
<Button
:icon="h(Trash2)"
type="primary"
danger
class="ml-2"
:disabled="isEmpty(checkedIds)"
@click="onDeleteBatch"
@click="handleDeleteBatch"
v-access:code="['infra:demo03-student:delete']"
>
<IconifyIcon icon="lucide:trash-2" />
批量删除
</Button>
</VbenVxeTableToolbar>
@@ -261,7 +261,7 @@ onMounted(() => {
<Button
size="small"
type="link"
@click="onEdit(row)"
@click="handleEdit(row)"
v-access:code="['infra:demo03-student:update']"
>
{{ $t('ui.actionTitle.edit') }}
@@ -271,7 +271,7 @@ onMounted(() => {
type="link"
danger
class="ml-2"
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo03-student:delete']"
>
{{ $t('ui.actionTitle.delete') }}

View File

@@ -1,10 +1,10 @@
<script lang="ts" setup>
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
import { h, nextTick, onMounted, reactive, ref, watch } from 'vue';
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
import { ContentWrap, useVbenModal } from '@vben/common-ui';
import { Plus, Trash2 } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
import { cloneDeep, formatDateTime, isEmpty } from '@vben/utils';
@@ -38,7 +38,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 创建学生班级 */
function onCreate() {
function handleCreate() {
if (!props.studentId) {
message.warning('请先选择一个学生!');
return;
@@ -47,12 +47,12 @@ function onCreate() {
}
/** 编辑学生班级 */
function onEdit(row: Demo03StudentApi.Demo03Grade) {
function handleEdit(row: Demo03StudentApi.Demo03Grade) {
formModalApi.setData(row).open();
}
/** 删除学生班级 */
async function onDelete(row: Demo03StudentApi.Demo03Grade) {
async function handleDelete(row: Demo03StudentApi.Demo03Grade) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.id]),
duration: 0,
@@ -71,7 +71,7 @@ async function onDelete(row: Demo03StudentApi.Demo03Grade) {
}
/** 批量删除学生班级 */
async function onDeleteBatch() {
async function handleDeleteBatch() {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting'),
duration: 0,
@@ -218,22 +218,22 @@ onMounted(() => {
>
<Button
class="ml-2"
:icon="h(Plus)"
type="primary"
@click="onCreate"
@click="handleCreate"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生']) }}
</Button>
<Button
:icon="h(Trash2)"
type="primary"
danger
class="ml-2"
:disabled="isEmpty(checkedIds)"
@click="onDeleteBatch"
@click="handleDeleteBatch"
v-access:code="['infra:demo03-student:delete']"
>
<IconifyIcon icon="lucide:trash-2" />
批量删除
</Button>
</VbenVxeTableToolbar>
@@ -261,7 +261,7 @@ onMounted(() => {
<Button
size="small"
type="link"
@click="onEdit(row)"
@click="handleEdit(row)"
v-access:code="['infra:demo03-student:update']"
>
{{ $t('ui.actionTitle.edit') }}
@@ -271,7 +271,7 @@ onMounted(() => {
type="link"
danger
class="ml-2"
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo03-student:delete']"
>
{{ $t('ui.actionTitle.delete') }}

View File

@@ -1,12 +1,12 @@
<script lang="ts" setup>
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
import { h, onMounted, reactive, ref } from 'vue';
import { onMounted, reactive, ref } from 'vue';
import { ContentWrap, Page, useVbenModal } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { Download, Plus, Trash2 } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
import {
cloneDeep,
@@ -93,27 +93,25 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 创建学生 */
function onCreate() {
function handleCreate() {
formModalApi.setData(null).open();
}
/** 编辑学生 */
function onEdit(row: Demo03StudentApi.Demo03Student) {
function handleEdit(row: Demo03StudentApi.Demo03Student) {
formModalApi.setData(row).open();
}
/** 删除学生 */
async function onDelete(row: Demo03StudentApi.Demo03Student) {
async function handleDelete(row: Demo03StudentApi.Demo03Student) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.id]),
duration: 0,
key: 'action_process_msg',
});
try {
await deleteDemo03Student(row.id!);
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
key: 'action_process_msg',
});
await getList();
} finally {
@@ -122,11 +120,10 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
}
/** 批量删除学生 */
async function onDeleteBatch() {
async function handleDeleteBatch() {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting'),
duration: 0,
key: 'action_process_msg',
});
try {
await deleteDemo03StudentList(checkedIds.value);
@@ -148,7 +145,7 @@ function handleRowCheckboxChange({
}
/** 导出表格 */
async function onExport() {
async function handleExport() {
try {
exportLoading.value = true;
const data = await exportDemo03Student(queryParams);
@@ -225,32 +222,32 @@ onMounted(() => {
>
<Button
class="ml-2"
:icon="h(Plus)"
type="primary"
@click="onCreate"
@click="handleCreate"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生']) }}
</Button>
<Button
:icon="h(Download)"
type="primary"
class="ml-2"
:loading="exportLoading"
@click="onExport"
@click="handleExport"
v-access:code="['infra:demo03-student:export']"
>
<IconifyIcon icon="lucide:download" />
{{ $t('ui.actionTitle.export') }}
</Button>
<Button
:icon="h(Trash2)"
type="primary"
danger
class="ml-2"
:disabled="isEmpty(checkedIds)"
@click="onDeleteBatch"
@click="handleDeleteBatch"
v-access:code="['infra:demo03-student:delete']"
>
<IconifyIcon icon="lucide:trash-2" />
批量删除
</Button>
</VbenVxeTableToolbar>
@@ -301,7 +298,7 @@ onMounted(() => {
<Button
size="small"
type="link"
@click="onEdit(row)"
@click="handleEdit(row)"
v-access:code="['infra:demo03-student:update']"
>
{{ $t('ui.actionTitle.edit') }}
@@ -311,7 +308,7 @@ onMounted(() => {
type="link"
danger
class="ml-2"
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo03-student:delete']"
>
{{ $t('ui.actionTitle.delete') }}

View File

@@ -1,11 +1,10 @@
<script lang="ts" setup>
import type { VxeTableInstance } from '@vben/plugins/vxe-table';
import type { VxeTableInstance } from '#/adapter/vxe-table';
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
import { h, ref, watch } from 'vue';
import { ref, watch } from 'vue';
import { Plus } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { Button, Input } from 'ant-design-vue';
@@ -25,7 +24,7 @@ async function onAdd() {
}
/** 删除学生课程 */
async function onDelete(row: Demo03StudentApi.Demo03Course) {
async function handleDelete(row: Demo03StudentApi.Demo03Course) {
await tableRef.value?.remove(row);
}
@@ -74,7 +73,7 @@ watch(
size="small"
type="link"
danger
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo03-student:delete']"
>
{{ $t('ui.actionTitle.delete') }}
@@ -84,12 +83,12 @@ watch(
</VxeTable>
<div class="mt-4 flex justify-center">
<Button
:icon="h(Plus)"
type="primary"
ghost
@click="onAdd"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生课程']) }}
</Button>
</div>

View File

@@ -1,12 +1,12 @@
<script lang="ts" setup>
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
import { h, onMounted, reactive, ref } from 'vue';
import { onMounted, reactive, ref } from 'vue';
import { ContentWrap, Page, useVbenModal } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
import { Download, Plus, Trash2 } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { useTableToolbar, VbenVxeTableToolbar } from '@vben/plugins/vxe-table';
import {
cloneDeep,
@@ -87,17 +87,17 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 创建学生 */
function onCreate() {
function handleCreate() {
formModalApi.setData(null).open();
}
/** 编辑学生 */
function onEdit(row: Demo03StudentApi.Demo03Student) {
function handle(row: Demo03StudentApi.Demo03Student) {
formModalApi.setData(row).open();
}
/** 删除学生 */
async function onDelete(row: Demo03StudentApi.Demo03Student) {
async function handleDelete(row: Demo03StudentApi.Demo03Student) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.id]),
duration: 0,
@@ -116,7 +116,7 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
}
/** 批量删除学生 */
async function onDeleteBatch() {
async function handleDeleteBatch() {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting'),
duration: 0,
@@ -142,7 +142,7 @@ function handleRowCheckboxChange({
}
/** 导出表格 */
async function onExport() {
async function handleExport() {
try {
exportLoading.value = true;
const data = await exportDemo03Student(queryParams);
@@ -219,32 +219,32 @@ onMounted(() => {
>
<Button
class="ml-2"
:icon="h(Plus)"
type="primary"
@click="onCreate"
@click="handleCreate"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生']) }}
</Button>
<Button
:icon="h(Download)"
type="primary"
class="ml-2"
:loading="exportLoading"
@click="onExport"
@click="handleExport"
v-access:code="['infra:demo03-student:export']"
>
<IconifyIcon icon="lucide:download" />
{{ $t('ui.actionTitle.export') }}
</Button>
<Button
:icon="h(Trash2)"
type="primary"
danger
class="ml-2"
:disabled="isEmpty(checkedIds)"
@click="onDeleteBatch"
@click="handleDeleteBatch"
v-access:code="['infra:demo03-student:delete']"
>
<IconifyIcon icon="lucide:trash-2" />
批量删除
</Button>
</VbenVxeTableToolbar>
@@ -281,7 +281,7 @@ onMounted(() => {
<Button
size="small"
type="link"
@click="onEdit(row)"
@click="handle(row)"
v-access:code="['infra:demo03-student:update']"
>
{{ $t('ui.actionTitle.edit') }}
@@ -291,7 +291,7 @@ onMounted(() => {
type="link"
danger
class="ml-2"
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo03-student:delete']"
>
{{ $t('ui.actionTitle.delete') }}

View File

@@ -2,9 +2,9 @@
import type { VxeTableInstance } from '#/adapter/vxe-table';
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
import { h, ref, watch } from 'vue';
import { ref, watch } from 'vue';
import { Plus } from '@vben/icons';
import { IconifyIcon } from '@vben/icons';
import { Button, Input } from 'ant-design-vue';
@@ -24,7 +24,7 @@ async function onAdd() {
}
/** 删除学生课程 */
async function onDelete(row: Demo03StudentApi.Demo03Course) {
async function handleDelete(row: Demo03StudentApi.Demo03Course) {
await tableRef.value?.remove(row);
}
@@ -73,7 +73,7 @@ watch(
size="small"
type="link"
danger
@click="onDelete(row)"
@click="handleDelete(row)"
v-access:code="['infra:demo03-student:delete']"
>
{{ $t('ui.actionTitle.delete') }}
@@ -83,12 +83,12 @@ watch(
</VxeTable>
<div class="mt-4 flex justify-center">
<Button
:icon="h(Plus)"
type="primary"
ghost
@click="onAdd"
v-access:code="['infra:demo03-student:create']"
>
<IconifyIcon icon="lucide:plus" />
{{ $t('ui.actionTitle.create', ['学生课程']) }}
</Button>
</div>

View File

@@ -76,15 +76,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
field: 'size',
title: '文件大小',
minWidth: 80,
formatter: ({ cellValue }) => {
// TODO @xingyu【优先级中】要不要搞到一个方法里
if (!cellValue) return '0 B';
const unitArr = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const index = Math.floor(Math.log(cellValue) / Math.log(1024));
const size = cellValue / 1024 ** index;
const formattedSize = size.toFixed(2);
return `${formattedSize} ${unitArr[index]}`;
},
formatter: 'formatFileSize',
},
{
field: 'type',

View File

@@ -21,7 +21,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -82,7 +82,7 @@ async function handleDelete(row: AlertConfigApi.AlertConfig) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -121,7 +121,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<template>
<Page auto-content-height>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="告警配置列表">
<template #toolbar-tools>
<TableAction

View File

@@ -22,7 +22,7 @@ const productList = ref<any[]>([]);
const deviceList = ref<any[]>([]);
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -101,7 +101,7 @@ async function handleProcess(row: AlertRecord) {
try {
await processAlertRecord(row.id as number, processRemark);
message.success('处理成功');
onRefresh();
handleRefresh();
} catch (error) {
console.error('处理失败:', error);
throw error;

View File

@@ -22,7 +22,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -47,7 +47,7 @@ async function handleDelete(row: IotDeviceGroupApi.DeviceGroup) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -97,7 +97,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<template>
<Page auto-content-height>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="设备分组列表">
<template #toolbar-tools>
<TableAction

View File

@@ -22,7 +22,7 @@ const [FormModal, formModalApi] = useVbenModal({
});
/** 刷新表格 */
function onRefresh() {
function handleRefresh() {
gridApi.query();
}
@@ -52,7 +52,7 @@ async function handleDelete(row: IoTOtaFirmwareApi.Firmware) {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
});
onRefresh();
handleRefresh();
} finally {
hideLoading();
}
@@ -91,7 +91,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<template>
<Page auto-content-height>
<FormModal @success="onRefresh" />
<FormModal @success="handleRefresh" />
<Grid table-title="固件列表">
<template #toolbar-tools>
<TableAction

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