commit
db3b1d7210
|
|
@ -1,3 +1,4 @@
|
||||||
|
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
@ -63,7 +64,7 @@ setupVbenVxeTable({
|
||||||
round: true,
|
round: true,
|
||||||
showOverflow: true,
|
showOverflow: true,
|
||||||
size: 'small',
|
size: 'small',
|
||||||
},
|
} as VxeTableGridOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||||
|
|
@ -74,6 +75,16 @@ setupVbenVxeTable({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
vxeUI.renderer.add('CellImages', {
|
||||||
|
renderTableDefault(_renderOpts, params) {
|
||||||
|
const { column, row } = params;
|
||||||
|
if (column && column.field && row[column.field]) {
|
||||||
|
return row[column.field].map((item: any) => h(Image, { src: item }));
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
vxeUI.renderer.add('CellLink', {
|
vxeUI.renderer.add('CellLink', {
|
||||||
renderTableDefault(renderOpts) {
|
renderTableDefault(renderOpts) {
|
||||||
|
|
@ -267,6 +278,38 @@ setupVbenVxeTable({
|
||||||
|
|
||||||
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||||
// vxeUI.formats.add
|
// vxeUI.formats.add
|
||||||
|
|
||||||
|
vxeUI.formats.add('formatPast2', {
|
||||||
|
tableCellFormatMethod({ cellValue }) {
|
||||||
|
if (cellValue === null || cellValue === undefined) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// 定义时间单位常量,便于维护
|
||||||
|
const SECOND = 1000;
|
||||||
|
const MINUTE = 60 * SECOND;
|
||||||
|
const HOUR = 60 * MINUTE;
|
||||||
|
const DAY = 24 * HOUR;
|
||||||
|
|
||||||
|
// 计算各时间单位
|
||||||
|
const day = Math.floor(cellValue / DAY);
|
||||||
|
const hour = Math.floor((cellValue % DAY) / HOUR);
|
||||||
|
const minute = Math.floor((cellValue % HOUR) / MINUTE);
|
||||||
|
const second = Math.floor((cellValue % MINUTE) / SECOND);
|
||||||
|
|
||||||
|
// 根据时间长短返回不同格式
|
||||||
|
if (day > 0) {
|
||||||
|
return `${day} 天${hour} 小时 ${minute} 分钟`;
|
||||||
|
}
|
||||||
|
if (hour > 0) {
|
||||||
|
return `${hour} 小时 ${minute} 分钟`;
|
||||||
|
}
|
||||||
|
if (minute > 0) {
|
||||||
|
return `${minute} 分钟`;
|
||||||
|
}
|
||||||
|
return second > 0 ? `${second} 秒` : `${0} 秒`;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// add by 星语:数量格式化,例如说:金额
|
// add by 星语:数量格式化,例如说:金额
|
||||||
vxeUI.formats.add('formatNumber', {
|
vxeUI.formats.add('formatNumber', {
|
||||||
tableCellFormatMethod({ cellValue }, digits = 2) {
|
tableCellFormatMethod({ cellValue }, digits = 2) {
|
||||||
|
|
@ -284,7 +327,7 @@ setupVbenVxeTable({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
vxeUI.formats.add('formatFraction', {
|
vxeUI.formats.add('formatAmount2', {
|
||||||
tableCellFormatMethod({ cellValue }) {
|
tableCellFormatMethod({ cellValue }) {
|
||||||
if (cellValue === null || cellValue === undefined) {
|
if (cellValue === null || cellValue === undefined) {
|
||||||
return '0.00';
|
return '0.00';
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmCategoryApi {
|
export namespace BpmCategoryApi {
|
||||||
/** BPM 流程分类 VO */
|
/** 流程分类 VO */
|
||||||
|
// TODO @jason:不用 VO 后缀哈
|
||||||
export interface CategoryVO {
|
export interface CategoryVO {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
/** 流程定义 */
|
|
||||||
export namespace BpmProcessDefinitionApi {
|
export namespace BpmProcessDefinitionApi {
|
||||||
// 流程定义
|
/** 流程定义 */
|
||||||
|
// TODO @ziye:不用 VO 后缀哈
|
||||||
export interface ProcessDefinitionVO {
|
export interface ProcessDefinitionVO {
|
||||||
id: string;
|
id: string;
|
||||||
version: number;
|
version: number;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmFormApi {
|
export namespace BpmFormApi {
|
||||||
// 流程表单
|
/** 流程表单 */
|
||||||
|
// TODO @jason:不用 VO 后缀哈
|
||||||
export interface FormVO {
|
export interface FormVO {
|
||||||
id?: number | undefined;
|
id?: number | undefined;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -23,6 +24,7 @@ export async function getFormPage(params: PageParam) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取表单详情 */
|
/** 获取表单详情 */
|
||||||
|
// TODO @ziye:应该不会 string 的情况呢。
|
||||||
export async function getFormDetail(id: number | string) {
|
export async function getFormDetail(id: number | string) {
|
||||||
return requestClient.get<BpmFormApi.FormVO>(`/bpm/form/get?id=${id}`);
|
return requestClient.get<BpmFormApi.FormVO>(`/bpm/form/get?id=${id}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export namespace BpmModelApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 流程定义 VO */
|
/** 流程定义 VO */
|
||||||
|
// TODO @jason:不用 VO 后缀哈
|
||||||
export interface ProcessDefinitionVO {
|
export interface ProcessDefinitionVO {
|
||||||
id: string;
|
id: string;
|
||||||
key?: string;
|
key?: string;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmOALeaveApi {
|
export namespace BpmOALeaveApi {
|
||||||
|
// TODO @ziye:不用 VO 后缀
|
||||||
export interface LeaveVO {
|
export interface LeaveVO {
|
||||||
id: number;
|
id: number;
|
||||||
status: number;
|
status: number;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmProcessExpressionApi {
|
export namespace BpmProcessExpressionApi {
|
||||||
/** BPM 流程表达式 VO */
|
// TODO @ziye:不用 VO 后缀
|
||||||
|
/** 流程表达式 VO */
|
||||||
export interface ProcessExpressionVO {
|
export interface ProcessExpressionVO {
|
||||||
id: number; // 编号
|
id: number; // 编号
|
||||||
name: string; // 表达式名字
|
name: string; // 表达式名字
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import type { BpmCandidateStrategyEnum, BpmNodeTypeEnum } from '#/utils';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmProcessInstanceApi {
|
export namespace BpmProcessInstanceApi {
|
||||||
|
// TODO @芋艿:一些注释缺少或者不对;
|
||||||
export type Task = {
|
export type Task = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -42,7 +43,7 @@ export namespace BpmProcessInstanceApi {
|
||||||
tasks: ApprovalTaskInfo[];
|
tasks: ApprovalTaskInfo[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 流程实例
|
/** 流程实例 */
|
||||||
export type ProcessInstanceVO = {
|
export type ProcessInstanceVO = {
|
||||||
businessKey: string;
|
businessKey: string;
|
||||||
category: string;
|
category: string;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmProcessListenerApi {
|
export namespace BpmProcessListenerApi {
|
||||||
|
// TODO @ziye:不用 VO 后缀
|
||||||
/** BPM 流程监听器 VO */
|
/** BPM 流程监听器 VO */
|
||||||
export interface ProcessListenerVO {
|
export interface ProcessListenerVO {
|
||||||
id: number; // 编号
|
id: number; // 编号
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import type { BpmProcessInstanceApi } from '../processInstance';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmTaskApi {
|
export namespace BpmTaskApi {
|
||||||
|
// TODO @ziye:不用 VO 后缀;注释使用 /** */ 风格;
|
||||||
/** BPM 流程监听器 VO */
|
/** BPM 流程监听器 VO */
|
||||||
export interface TaskVO {
|
export interface TaskVO {
|
||||||
id: number; // 编号
|
id: number; // 编号
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace BpmUserGroupApi {
|
export namespace BpmUserGroupApi {
|
||||||
|
// TODO @ziye:不用 VO 后缀
|
||||||
/** BPM 用户组 VO */
|
/** BPM 用户组 VO */
|
||||||
export interface UserGroupVO {
|
export interface UserGroupVO {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,7 @@ export function deleteDemo01Contact(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除示例联系人 */
|
/** 批量删除示例联系人 */
|
||||||
// TODO @puhui999:ByIds,这种按照约定,是不带的,针对 Id 的情况哈。
|
export function deleteDemo01ContactList(ids: number[]) {
|
||||||
export function deleteDemo01ContactListByIds(ids: number[]) {
|
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo01-contact/delete-list?ids=${ids.join(',')}`,
|
`/infra/demo01-contact/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ export function deleteDemo03Student(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除学生 */
|
/** 批量删除学生 */
|
||||||
export function deleteDemo03StudentListByIds(ids: number[]) {
|
export function deleteDemo03StudentList(ids: number[]) {
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo03-student-erp/delete-list?ids=${ids.join(',')}`,
|
`/infra/demo03-student-erp/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
|
|
@ -109,7 +109,7 @@ export function deleteDemo03Course(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除学生课程 */
|
/** 批量删除学生课程 */
|
||||||
export function deleteDemo03CourseListByIds(ids: number[]) {
|
export function deleteDemo03CourseList(ids: number[]) {
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo03-student-erp/demo03-course/delete-list?ids=${ids.join(',')}`,
|
`/infra/demo03-student-erp/demo03-course/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
|
|
@ -155,7 +155,7 @@ export function deleteDemo03Grade(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除学生班级 */
|
/** 批量删除学生班级 */
|
||||||
export function deleteDemo03GradeListByIds(ids: number[]) {
|
export function deleteDemo03GradeList(ids: number[]) {
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo03-student-erp/demo03-grade/delete-list?ids=${ids.join(',')}`,
|
`/infra/demo03-student-erp/demo03-grade/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ export function deleteDemo03Student(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除学生 */
|
/** 批量删除学生 */
|
||||||
export function deleteDemo03StudentListByIds(ids: number[]) {
|
export function deleteDemo03StudentList(ids: number[]) {
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo03-student-inner/delete-list?ids=${ids.join(',')}`,
|
`/infra/demo03-student-inner/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ export function deleteDemo03Student(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 批量删除学生 */
|
/** 批量删除学生 */
|
||||||
export function deleteDemo03StudentListByIds(ids: number[]) {
|
export function deleteDemo03StudentList(ids: number[]) {
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo03-student-normal/delete-list?ids=${ids.join(',')}`,
|
`/infra/demo03-student-normal/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBannerApi {
|
||||||
|
/** Banner 信息 */
|
||||||
|
export interface Banner {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
picUrl: string;
|
||||||
|
status: number;
|
||||||
|
url: string;
|
||||||
|
position: number;
|
||||||
|
sort: number;
|
||||||
|
memo: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询Banner管理列表 */
|
||||||
|
export function getBannerPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallBannerApi.Banner>>(
|
||||||
|
'/promotion/banner/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询Banner管理详情 */
|
||||||
|
export function getBanner(id: number) {
|
||||||
|
return requestClient.get<MallBannerApi.Banner>(
|
||||||
|
`/promotion/banner/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增Banner管理 */
|
||||||
|
export function createBanner(data: MallBannerApi.Banner) {
|
||||||
|
return requestClient.post('/promotion/banner/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改Banner管理 */
|
||||||
|
export function updateBanner(data: MallBannerApi.Banner) {
|
||||||
|
return requestClient.put('/promotion/banner/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除Banner管理 */
|
||||||
|
export function deleteBanner(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/banner/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBrandApi {
|
||||||
|
/** 商品品牌 */
|
||||||
|
export interface Brand {
|
||||||
|
/** 品牌编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 品牌名称 */
|
||||||
|
name: string;
|
||||||
|
/** 品牌图片 */
|
||||||
|
picUrl: string;
|
||||||
|
/** 品牌排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 品牌描述 */
|
||||||
|
description?: string;
|
||||||
|
/** 开启状态 */
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建商品品牌 */
|
||||||
|
export function createBrand(data: MallBrandApi.Brand) {
|
||||||
|
return requestClient.post('/product/brand/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新商品品牌 */
|
||||||
|
export function updateBrand(data: MallBrandApi.Brand) {
|
||||||
|
return requestClient.put('/product/brand/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除商品品牌 */
|
||||||
|
export function deleteBrand(id: number) {
|
||||||
|
return requestClient.delete(`/product/brand/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品品牌 */
|
||||||
|
export function getBrand(id: number) {
|
||||||
|
return requestClient.get<MallBrandApi.Brand>(`/product/brand/get?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品品牌列表 */
|
||||||
|
export function getBrandPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallBrandApi.Brand>>(
|
||||||
|
'/product/brand/page',
|
||||||
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品品牌精简信息列表 */
|
||||||
|
export function getSimpleBrandList() {
|
||||||
|
return requestClient.get<MallBrandApi.Brand[]>(
|
||||||
|
'/product/brand/list-all-simple',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallCategoryApi {
|
||||||
|
/** 产品分类 */
|
||||||
|
export interface Category {
|
||||||
|
/** 分类编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 父分类编号 */
|
||||||
|
parentId?: number;
|
||||||
|
/** 分类名称 */
|
||||||
|
name: string;
|
||||||
|
/** 移动端分类图 */
|
||||||
|
picUrl: string;
|
||||||
|
/** 分类排序 */
|
||||||
|
sort: number;
|
||||||
|
/** 开启状态 */
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建商品分类 */
|
||||||
|
export function createCategory(data: MallCategoryApi.Category) {
|
||||||
|
return requestClient.post('/product/category/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新商品分类 */
|
||||||
|
export function updateCategory(data: MallCategoryApi.Category) {
|
||||||
|
return requestClient.put('/product/category/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除商品分类 */
|
||||||
|
export function deleteCategory(id: number) {
|
||||||
|
return requestClient.delete(`/product/category/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品分类 */
|
||||||
|
export function getCategory(id: number) {
|
||||||
|
return requestClient.get<MallCategoryApi.Category>(
|
||||||
|
`/product/category/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品分类列表 */
|
||||||
|
export function getCategoryList(params: any) {
|
||||||
|
return requestClient.get<MallCategoryApi.Category[]>(
|
||||||
|
'/product/category/list',
|
||||||
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallCommentApi {
|
||||||
|
export interface Property {
|
||||||
|
propertyId: number;
|
||||||
|
propertyName: string;
|
||||||
|
valueId: number;
|
||||||
|
valueName: string;
|
||||||
|
}
|
||||||
|
/** 商品评论 */
|
||||||
|
export interface Comment {
|
||||||
|
id: number;
|
||||||
|
userId: number;
|
||||||
|
userNickname: string;
|
||||||
|
userAvatar: string;
|
||||||
|
anonymous: boolean;
|
||||||
|
orderId: number;
|
||||||
|
orderItemId: number;
|
||||||
|
spuId: number;
|
||||||
|
spuName: string;
|
||||||
|
skuId: number;
|
||||||
|
visible: boolean;
|
||||||
|
scores: number;
|
||||||
|
descriptionScores: number;
|
||||||
|
benefitScores: number;
|
||||||
|
content: string;
|
||||||
|
picUrls: string[];
|
||||||
|
replyStatus: boolean;
|
||||||
|
replyUserId: number;
|
||||||
|
replyContent: string;
|
||||||
|
replyTime: Date;
|
||||||
|
createTime: Date;
|
||||||
|
skuProperties: Property[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 评论可见性更新 */
|
||||||
|
export interface CommentVisibleUpdate {
|
||||||
|
id: number;
|
||||||
|
visible: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 评论回复 */
|
||||||
|
export interface CommentReply {
|
||||||
|
id: number;
|
||||||
|
replyContent: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询商品评论列表 */
|
||||||
|
export function getCommentPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallCommentApi.Comment>>(
|
||||||
|
'/product/comment/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询商品评论详情 */
|
||||||
|
export function getComment(id: number) {
|
||||||
|
return requestClient.get<MallCommentApi.Comment>(
|
||||||
|
`/product/comment/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 添加自评 */
|
||||||
|
export function createComment(data: MallCommentApi.Comment) {
|
||||||
|
return requestClient.post('/product/comment/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 显示 / 隐藏评论 */
|
||||||
|
export function updateCommentVisible(
|
||||||
|
data: MallCommentApi.CommentVisibleUpdate,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/product/comment/update-visible', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商家回复 */
|
||||||
|
export function replyComment(data: MallCommentApi.CommentReply) {
|
||||||
|
return requestClient.put('/product/comment/reply', data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallFavoriteApi {
|
||||||
|
/** 商品收藏 */
|
||||||
|
export interface Favorite {
|
||||||
|
/** 收藏编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId?: string;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: null | number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品收藏列表 */
|
||||||
|
export function getFavoritePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallFavoriteApi.Favorite>>(
|
||||||
|
'/product/favorite/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallHistoryApi {
|
||||||
|
/** 商品浏览记录 */
|
||||||
|
export interface BrowseHistory {
|
||||||
|
/** 记录编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId?: number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: number;
|
||||||
|
/** 浏览时间 */
|
||||||
|
createTime?: Date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得商品浏览记录分页
|
||||||
|
*
|
||||||
|
* @param params 请求参数
|
||||||
|
*/
|
||||||
|
export function getBrowseHistoryPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallHistoryApi.BrowseHistory>>(
|
||||||
|
'/product/browse-history/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallPropertyApi {
|
||||||
|
/** 商品属性 */
|
||||||
|
export interface Property {
|
||||||
|
/** 属性编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 名称 */
|
||||||
|
name: string;
|
||||||
|
/** 备注 */
|
||||||
|
remark?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 属性值 */
|
||||||
|
export interface PropertyValue {
|
||||||
|
/** 属性值编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 属性项的编号 */
|
||||||
|
propertyId?: number;
|
||||||
|
/** 名称 */
|
||||||
|
name: string;
|
||||||
|
/** 备注 */
|
||||||
|
remark?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 属性值查询参数 */
|
||||||
|
export interface PropertyValueQuery extends PageParam {
|
||||||
|
propertyId?: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建属性项 */
|
||||||
|
export function createProperty(data: MallPropertyApi.Property) {
|
||||||
|
return requestClient.post('/product/property/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新属性项 */
|
||||||
|
export function updateProperty(data: MallPropertyApi.Property) {
|
||||||
|
return requestClient.put('/product/property/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除属性项 */
|
||||||
|
export function deleteProperty(id: number) {
|
||||||
|
return requestClient.delete(`/product/property/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得属性项 */
|
||||||
|
export function getProperty(id: number) {
|
||||||
|
return requestClient.get<MallPropertyApi.Property>(
|
||||||
|
`/product/property/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得属性项分页 */
|
||||||
|
export function getPropertyPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallPropertyApi.Property>>(
|
||||||
|
'/product/property/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得属性项精简列表 */
|
||||||
|
export function getPropertySimpleList() {
|
||||||
|
return requestClient.get<MallPropertyApi.Property[]>(
|
||||||
|
'/product/property/simple-list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得属性值分页 */
|
||||||
|
export function getPropertyValuePage(
|
||||||
|
params: MallPropertyApi.PropertyValueQuery,
|
||||||
|
) {
|
||||||
|
return requestClient.get<PageResult<MallPropertyApi.PropertyValue>>(
|
||||||
|
'/product/property/value/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得属性值 */
|
||||||
|
export function getPropertyValue(id: number) {
|
||||||
|
return requestClient.get<MallPropertyApi.PropertyValue>(
|
||||||
|
`/product/property/value/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建属性值 */
|
||||||
|
export function createPropertyValue(data: MallPropertyApi.PropertyValue) {
|
||||||
|
return requestClient.post('/product/property/value/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新属性值 */
|
||||||
|
export function updatePropertyValue(data: MallPropertyApi.PropertyValue) {
|
||||||
|
return requestClient.put('/product/property/value/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除属性值 */
|
||||||
|
export function deletePropertyValue(id: number) {
|
||||||
|
return requestClient.delete(`/product/property/value/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得属性值精简列表 */
|
||||||
|
export function getPropertyValueSimpleList(propertyId: number) {
|
||||||
|
return requestClient.get<MallPropertyApi.PropertyValue[]>(
|
||||||
|
'/product/property/value/simple-list',
|
||||||
|
{
|
||||||
|
params: { propertyId },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallSpuApi {
|
||||||
|
/** 商品属性 */
|
||||||
|
export interface Property {
|
||||||
|
/** 属性编号 */
|
||||||
|
propertyId?: number;
|
||||||
|
/** 属性名称 */
|
||||||
|
propertyName?: string;
|
||||||
|
/** 属性值编号 */
|
||||||
|
valueId?: number;
|
||||||
|
/** 属性值名称 */
|
||||||
|
valueName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商品 SKU */
|
||||||
|
export interface Sku {
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 商品 SKU 名称 */
|
||||||
|
name?: string;
|
||||||
|
/** SPU 编号 */
|
||||||
|
spuId?: number;
|
||||||
|
/** 属性数组 */
|
||||||
|
properties?: Property[];
|
||||||
|
/** 商品价格 */
|
||||||
|
price?: number | string;
|
||||||
|
/** 市场价 */
|
||||||
|
marketPrice?: number | string;
|
||||||
|
/** 成本价 */
|
||||||
|
costPrice?: number | string;
|
||||||
|
/** 商品条码 */
|
||||||
|
barCode?: string;
|
||||||
|
/** 图片地址 */
|
||||||
|
picUrl?: string;
|
||||||
|
/** 库存 */
|
||||||
|
stock?: number;
|
||||||
|
/** 商品重量,单位:kg 千克 */
|
||||||
|
weight?: number;
|
||||||
|
/** 商品体积,单位:m^3 平米 */
|
||||||
|
volume?: number;
|
||||||
|
/** 一级分销的佣金 */
|
||||||
|
firstBrokeragePrice?: number | string;
|
||||||
|
/** 二级分销的佣金 */
|
||||||
|
secondBrokeragePrice?: number | string;
|
||||||
|
/** 商品销量 */
|
||||||
|
salesCount?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 优惠券模板 */
|
||||||
|
export interface GiveCouponTemplate {
|
||||||
|
/** 优惠券编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 优惠券名称 */
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商品 SPU */
|
||||||
|
export interface Spu {
|
||||||
|
/** 商品编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 商品名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 商品分类 */
|
||||||
|
categoryId?: number;
|
||||||
|
/** 关键字 */
|
||||||
|
keyword?: string;
|
||||||
|
/** 单位 */
|
||||||
|
unit?: number | undefined;
|
||||||
|
/** 商品封面图 */
|
||||||
|
picUrl?: string;
|
||||||
|
/** 商品轮播图 */
|
||||||
|
sliderPicUrls?: string[];
|
||||||
|
/** 商品简介 */
|
||||||
|
introduction?: string;
|
||||||
|
/** 配送方式 */
|
||||||
|
deliveryTypes?: number[];
|
||||||
|
/** 运费模版 */
|
||||||
|
deliveryTemplateId?: number | undefined;
|
||||||
|
/** 商品品牌编号 */
|
||||||
|
brandId?: number;
|
||||||
|
/** 商品规格 */
|
||||||
|
specType?: boolean;
|
||||||
|
/** 分销类型 */
|
||||||
|
subCommissionType?: boolean;
|
||||||
|
/** sku数组 */
|
||||||
|
skus?: Sku[];
|
||||||
|
/** 商品详情 */
|
||||||
|
description?: string;
|
||||||
|
/** 商品排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 赠送积分 */
|
||||||
|
giveIntegral?: number;
|
||||||
|
/** 虚拟销量 */
|
||||||
|
virtualSalesCount?: number;
|
||||||
|
/** 商品价格 */
|
||||||
|
price?: number;
|
||||||
|
/** 商品拼团价格 */
|
||||||
|
combinationPrice?: number;
|
||||||
|
/** 商品秒杀价格 */
|
||||||
|
seckillPrice?: number;
|
||||||
|
/** 商品销量 */
|
||||||
|
salesCount?: number;
|
||||||
|
/** 市场价 */
|
||||||
|
marketPrice?: number;
|
||||||
|
/** 成本价 */
|
||||||
|
costPrice?: number;
|
||||||
|
/** 商品库存 */
|
||||||
|
stock?: number;
|
||||||
|
/** 商品创建时间 */
|
||||||
|
createTime?: Date;
|
||||||
|
/** 商品状态 */
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商品状态更新 */
|
||||||
|
export interface StatusUpdate {
|
||||||
|
/** 商品编号 */
|
||||||
|
id: number;
|
||||||
|
/** 商品状态 */
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品 SPU 列表 */
|
||||||
|
export function getSpuPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallSpuApi.Spu>>('/product/spu/page', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品 SPU 列表 tabsCount */
|
||||||
|
export function getTabsCount() {
|
||||||
|
return requestClient.get<Record<string, number>>('/product/spu/get-count');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建商品 SPU */
|
||||||
|
export function createSpu(data: MallSpuApi.Spu) {
|
||||||
|
return requestClient.post('/product/spu/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新商品 SPU */
|
||||||
|
export function updateSpu(data: MallSpuApi.Spu) {
|
||||||
|
return requestClient.put('/product/spu/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新商品 SPU 状态 */
|
||||||
|
export function updateStatus(data: MallSpuApi.StatusUpdate) {
|
||||||
|
return requestClient.put('/product/spu/update-status', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品 SPU */
|
||||||
|
export function getSpu(id: number) {
|
||||||
|
return requestClient.get<MallSpuApi.Spu>(`/product/spu/get-detail?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品 SPU 详情列表 */
|
||||||
|
export function getSpuDetailList(ids: number[]) {
|
||||||
|
return requestClient.get<MallSpuApi.Spu[]>(`/product/spu/list?spuIds=${ids}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除商品 SPU */
|
||||||
|
export function deleteSpu(id: number) {
|
||||||
|
return requestClient.delete(`/product/spu/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出商品 SPU Excel */
|
||||||
|
export function exportSpu(params: PageParam) {
|
||||||
|
return requestClient.download('/product/spu/export', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品 SPU 精简列表 */
|
||||||
|
export function getSpuSimpleList() {
|
||||||
|
return requestClient.get<MallSpuApi.Spu[]>('/product/spu/list-all-simple');
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallArticleApi {
|
||||||
|
/** 文章管理 */
|
||||||
|
export interface Article {
|
||||||
|
/** 文章编号 */
|
||||||
|
id: number;
|
||||||
|
/** 分类编号 */
|
||||||
|
categoryId: number;
|
||||||
|
/** 文章标题 */
|
||||||
|
title: string;
|
||||||
|
/** 作者 */
|
||||||
|
author: string;
|
||||||
|
/** 封面图 */
|
||||||
|
picUrl: string;
|
||||||
|
/** 文章简介 */
|
||||||
|
introduction: string;
|
||||||
|
/** 浏览数量 */
|
||||||
|
browseCount: string;
|
||||||
|
/** 排序 */
|
||||||
|
sort: number;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
/** 商品编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 是否热门 */
|
||||||
|
recommendHot: boolean;
|
||||||
|
/** 是否轮播图 */
|
||||||
|
recommendBanner: boolean;
|
||||||
|
/** 文章内容 */
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询文章管理列表 */
|
||||||
|
export function getArticlePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallArticleApi.Article>>(
|
||||||
|
'/promotion/article/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询文章管理详情 */
|
||||||
|
export function getArticle(id: number) {
|
||||||
|
return requestClient.get<MallArticleApi.Article>(
|
||||||
|
`/promotion/article/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增文章管理 */
|
||||||
|
export function createArticle(data: MallArticleApi.Article) {
|
||||||
|
return requestClient.post('/promotion/article/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改文章管理 */
|
||||||
|
export function updateArticle(data: MallArticleApi.Article) {
|
||||||
|
return requestClient.put('/promotion/article/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除文章管理 */
|
||||||
|
export function deleteArticle(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/article/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallArticleCategoryApi {
|
||||||
|
/** 文章分类 */
|
||||||
|
export interface ArticleCategory {
|
||||||
|
/** 分类编号 */
|
||||||
|
id: number;
|
||||||
|
/** 分类名称 */
|
||||||
|
name: string;
|
||||||
|
/** 分类图片 */
|
||||||
|
picUrl: string;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
/** 排序 */
|
||||||
|
sort: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询文章分类列表 */
|
||||||
|
export function getArticleCategoryPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallArticleCategoryApi.ArticleCategory>>(
|
||||||
|
'/promotion/article-category/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询文章分类精简信息列表 */
|
||||||
|
export function getSimpleArticleCategoryList() {
|
||||||
|
return requestClient.get<MallArticleCategoryApi.ArticleCategory[]>(
|
||||||
|
'/promotion/article-category/list-all-simple',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询文章分类详情 */
|
||||||
|
export function getArticleCategory(id: number) {
|
||||||
|
return requestClient.get<MallArticleCategoryApi.ArticleCategory>(
|
||||||
|
`/promotion/article-category/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增文章分类 */
|
||||||
|
export function createArticleCategory(
|
||||||
|
data: MallArticleCategoryApi.ArticleCategory,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/promotion/article-category/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改文章分类 */
|
||||||
|
export function updateArticleCategory(
|
||||||
|
data: MallArticleCategoryApi.ArticleCategory,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/article-category/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除文章分类 */
|
||||||
|
export function deleteArticleCategory(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/article-category/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import type { MallSpuApi } from '#/api/mall/product/spu';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBargainActivityApi {
|
||||||
|
/** 砍价活动 */
|
||||||
|
export interface BargainActivity {
|
||||||
|
/** 活动编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 活动名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 开始时间 */
|
||||||
|
startTime?: Date;
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime?: Date;
|
||||||
|
/** 状态 */
|
||||||
|
status?: number;
|
||||||
|
/** 达到该人数,才能砍到低价 */
|
||||||
|
helpMaxCount?: number;
|
||||||
|
/** 最大帮砍次数 */
|
||||||
|
bargainCount?: number;
|
||||||
|
/** 最大购买次数 */
|
||||||
|
totalLimitCount?: number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId: number;
|
||||||
|
/** 砍价起始价格,单位分 */
|
||||||
|
bargainFirstPrice: number;
|
||||||
|
/** 砍价底价 */
|
||||||
|
bargainMinPrice: number;
|
||||||
|
/** 活动库存 */
|
||||||
|
stock: number;
|
||||||
|
/** 用户每次砍价的最小金额,单位:分 */
|
||||||
|
randomMinPrice?: number;
|
||||||
|
/** 用户每次砍价的最大金额,单位:分 */
|
||||||
|
randomMaxPrice?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 砍价活动所需属性。选择的商品和属性的时候使用方便使用活动的通用封装 */
|
||||||
|
export interface BargainProduct {
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId: number;
|
||||||
|
/** 砍价起始价格,单位分 */
|
||||||
|
bargainFirstPrice: number;
|
||||||
|
/** 砍价底价 */
|
||||||
|
bargainMinPrice: number;
|
||||||
|
/** 活动库存 */
|
||||||
|
stock: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扩展 SKU 配置 */
|
||||||
|
export type SkuExtension = {
|
||||||
|
/** 砍价活动配置 */
|
||||||
|
productConfig: BargainProduct;
|
||||||
|
} & MallSpuApi.Sku;
|
||||||
|
|
||||||
|
/** 扩展 SPU 配置 */
|
||||||
|
export interface SpuExtension extends MallSpuApi.Spu {
|
||||||
|
/** SKU 列表 */
|
||||||
|
skus: SkuExtension[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询砍价活动列表 */
|
||||||
|
export function getBargainActivityPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallBargainActivityApi.BargainActivity>>(
|
||||||
|
'/promotion/bargain-activity/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询砍价活动详情 */
|
||||||
|
export function getBargainActivity(id: number) {
|
||||||
|
return requestClient.get<MallBargainActivityApi.BargainActivity>(
|
||||||
|
`/promotion/bargain-activity/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增砍价活动 */
|
||||||
|
export function createBargainActivity(
|
||||||
|
data: MallBargainActivityApi.BargainActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/promotion/bargain-activity/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改砍价活动 */
|
||||||
|
export function updateBargainActivity(
|
||||||
|
data: MallBargainActivityApi.BargainActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/bargain-activity/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭砍价活动 */
|
||||||
|
export function closeBargainActivity(id: number) {
|
||||||
|
return requestClient.put(`/promotion/bargain-activity/close?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除砍价活动 */
|
||||||
|
export function deleteBargainActivity(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/bargain-activity/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBargainHelpApi {
|
||||||
|
/** 砍价记录 */
|
||||||
|
export interface BargainHelp {
|
||||||
|
/** 记录编号 */
|
||||||
|
id: number;
|
||||||
|
/** 砍价记录编号 */
|
||||||
|
record: number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
/** 砍掉金额 */
|
||||||
|
reducePrice: number;
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime: Date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询砍价记录列表 */
|
||||||
|
export function getBargainHelpPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallBargainHelpApi.BargainHelp>>(
|
||||||
|
'/promotion/bargain-help/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBargainRecordApi {
|
||||||
|
/** 砍价记录 */
|
||||||
|
export interface BargainRecord {
|
||||||
|
/** 记录编号 */
|
||||||
|
id: number;
|
||||||
|
/** 活动编号 */
|
||||||
|
activityId: number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId: number;
|
||||||
|
/** 砍价起始价格 */
|
||||||
|
bargainFirstPrice: number;
|
||||||
|
/** 砍价价格 */
|
||||||
|
bargainPrice: number;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
/** 订单编号 */
|
||||||
|
orderId: number;
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime: Date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询砍价记录列表 */
|
||||||
|
export function getBargainRecordPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallBargainRecordApi.BargainRecord>>(
|
||||||
|
'/promotion/bargain-record/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import type { MallSpuApi } from '#/api/mall/product/spu';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallCombinationActivityApi {
|
||||||
|
/** 拼团活动所需属性 */
|
||||||
|
export interface CombinationProduct {
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId: number;
|
||||||
|
/** 拼团价格 */
|
||||||
|
combinationPrice: number;
|
||||||
|
}
|
||||||
|
/** 拼团活动 */
|
||||||
|
export interface CombinationActivity {
|
||||||
|
/** 活动编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 活动名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: number;
|
||||||
|
/** 总限购数量 */
|
||||||
|
totalLimitCount?: number;
|
||||||
|
/** 单次限购数量 */
|
||||||
|
singleLimitCount?: number;
|
||||||
|
/** 开始时间 */
|
||||||
|
startTime?: Date;
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime?: Date;
|
||||||
|
/** 用户数量 */
|
||||||
|
userSize?: number;
|
||||||
|
/** 总数量 */
|
||||||
|
totalCount?: number;
|
||||||
|
/** 成功数量 */
|
||||||
|
successCount?: number;
|
||||||
|
/** 订单用户数量 */
|
||||||
|
orderUserCount?: number;
|
||||||
|
/** 虚拟成团 */
|
||||||
|
virtualGroup?: number;
|
||||||
|
/** 状态 */
|
||||||
|
status?: number;
|
||||||
|
/** 限制时长 */
|
||||||
|
limitDuration?: number;
|
||||||
|
/** 拼团价格 */
|
||||||
|
combinationPrice?: number;
|
||||||
|
/** 商品列表 */
|
||||||
|
products: CombinationProduct[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扩展 SKU 配置 */
|
||||||
|
export type SkuExtension = {
|
||||||
|
/** 拼团活动配置 */
|
||||||
|
productConfig: CombinationProduct;
|
||||||
|
} & MallSpuApi.Sku;
|
||||||
|
|
||||||
|
/** 扩展 SPU 配置 */
|
||||||
|
export interface SpuExtension extends MallSpuApi.Spu {
|
||||||
|
/** SKU 列表 */
|
||||||
|
skus: SkuExtension[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询拼团活动列表 */
|
||||||
|
export function getCombinationActivityPage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MallCombinationActivityApi.CombinationActivity>
|
||||||
|
>('/promotion/combination-activity/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询拼团活动详情 */
|
||||||
|
export function getCombinationActivity(id: number) {
|
||||||
|
return requestClient.get<MallCombinationActivityApi.CombinationActivity>(
|
||||||
|
`/promotion/combination-activity/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得拼团活动列表,基于活动编号数组 */
|
||||||
|
export function getCombinationActivityListByIds(ids: number[]) {
|
||||||
|
return requestClient.get<MallCombinationActivityApi.CombinationActivity[]>(
|
||||||
|
`/promotion/combination-activity/list-by-ids?ids=${ids}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增拼团活动 */
|
||||||
|
export function createCombinationActivity(
|
||||||
|
data: MallCombinationActivityApi.CombinationActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/promotion/combination-activity/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改拼团活动 */
|
||||||
|
export function updateCombinationActivity(
|
||||||
|
data: MallCombinationActivityApi.CombinationActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/combination-activity/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭拼团活动 */
|
||||||
|
export function closeCombinationActivity(id: number) {
|
||||||
|
return requestClient.put(`/promotion/combination-activity/close?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除拼团活动 */
|
||||||
|
export function deleteCombinationActivity(id: number) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/promotion/combination-activity/delete?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallCombinationRecordApi {
|
||||||
|
/** 拼团记录 */
|
||||||
|
export interface CombinationRecord {
|
||||||
|
/** 拼团记录编号 */
|
||||||
|
id: number;
|
||||||
|
/** 拼团活动编号 */
|
||||||
|
activityId: number;
|
||||||
|
/** 用户昵称 */
|
||||||
|
nickname: string;
|
||||||
|
/** 用户头像 */
|
||||||
|
avatar: string;
|
||||||
|
/** 团长编号 */
|
||||||
|
headId: number;
|
||||||
|
/** 过期时间 */
|
||||||
|
expireTime: string;
|
||||||
|
/** 可参团人数 */
|
||||||
|
userSize: number;
|
||||||
|
/** 已参团人数 */
|
||||||
|
userCount: number;
|
||||||
|
/** 拼团状态 */
|
||||||
|
status: number;
|
||||||
|
/** 商品名字 */
|
||||||
|
spuName: string;
|
||||||
|
/** 商品图片 */
|
||||||
|
picUrl: string;
|
||||||
|
/** 是否虚拟成团 */
|
||||||
|
virtualGroup: boolean;
|
||||||
|
/** 开始时间 (订单付款后开始的时间) */
|
||||||
|
startTime: string;
|
||||||
|
/** 结束时间(成团时间/失败时间) */
|
||||||
|
endTime: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 拼团记录概要信息 */
|
||||||
|
export interface RecordSummary {
|
||||||
|
/** 待成团数量 */
|
||||||
|
pendingCount: number;
|
||||||
|
/** 已成团数量 */
|
||||||
|
successCount: number;
|
||||||
|
/** 已失败数量 */
|
||||||
|
failCount: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询拼团记录列表 */
|
||||||
|
export function getCombinationRecordPage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MallCombinationRecordApi.CombinationRecord>
|
||||||
|
>('/promotion/combination-record/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得拼团记录的概要信息 */
|
||||||
|
export function getCombinationRecordSummary() {
|
||||||
|
return requestClient.get<MallCombinationRecordApi.RecordSummary>(
|
||||||
|
'/promotion/combination-record/get-summary',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallCouponApi {
|
||||||
|
/** 优惠券 */
|
||||||
|
export interface Coupon {
|
||||||
|
/** 优惠券编号 */
|
||||||
|
id: number;
|
||||||
|
/** 优惠券名称 */
|
||||||
|
name: string;
|
||||||
|
/** 优惠券状态 */
|
||||||
|
status: number;
|
||||||
|
/** 优惠券类型 */
|
||||||
|
type: number;
|
||||||
|
/** 优惠券金额 */
|
||||||
|
price: number;
|
||||||
|
/** 使用门槛 */
|
||||||
|
usePrice: number;
|
||||||
|
/** 商品范围 */
|
||||||
|
productScope: number;
|
||||||
|
/** 商品编号数组 */
|
||||||
|
productSpuIds: number[];
|
||||||
|
/** 有效期类型 */
|
||||||
|
validityType: number;
|
||||||
|
/** 固定日期-生效开始时间 */
|
||||||
|
validStartTime: Date;
|
||||||
|
/** 固定日期-生效结束时间 */
|
||||||
|
validEndTime: Date;
|
||||||
|
/** 领取日期-开始天数 */
|
||||||
|
fixedStartTerm: number;
|
||||||
|
/** 领取日期-结束天数 */
|
||||||
|
fixedEndTerm: number;
|
||||||
|
/** 每人限领个数 */
|
||||||
|
takeLimitCount: number;
|
||||||
|
/** 是否设置满多少金额可用 */
|
||||||
|
usePriceEnabled: boolean;
|
||||||
|
/** 商品分类编号数组 */
|
||||||
|
productCategoryIds: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发送优惠券 */
|
||||||
|
export interface SendCoupon {
|
||||||
|
/** 优惠券编号 */
|
||||||
|
couponId: number;
|
||||||
|
/** 用户编号数组 */
|
||||||
|
userIds: number[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除优惠劵 */
|
||||||
|
export function deleteCoupon(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/coupon/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得优惠劵分页 */
|
||||||
|
export function getCouponPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallCouponApi.Coupon>>(
|
||||||
|
'/promotion/coupon/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发送优惠券 */
|
||||||
|
export function sendCoupon(data: MallCouponApi.SendCoupon) {
|
||||||
|
return requestClient.post('/promotion/coupon/send', data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallCouponTemplateApi {
|
||||||
|
/** 优惠券模板 */
|
||||||
|
export interface CouponTemplate {
|
||||||
|
/** 模板编号 */
|
||||||
|
id: number;
|
||||||
|
/** 模板名称 */
|
||||||
|
name: string;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
/** 发放数量 */
|
||||||
|
totalCount: number;
|
||||||
|
/** 每人限领个数 */
|
||||||
|
takeLimitCount: number;
|
||||||
|
/** 领取方式 */
|
||||||
|
takeType: number;
|
||||||
|
/** 使用门槛 */
|
||||||
|
usePrice: number;
|
||||||
|
/** 商品范围 */
|
||||||
|
productScope: number;
|
||||||
|
/** 商品范围值 */
|
||||||
|
productScopeValues: number[];
|
||||||
|
/** 有效期类型 */
|
||||||
|
validityType: number;
|
||||||
|
/** 固定日期-生效开始时间 */
|
||||||
|
validStartTime: Date;
|
||||||
|
/** 固定日期-生效结束时间 */
|
||||||
|
validEndTime: Date;
|
||||||
|
/** 领取日期-开始天数 */
|
||||||
|
fixedStartTerm: number;
|
||||||
|
/** 领取日期-结束天数 */
|
||||||
|
fixedEndTerm: number;
|
||||||
|
/** 优惠类型 */
|
||||||
|
discountType: number;
|
||||||
|
/** 折扣百分比 */
|
||||||
|
discountPercent: number;
|
||||||
|
/** 优惠金额 */
|
||||||
|
discountPrice: number;
|
||||||
|
/** 折扣上限 */
|
||||||
|
discountLimitPrice: number;
|
||||||
|
/** 已领取数量 */
|
||||||
|
takeCount: number;
|
||||||
|
/** 已使用数量 */
|
||||||
|
useCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 优惠券模板状态更新 */
|
||||||
|
export interface StatusUpdate {
|
||||||
|
/** 模板编号 */
|
||||||
|
id: number;
|
||||||
|
/** 状态 */
|
||||||
|
status: 0 | 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建优惠劵模板 */
|
||||||
|
export function createCouponTemplate(
|
||||||
|
data: MallCouponTemplateApi.CouponTemplate,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/promotion/coupon-template/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新优惠劵模板 */
|
||||||
|
export function updateCouponTemplate(
|
||||||
|
data: MallCouponTemplateApi.CouponTemplate,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/coupon-template/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新优惠劵模板的状态 */
|
||||||
|
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 deleteCouponTemplate(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/coupon-template/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得优惠劵模板 */
|
||||||
|
export function getCouponTemplate(id: number) {
|
||||||
|
return requestClient.get<MallCouponTemplateApi.CouponTemplate>(
|
||||||
|
`/promotion/coupon-template/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得优惠劵模板分页 */
|
||||||
|
export function getCouponTemplatePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallCouponTemplateApi.CouponTemplate>>(
|
||||||
|
'/promotion/coupon-template/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得优惠劵模板列表 */
|
||||||
|
export function getCouponTemplateList(ids: number[]) {
|
||||||
|
return requestClient.get<MallCouponTemplateApi.CouponTemplate[]>(
|
||||||
|
`/promotion/coupon-template/list?ids=${ids}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出优惠劵模板 Excel */
|
||||||
|
export function exportCouponTemplateExcel(params: PageParam) {
|
||||||
|
return requestClient.get('/promotion/coupon-template/export-excel', {
|
||||||
|
params,
|
||||||
|
responseType: 'blob',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import type { MallSpuApi } from '#/api/mall/product/spu';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallDiscountActivityApi {
|
||||||
|
/** 限时折扣相关属性 */
|
||||||
|
export interface DiscountProduct {
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId: number;
|
||||||
|
/** 折扣类型 */
|
||||||
|
discountType: number;
|
||||||
|
/** 折扣百分比 */
|
||||||
|
discountPercent: number;
|
||||||
|
/** 折扣价格 */
|
||||||
|
discountPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 限时折扣活动 */
|
||||||
|
export interface DiscountActivity {
|
||||||
|
/** 活动编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: number;
|
||||||
|
/** 活动名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 状态 */
|
||||||
|
status?: number;
|
||||||
|
/** 备注 */
|
||||||
|
remark?: string;
|
||||||
|
/** 开始时间 */
|
||||||
|
startTime?: Date;
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime?: Date;
|
||||||
|
/** 商品列表 */
|
||||||
|
products?: DiscountProduct[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扩展 SKU 配置 */
|
||||||
|
export type SkuExtension = {
|
||||||
|
/** 限时折扣配置 */
|
||||||
|
productConfig: DiscountProduct;
|
||||||
|
} & MallSpuApi.Sku;
|
||||||
|
|
||||||
|
/** 扩展 SPU 配置 */
|
||||||
|
export interface SpuExtension extends MallSpuApi.Spu {
|
||||||
|
/** SKU 列表 */
|
||||||
|
skus: SkuExtension[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询限时折扣活动列表 */
|
||||||
|
export function getDiscountActivityPage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MallDiscountActivityApi.DiscountActivity>
|
||||||
|
>('/promotion/discount-activity/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询限时折扣活动详情 */
|
||||||
|
export function getDiscountActivity(id: number) {
|
||||||
|
return requestClient.get<MallDiscountActivityApi.DiscountActivity>(
|
||||||
|
`/promotion/discount-activity/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增限时折扣活动 */
|
||||||
|
export function createDiscountActivity(
|
||||||
|
data: MallDiscountActivityApi.DiscountActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/promotion/discount-activity/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改限时折扣活动 */
|
||||||
|
export function updateDiscountActivity(
|
||||||
|
data: MallDiscountActivityApi.DiscountActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/discount-activity/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭限时折扣活动 */
|
||||||
|
export function closeDiscountActivity(id: number) {
|
||||||
|
return requestClient.put(`/promotion/discount-activity/close?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除限时折扣活动 */
|
||||||
|
export function deleteDiscountActivity(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/discount-activity/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallDiyPageApi {
|
||||||
|
/** 装修页面 */
|
||||||
|
export interface DiyPage {
|
||||||
|
/** 页面编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 模板编号 */
|
||||||
|
templateId?: number;
|
||||||
|
/** 页面名称 */
|
||||||
|
name: string;
|
||||||
|
/** 备注 */
|
||||||
|
remark: string;
|
||||||
|
/** 预览图片地址数组 */
|
||||||
|
previewPicUrls: string[];
|
||||||
|
/** 页面属性 */
|
||||||
|
property: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询装修页面列表 */
|
||||||
|
export function getDiyPagePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallDiyPageApi.DiyPage>>(
|
||||||
|
'/promotion/diy-page/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询装修页面详情 */
|
||||||
|
export function getDiyPage(id: number) {
|
||||||
|
return requestClient.get<MallDiyPageApi.DiyPage>(
|
||||||
|
`/promotion/diy-page/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增装修页面 */
|
||||||
|
export function createDiyPage(data: MallDiyPageApi.DiyPage) {
|
||||||
|
return requestClient.post('/promotion/diy-page/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改装修页面 */
|
||||||
|
export function updateDiyPage(data: MallDiyPageApi.DiyPage) {
|
||||||
|
return requestClient.put('/promotion/diy-page/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除装修页面 */
|
||||||
|
export function deleteDiyPage(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/diy-page/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得装修页面属性 */
|
||||||
|
export function getDiyPageProperty(id: number) {
|
||||||
|
return requestClient.get<string>(`/promotion/diy-page/get-property?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新装修页面属性 */
|
||||||
|
export function updateDiyPageProperty(data: MallDiyPageApi.DiyPage) {
|
||||||
|
return requestClient.put('/promotion/diy-page/update-property', data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import type { MallDiyPageApi } from './page';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallDiyTemplateApi {
|
||||||
|
/** 装修模板 */
|
||||||
|
export interface DiyTemplate {
|
||||||
|
/** 模板编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 模板名称 */
|
||||||
|
name: string;
|
||||||
|
/** 是否使用 */
|
||||||
|
used: boolean;
|
||||||
|
/** 使用时间 */
|
||||||
|
usedTime?: Date;
|
||||||
|
/** 备注 */
|
||||||
|
remark: string;
|
||||||
|
/** 预览图片地址数组 */
|
||||||
|
previewPicUrls: string[];
|
||||||
|
/** 模板属性 */
|
||||||
|
property: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 装修模板属性(包含页面列表) */
|
||||||
|
export interface DiyTemplateProperty extends DiyTemplate {
|
||||||
|
/** 页面列表 */
|
||||||
|
pages: MallDiyPageApi.DiyPage[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询装修模板列表 */
|
||||||
|
export function getDiyTemplatePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallDiyTemplateApi.DiyTemplate>>(
|
||||||
|
'/promotion/diy-template/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询装修模板详情 */
|
||||||
|
export function getDiyTemplate(id: number) {
|
||||||
|
return requestClient.get<MallDiyTemplateApi.DiyTemplate>(
|
||||||
|
`/promotion/diy-template/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增装修模板 */
|
||||||
|
export function createDiyTemplate(data: MallDiyTemplateApi.DiyTemplate) {
|
||||||
|
return requestClient.post('/promotion/diy-template/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改装修模板 */
|
||||||
|
export function updateDiyTemplate(data: MallDiyTemplateApi.DiyTemplate) {
|
||||||
|
return requestClient.put('/promotion/diy-template/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除装修模板 */
|
||||||
|
export function deleteDiyTemplate(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/diy-template/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 使用装修模板 */
|
||||||
|
export function useDiyTemplate(id: number) {
|
||||||
|
return requestClient.put(`/promotion/diy-template/use?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得装修模板属性 */
|
||||||
|
export function getDiyTemplateProperty(id: number) {
|
||||||
|
return requestClient.get<MallDiyTemplateApi.DiyTemplateProperty>(
|
||||||
|
`/promotion/diy-template/get-property?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新装修模板属性 */
|
||||||
|
export function updateDiyTemplateProperty(
|
||||||
|
data: MallDiyTemplateApi.DiyTemplate,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/diy-template/update-property', data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import type { PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallKefuConversationApi {
|
||||||
|
/** 客服会话 */
|
||||||
|
export interface Conversation {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 会话所属用户 */
|
||||||
|
userId: number;
|
||||||
|
/** 会话所属用户头像 */
|
||||||
|
userAvatar: string;
|
||||||
|
/** 会话所属用户昵称 */
|
||||||
|
userNickname: string;
|
||||||
|
/** 最后聊天时间 */
|
||||||
|
lastMessageTime: Date;
|
||||||
|
/** 最后聊天内容 */
|
||||||
|
lastMessageContent: string;
|
||||||
|
/** 最后发送的消息类型 */
|
||||||
|
lastMessageContentType: number;
|
||||||
|
/** 管理端置顶 */
|
||||||
|
adminPinned: boolean;
|
||||||
|
/** 用户是否可见 */
|
||||||
|
userDeleted: boolean;
|
||||||
|
/** 管理员是否可见 */
|
||||||
|
adminDeleted: boolean;
|
||||||
|
/** 管理员未读消息数 */
|
||||||
|
adminUnreadMessageCount: number;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会话置顶请求 */
|
||||||
|
export interface ConversationPinnedUpdate {
|
||||||
|
/** 会话编号 */
|
||||||
|
id: number;
|
||||||
|
/** 是否置顶 */
|
||||||
|
pinned: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得客服会话列表 */
|
||||||
|
export function getConversationList() {
|
||||||
|
return requestClient.get<PageResult<MallKefuConversationApi.Conversation>>(
|
||||||
|
'/promotion/kefu-conversation/list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得客服会话 */
|
||||||
|
export function getConversation(id: number) {
|
||||||
|
return requestClient.get<MallKefuConversationApi.Conversation>(
|
||||||
|
`/promotion/kefu-conversation/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 客服会话置顶 */
|
||||||
|
export function updateConversationPinned(
|
||||||
|
data: MallKefuConversationApi.ConversationPinnedUpdate,
|
||||||
|
) {
|
||||||
|
return requestClient.put(
|
||||||
|
'/promotion/kefu-conversation/update-conversation-pinned',
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除客服会话 */
|
||||||
|
export function deleteConversation(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/kefu-conversation/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallKefuMessageApi {
|
||||||
|
/** 客服消息 */
|
||||||
|
export interface Message {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 会话编号 */
|
||||||
|
conversationId: number;
|
||||||
|
/** 发送人编号 */
|
||||||
|
senderId: number;
|
||||||
|
/** 发送人头像 */
|
||||||
|
senderAvatar: string;
|
||||||
|
/** 发送人类型 */
|
||||||
|
senderType: number;
|
||||||
|
/** 接收人编号 */
|
||||||
|
receiverId: number;
|
||||||
|
/** 接收人类型 */
|
||||||
|
receiverType: number;
|
||||||
|
/** 消息类型 */
|
||||||
|
contentType: number;
|
||||||
|
/** 消息内容 */
|
||||||
|
content: string;
|
||||||
|
/** 是否已读 */
|
||||||
|
readStatus: boolean;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发送消息请求 */
|
||||||
|
export interface MessageSend {
|
||||||
|
/** 会话编号 */
|
||||||
|
conversationId: number;
|
||||||
|
/** 消息类型 */
|
||||||
|
contentType: number;
|
||||||
|
/** 消息内容 */
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 消息列表查询参数 */
|
||||||
|
export interface MessageQuery extends PageParam {
|
||||||
|
/** 会话编号 */
|
||||||
|
conversationId: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发送客服消息 */
|
||||||
|
export function sendKeFuMessage(data: MallKefuMessageApi.MessageSend) {
|
||||||
|
return requestClient.post('/promotion/kefu-message/send', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新客服消息已读状态 */
|
||||||
|
export function updateKeFuMessageReadStatus(conversationId: number) {
|
||||||
|
return requestClient.put(
|
||||||
|
`/promotion/kefu-message/update-read-status?conversationId=${conversationId}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得消息列表(流式加载) */
|
||||||
|
export function getKeFuMessageList(params: MallKefuMessageApi.MessageQuery) {
|
||||||
|
return requestClient.get<PageResult<MallKefuMessageApi.Message>>(
|
||||||
|
'/promotion/kefu-message/list',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import type { MallSpuApi } from '#/api/mall/product/spu';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallPointActivityApi {
|
||||||
|
/** 积分商城商品 */
|
||||||
|
export interface PointProduct {
|
||||||
|
/** 积分商城商品编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 积分商城活动 id */
|
||||||
|
activityId?: number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: number;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId: number;
|
||||||
|
/** 可兑换数量 */
|
||||||
|
count: number;
|
||||||
|
/** 兑换积分 */
|
||||||
|
point: number;
|
||||||
|
/** 兑换金额,单位:分 */
|
||||||
|
price: number;
|
||||||
|
/** 积分商城商品库存 */
|
||||||
|
stock: number;
|
||||||
|
/** 积分商城商品状态 */
|
||||||
|
activityStatus?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 积分商城活动 */
|
||||||
|
export interface PointActivity {
|
||||||
|
/** 积分商城活动编号 */
|
||||||
|
id: number;
|
||||||
|
/** 积分商城活动商品 */
|
||||||
|
spuId: number;
|
||||||
|
/** 活动状态 */
|
||||||
|
status: number;
|
||||||
|
/** 积分商城活动库存 */
|
||||||
|
stock: number;
|
||||||
|
/** 积分商城活动总库存 */
|
||||||
|
totalStock: number;
|
||||||
|
/** 备注 */
|
||||||
|
remark?: string;
|
||||||
|
/** 排序 */
|
||||||
|
sort: number;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime: string;
|
||||||
|
/** 积分商城商品 */
|
||||||
|
products: PointProduct[];
|
||||||
|
/** 商品名称 */
|
||||||
|
spuName: string;
|
||||||
|
/** 商品主图 */
|
||||||
|
picUrl: string;
|
||||||
|
/** 商品市场价,单位:分 */
|
||||||
|
marketPrice: number;
|
||||||
|
/** 兑换积分 */
|
||||||
|
point: number;
|
||||||
|
/** 兑换金额,单位:分 */
|
||||||
|
price: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扩展 SKU 配置 */
|
||||||
|
export type SkuExtension = {
|
||||||
|
/** 积分商城商品配置 */
|
||||||
|
productConfig: PointProduct;
|
||||||
|
} & MallSpuApi.Sku;
|
||||||
|
|
||||||
|
/** 扩展 SPU 配置 */
|
||||||
|
export interface SpuExtension extends MallSpuApi.Spu {
|
||||||
|
/** SKU 列表 */
|
||||||
|
skus: SkuExtension[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扩展 SPU 配置(带积分信息) */
|
||||||
|
export interface SpuExtensionWithPoint extends MallSpuApi.Spu {
|
||||||
|
/** 积分商城活动库存 */
|
||||||
|
pointStock: number;
|
||||||
|
/** 积分商城活动总库存 */
|
||||||
|
pointTotalStock: number;
|
||||||
|
/** 兑换积分 */
|
||||||
|
point: number;
|
||||||
|
/** 兑换金额,单位:分 */
|
||||||
|
pointPrice: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询积分商城活动分页 */
|
||||||
|
export function getPointActivityPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallPointActivityApi.PointActivity>>(
|
||||||
|
'/promotion/point-activity/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询积分商城活动详情 */
|
||||||
|
export function getPointActivity(id: number) {
|
||||||
|
return requestClient.get<MallPointActivityApi.PointActivity>(
|
||||||
|
`/promotion/point-activity/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询积分商城活动列表,基于活动编号数组 */
|
||||||
|
export function getPointActivityListByIds(ids: number[]) {
|
||||||
|
return requestClient.get<MallPointActivityApi.PointActivity[]>(
|
||||||
|
`/promotion/point-activity/list-by-ids?ids=${ids}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增积分商城活动 */
|
||||||
|
export function createPointActivity(data: MallPointActivityApi.PointActivity) {
|
||||||
|
return requestClient.post('/promotion/point-activity/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改积分商城活动 */
|
||||||
|
export function updatePointActivity(data: MallPointActivityApi.PointActivity) {
|
||||||
|
return requestClient.put('/promotion/point-activity/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除积分商城活动 */
|
||||||
|
export function deletePointActivity(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/point-activity/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭积分商城活动 */
|
||||||
|
export function closePointActivity(id: number) {
|
||||||
|
return requestClient.put(`/promotion/point-activity/close?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallRewardActivityApi {
|
||||||
|
/** 优惠规则 */
|
||||||
|
export interface RewardRule {
|
||||||
|
/** 满足金额 */
|
||||||
|
limit?: number;
|
||||||
|
/** 优惠金额 */
|
||||||
|
discountPrice?: number;
|
||||||
|
/** 是否包邮 */
|
||||||
|
freeDelivery?: boolean;
|
||||||
|
/** 赠送积分 */
|
||||||
|
point: number;
|
||||||
|
/** 赠送优惠券数量 */
|
||||||
|
giveCouponTemplateCounts?: {
|
||||||
|
[key: number]: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 满减送活动 */
|
||||||
|
export interface RewardActivity {
|
||||||
|
/** 活动编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 活动名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 开始时间 */
|
||||||
|
startTime?: Date;
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime?: Date;
|
||||||
|
/** 开始和结束时间(仅前端使用) */
|
||||||
|
startAndEndTime?: Date[];
|
||||||
|
/** 备注 */
|
||||||
|
remark?: string;
|
||||||
|
/** 条件类型 */
|
||||||
|
conditionType?: number;
|
||||||
|
/** 商品范围 */
|
||||||
|
productScope?: number;
|
||||||
|
/** 优惠规则列表 */
|
||||||
|
rules: RewardRule[];
|
||||||
|
/** 商品范围值(仅表单使用):值为品类编号列表、商品编号列表 */
|
||||||
|
productScopeValues?: number[];
|
||||||
|
/** 商品分类编号列表(仅表单使用) */
|
||||||
|
productCategoryIds?: number[];
|
||||||
|
/** 商品 SPU 编号列表(仅表单使用) */
|
||||||
|
productSpuIds?: number[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增满减送活动 */
|
||||||
|
export function createRewardActivity(
|
||||||
|
data: MallRewardActivityApi.RewardActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/promotion/reward-activity/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新满减送活动 */
|
||||||
|
export function updateRewardActivity(
|
||||||
|
data: MallRewardActivityApi.RewardActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/reward-activity/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询满减送活动列表 */
|
||||||
|
export function getRewardActivityPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallRewardActivityApi.RewardActivity>>(
|
||||||
|
'/promotion/reward-activity/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询满减送活动详情 */
|
||||||
|
export function getReward(id: number) {
|
||||||
|
return requestClient.get<MallRewardActivityApi.RewardActivity>(
|
||||||
|
`/promotion/reward-activity/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除满减送活动 */
|
||||||
|
export function deleteRewardActivity(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/reward-activity/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭满减送活动 */
|
||||||
|
export function closeRewardActivity(id: number) {
|
||||||
|
return requestClient.put(`/promotion/reward-activity/close?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import type { MallSpuApi } from '#/api/mall/product/spu';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallSeckillActivityApi {
|
||||||
|
/** 秒杀商品 */
|
||||||
|
export interface SeckillProduct {
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId: number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 秒杀价格 */
|
||||||
|
seckillPrice: number;
|
||||||
|
/** 秒杀库存 */
|
||||||
|
stock: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 秒杀活动 */
|
||||||
|
export interface SeckillActivity {
|
||||||
|
/** 活动编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: number;
|
||||||
|
/** 活动名称 */
|
||||||
|
name?: string;
|
||||||
|
/** 活动状态 */
|
||||||
|
status?: number;
|
||||||
|
/** 备注 */
|
||||||
|
remark?: string;
|
||||||
|
/** 开始时间 */
|
||||||
|
startTime?: Date;
|
||||||
|
/** 结束时间 */
|
||||||
|
endTime?: Date;
|
||||||
|
/** 排序 */
|
||||||
|
sort?: number;
|
||||||
|
/** 配置编号 */
|
||||||
|
configIds?: string;
|
||||||
|
/** 订单数量 */
|
||||||
|
orderCount?: number;
|
||||||
|
/** 用户数量 */
|
||||||
|
userCount?: number;
|
||||||
|
/** 总金额 */
|
||||||
|
totalPrice?: number;
|
||||||
|
/** 总限购数量 */
|
||||||
|
totalLimitCount?: number;
|
||||||
|
/** 单次限购数量 */
|
||||||
|
singleLimitCount?: number;
|
||||||
|
/** 秒杀库存 */
|
||||||
|
stock?: number;
|
||||||
|
/** 秒杀总库存 */
|
||||||
|
totalStock?: number;
|
||||||
|
/** 秒杀价格 */
|
||||||
|
seckillPrice?: number;
|
||||||
|
/** 秒杀商品列表 */
|
||||||
|
products?: SeckillProduct[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 扩展 SKU 配置 */
|
||||||
|
export type SkuExtension = {
|
||||||
|
/** 秒杀商品配置 */
|
||||||
|
productConfig: SeckillProduct;
|
||||||
|
} & MallSpuApi.Sku;
|
||||||
|
|
||||||
|
/** 扩展 SPU 配置 */
|
||||||
|
export interface SpuExtension extends MallSpuApi.Spu {
|
||||||
|
/** SKU 列表 */
|
||||||
|
skus: SkuExtension[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询秒杀活动列表 */
|
||||||
|
export function getSeckillActivityPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallSeckillActivityApi.SeckillActivity>>(
|
||||||
|
'/promotion/seckill-activity/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询秒杀活动列表,基于活动编号数组 */
|
||||||
|
export function getSeckillActivityListByIds(ids: number[]) {
|
||||||
|
return requestClient.get<MallSeckillActivityApi.SeckillActivity[]>(
|
||||||
|
`/promotion/seckill-activity/list-by-ids?ids=${ids}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询秒杀活动详情 */
|
||||||
|
export function getSeckillActivity(id: number) {
|
||||||
|
return requestClient.get<MallSeckillActivityApi.SeckillActivity>(
|
||||||
|
`/promotion/seckill-activity/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增秒杀活动 */
|
||||||
|
export function createSeckillActivity(
|
||||||
|
data: MallSeckillActivityApi.SeckillActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/promotion/seckill-activity/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改秒杀活动 */
|
||||||
|
export function updateSeckillActivity(
|
||||||
|
data: MallSeckillActivityApi.SeckillActivity,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/promotion/seckill-activity/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭秒杀活动 */
|
||||||
|
export function closeSeckillActivity(id: number) {
|
||||||
|
return requestClient.put(`/promotion/seckill-activity/close?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除秒杀活动 */
|
||||||
|
export function deleteSeckillActivity(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/seckill-activity/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallSeckillConfigApi {
|
||||||
|
/** 秒杀时段 */
|
||||||
|
export interface SeckillConfig {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 秒杀时段名称 */
|
||||||
|
name: string;
|
||||||
|
/** 开始时间点 */
|
||||||
|
startTime: string;
|
||||||
|
/** 结束时间点 */
|
||||||
|
endTime: string;
|
||||||
|
/** 秒杀轮播图 */
|
||||||
|
sliderPicUrls: string[];
|
||||||
|
/** 活动状态 */
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 时段配置状态更新 */
|
||||||
|
export interface StatusUpdate {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询秒杀时段分页 */
|
||||||
|
export function getSeckillConfigPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallSeckillConfigApi.SeckillConfig>>(
|
||||||
|
'/promotion/seckill-config/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询秒杀时段列表 */
|
||||||
|
export function getSimpleSeckillConfigList() {
|
||||||
|
return requestClient.get<MallSeckillConfigApi.SeckillConfig[]>(
|
||||||
|
'/promotion/seckill-config/list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询秒杀时段详情 */
|
||||||
|
export function getSeckillConfig(id: number) {
|
||||||
|
return requestClient.get<MallSeckillConfigApi.SeckillConfig>(
|
||||||
|
`/promotion/seckill-config/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增秒杀时段 */
|
||||||
|
export function createSeckillConfig(data: MallSeckillConfigApi.SeckillConfig) {
|
||||||
|
return requestClient.post('/promotion/seckill-config/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改秒杀时段 */
|
||||||
|
export function updateSeckillConfig(data: MallSeckillConfigApi.SeckillConfig) {
|
||||||
|
return requestClient.put('/promotion/seckill-config/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除秒杀时段 */
|
||||||
|
export function deleteSeckillConfig(id: number) {
|
||||||
|
return requestClient.delete(`/promotion/seckill-config/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改时段配置状态 */
|
||||||
|
export function updateSeckillConfigStatus(id: number, status: number) {
|
||||||
|
return requestClient.put('/promotion/seckill-config/update-status', {
|
||||||
|
id,
|
||||||
|
status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
/** 数据对照 Response VO */
|
||||||
|
export interface MallDataComparisonRespVO<T> {
|
||||||
|
value: T;
|
||||||
|
reference: T;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
import type { MallDataComparisonRespVO } from './common';
|
||||||
|
|
||||||
|
import { formatDate } from '@vben/utils';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallMemberStatisticsApi {
|
||||||
|
/** 会员分析 Request VO */
|
||||||
|
export interface AnalyseReq {
|
||||||
|
times: Date[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员分析对照数据 Response VO */
|
||||||
|
export interface AnalyseComparison {
|
||||||
|
registerUserCount: number;
|
||||||
|
visitUserCount: number;
|
||||||
|
rechargeUserCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员分析 Response VO */
|
||||||
|
export interface Analyse {
|
||||||
|
visitUserCount: number;
|
||||||
|
orderUserCount: number;
|
||||||
|
payUserCount: number;
|
||||||
|
atv: number;
|
||||||
|
comparison: MallDataComparisonRespVO<AnalyseComparison>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员地区统计 Response VO */
|
||||||
|
export interface AreaStatistics {
|
||||||
|
areaId: number;
|
||||||
|
areaName: string;
|
||||||
|
userCount: number;
|
||||||
|
orderCreateUserCount: number;
|
||||||
|
orderPayUserCount: number;
|
||||||
|
orderPayPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员性别统计 Response VO */
|
||||||
|
export interface SexStatistics {
|
||||||
|
sex: number;
|
||||||
|
userCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员统计 Response VO */
|
||||||
|
export interface Summary {
|
||||||
|
userCount: number;
|
||||||
|
rechargeUserCount: number;
|
||||||
|
rechargePrice: number;
|
||||||
|
expensePrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员终端统计 Response VO */
|
||||||
|
export interface TerminalStatistics {
|
||||||
|
terminal: number;
|
||||||
|
userCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员数量统计 Response VO */
|
||||||
|
export interface Count {
|
||||||
|
/** 用户访问量 */
|
||||||
|
visitUserCount: string;
|
||||||
|
/** 注册用户数量 */
|
||||||
|
registerUserCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 会员注册数量 Response VO */
|
||||||
|
export interface RegisterCount {
|
||||||
|
date: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询会员统计 */
|
||||||
|
export function getMemberSummary() {
|
||||||
|
return requestClient.get<MallMemberStatisticsApi.Summary>(
|
||||||
|
'/statistics/member/summary',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询会员分析数据 */
|
||||||
|
export function getMemberAnalyse(params: MallMemberStatisticsApi.AnalyseReq) {
|
||||||
|
return requestClient.get<MallMemberStatisticsApi.Analyse>(
|
||||||
|
'/statistics/member/analyse',
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
times: [formatDate(params.times[0]), formatDate(params.times[1])],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按照省份,查询会员统计列表 */
|
||||||
|
export function getMemberAreaStatisticsList() {
|
||||||
|
return requestClient.get<MallMemberStatisticsApi.AreaStatistics[]>(
|
||||||
|
'/statistics/member/area-statistics-list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按照性别,查询会员统计列表 */
|
||||||
|
export function getMemberSexStatisticsList() {
|
||||||
|
return requestClient.get<MallMemberStatisticsApi.SexStatistics[]>(
|
||||||
|
'/statistics/member/sex-statistics-list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按照终端,查询会员统计列表 */
|
||||||
|
export function getMemberTerminalStatisticsList() {
|
||||||
|
return requestClient.get<MallMemberStatisticsApi.TerminalStatistics[]>(
|
||||||
|
'/statistics/member/terminal-statistics-list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得用户数量量对照 */
|
||||||
|
export function getUserCountComparison() {
|
||||||
|
return requestClient.get<
|
||||||
|
MallDataComparisonRespVO<MallMemberStatisticsApi.Count>
|
||||||
|
>('/statistics/member/user-count-comparison');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得会员注册数量列表 */
|
||||||
|
export function getMemberRegisterCountList(beginTime: Date, endTime: Date) {
|
||||||
|
return requestClient.get<MallMemberStatisticsApi.RegisterCount[]>(
|
||||||
|
'/statistics/member/register-count-list',
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
times: [formatDate(beginTime), formatDate(endTime)],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallPayStatisticsApi {
|
||||||
|
/** 支付统计 */
|
||||||
|
export interface PaySummaryRespVO {
|
||||||
|
/** 充值金额,单位分 */
|
||||||
|
rechargePrice: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取钱包充值金额 */
|
||||||
|
export function getWalletRechargePrice() {
|
||||||
|
return requestClient.get<MallPayStatisticsApi.PaySummaryRespVO>(
|
||||||
|
'/statistics/pay/summary',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import type { MallDataComparisonRespVO } from './common';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallProductStatisticsApi {
|
||||||
|
/** 商品统计数据 */
|
||||||
|
export interface ProductStatistics {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 统计日期 */
|
||||||
|
day: string;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId: number;
|
||||||
|
/** 商品 SPU 名称 */
|
||||||
|
spuName: string;
|
||||||
|
/** 商品 SPU 图片 */
|
||||||
|
spuPicUrl: string;
|
||||||
|
/** 浏览次数 */
|
||||||
|
browseCount: number;
|
||||||
|
/** 浏览人数 */
|
||||||
|
browseUserCount: number;
|
||||||
|
/** 收藏次数 */
|
||||||
|
favoriteCount: number;
|
||||||
|
/** 加购次数 */
|
||||||
|
cartCount: number;
|
||||||
|
/** 下单次数 */
|
||||||
|
orderCount: number;
|
||||||
|
/** 支付次数 */
|
||||||
|
orderPayCount: number;
|
||||||
|
/** 支付金额 */
|
||||||
|
orderPayPrice: number;
|
||||||
|
/** 售后次数 */
|
||||||
|
afterSaleCount: number;
|
||||||
|
/** 退款金额 */
|
||||||
|
afterSaleRefundPrice: number;
|
||||||
|
/** 浏览转化率 */
|
||||||
|
browseConvertPercent: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品统计分析 */
|
||||||
|
export function getProductStatisticsAnalyse(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
MallDataComparisonRespVO<MallProductStatisticsApi.ProductStatistics>
|
||||||
|
>('/statistics/product/analyse', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品状况明细 */
|
||||||
|
export function getProductStatisticsList(params: PageParam) {
|
||||||
|
return requestClient.get<MallProductStatisticsApi.ProductStatistics[]>(
|
||||||
|
'/statistics/product/list',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出获得商品状况明细 Excel */
|
||||||
|
export function exportProductStatisticsExcel(params: PageParam) {
|
||||||
|
return requestClient.download('/statistics/product/export-excel', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得商品排行榜分页 */
|
||||||
|
export function getProductStatisticsRankPage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MallProductStatisticsApi.ProductStatistics>
|
||||||
|
>('/statistics/product/rank-page', { params });
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
import type { MallDataComparisonRespVO } from './common';
|
||||||
|
|
||||||
|
import { formatDate } from '@vben/utils';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallTradeStatisticsApi {
|
||||||
|
/** 交易统计 Response VO */
|
||||||
|
export interface TradeSummary {
|
||||||
|
yesterdayOrderCount: number;
|
||||||
|
monthOrderCount: number;
|
||||||
|
yesterdayPayPrice: number;
|
||||||
|
monthPayPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 交易状况 Request VO */
|
||||||
|
export interface TradeTrendReq {
|
||||||
|
times: [Date, Date];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 交易状况统计 Response VO */
|
||||||
|
export interface TradeTrendSummary {
|
||||||
|
time: string;
|
||||||
|
turnoverPrice: number;
|
||||||
|
orderPayPrice: number;
|
||||||
|
rechargePrice: number;
|
||||||
|
expensePrice: number;
|
||||||
|
walletPayPrice: number;
|
||||||
|
brokerageSettlementPrice: number;
|
||||||
|
afterSaleRefundPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 交易订单数量 Response VO */
|
||||||
|
export interface TradeOrderCount {
|
||||||
|
/** 待发货 */
|
||||||
|
undelivered?: number;
|
||||||
|
/** 待核销 */
|
||||||
|
pickUp?: number;
|
||||||
|
/** 退款中 */
|
||||||
|
afterSaleApply?: number;
|
||||||
|
/** 提现待审核 */
|
||||||
|
auditingWithdraw?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 交易订单统计 Response VO */
|
||||||
|
export interface TradeOrderSummary {
|
||||||
|
/** 支付订单商品数 */
|
||||||
|
orderPayCount?: number;
|
||||||
|
/** 总支付金额,单位:分 */
|
||||||
|
orderPayPrice?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单量趋势统计 Response VO */
|
||||||
|
export interface TradeOrderTrend {
|
||||||
|
/** 日期 */
|
||||||
|
date: string;
|
||||||
|
/** 订单数量 */
|
||||||
|
orderPayCount: number;
|
||||||
|
/** 订单支付金额 */
|
||||||
|
orderPayPrice: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 时间参数需要格式化, 确保接口能识别 */
|
||||||
|
const formatDateParam = (params: MallTradeStatisticsApi.TradeTrendReq) => {
|
||||||
|
return {
|
||||||
|
times: [formatDate(params.times[0]), formatDate(params.times[1])],
|
||||||
|
} as MallTradeStatisticsApi.TradeTrendReq;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 查询交易统计 */
|
||||||
|
export function getTradeStatisticsSummary() {
|
||||||
|
return requestClient.get<
|
||||||
|
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeSummary>
|
||||||
|
>('/statistics/trade/summary');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得交易状况统计 */
|
||||||
|
export function getTradeStatisticsAnalyse(
|
||||||
|
params: MallTradeStatisticsApi.TradeTrendReq,
|
||||||
|
) {
|
||||||
|
return requestClient.get<
|
||||||
|
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeTrendSummary>
|
||||||
|
>('/statistics/trade/analyse', { params: formatDateParam(params) });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得交易状况明细 */
|
||||||
|
export function getTradeStatisticsList(
|
||||||
|
params: MallTradeStatisticsApi.TradeTrendReq,
|
||||||
|
) {
|
||||||
|
return requestClient.get<MallTradeStatisticsApi.TradeTrendSummary[]>(
|
||||||
|
'/statistics/trade/list',
|
||||||
|
{ params: formatDateParam(params) },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出交易状况明细 */
|
||||||
|
export function exportTradeStatisticsExcel(
|
||||||
|
params: MallTradeStatisticsApi.TradeTrendReq,
|
||||||
|
) {
|
||||||
|
return requestClient.download('/statistics/trade/export-excel', {
|
||||||
|
params: formatDateParam(params),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得交易订单数量 */
|
||||||
|
export function getOrderCount() {
|
||||||
|
return requestClient.get<MallTradeStatisticsApi.TradeOrderCount>(
|
||||||
|
'/statistics/trade/order-count',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得交易订单数量对照 */
|
||||||
|
export function getOrderComparison() {
|
||||||
|
return requestClient.get<
|
||||||
|
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeOrderSummary>
|
||||||
|
>('/statistics/trade/order-comparison');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得订单量趋势统计 */
|
||||||
|
export function getOrderCountTrendComparison(
|
||||||
|
type: number,
|
||||||
|
beginTime: Date,
|
||||||
|
endTime: Date,
|
||||||
|
) {
|
||||||
|
return requestClient.get<
|
||||||
|
MallDataComparisonRespVO<MallTradeStatisticsApi.TradeOrderTrend>[]
|
||||||
|
>('/statistics/trade/order-count-trend', {
|
||||||
|
params: {
|
||||||
|
type,
|
||||||
|
beginTime: formatDate(beginTime),
|
||||||
|
endTime: formatDate(endTime),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallAfterSaleApi {
|
||||||
|
/** 商品属性 */
|
||||||
|
export interface ProductProperty {
|
||||||
|
/** 属性的编号 */
|
||||||
|
propertyId?: null | number;
|
||||||
|
/** 属性的名称 */
|
||||||
|
propertyName?: string;
|
||||||
|
/** 属性值的编号 */
|
||||||
|
valueId?: null | number;
|
||||||
|
/** 属性值的名称 */
|
||||||
|
valueName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 交易售后 */
|
||||||
|
export interface AfterSale {
|
||||||
|
/** 售后编号,主键自增 */
|
||||||
|
id?: null | number;
|
||||||
|
/** 售后单号 */
|
||||||
|
no?: string;
|
||||||
|
/** 退款状态 */
|
||||||
|
status?: null | number;
|
||||||
|
/** 售后方式 */
|
||||||
|
way?: null | number;
|
||||||
|
/** 售后类型 */
|
||||||
|
type?: null | number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId?: null | number;
|
||||||
|
/** 申请原因 */
|
||||||
|
applyReason?: string;
|
||||||
|
/** 补充描述 */
|
||||||
|
applyDescription?: string;
|
||||||
|
/** 补充凭证图片 */
|
||||||
|
applyPicUrls?: string[];
|
||||||
|
/** 交易订单编号 */
|
||||||
|
orderId?: null | number;
|
||||||
|
/** 订单流水号 */
|
||||||
|
orderNo?: string;
|
||||||
|
/** 交易订单项编号 */
|
||||||
|
orderItemId?: null | number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: null | number;
|
||||||
|
/** 商品 SPU 名称 */
|
||||||
|
spuName?: string;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId?: null | number;
|
||||||
|
/** 属性数组 */
|
||||||
|
properties?: ProductProperty[];
|
||||||
|
/** 商品图片 */
|
||||||
|
picUrl?: string;
|
||||||
|
/** 退货商品数量 */
|
||||||
|
count?: null | number;
|
||||||
|
/** 审批时间 */
|
||||||
|
auditTime?: Date;
|
||||||
|
/** 审批人 */
|
||||||
|
auditUserId?: null | number;
|
||||||
|
/** 审批备注 */
|
||||||
|
auditReason?: string;
|
||||||
|
/** 退款金额,单位:分 */
|
||||||
|
refundPrice?: null | number;
|
||||||
|
/** 支付退款编号 */
|
||||||
|
payRefundId?: null | number;
|
||||||
|
/** 退款时间 */
|
||||||
|
refundTime?: Date;
|
||||||
|
/** 退货物流公司编号 */
|
||||||
|
logisticsId?: null | number;
|
||||||
|
/** 退货物流单号 */
|
||||||
|
logisticsNo?: string;
|
||||||
|
/** 退货时间 */
|
||||||
|
deliveryTime?: Date;
|
||||||
|
/** 收货时间 */
|
||||||
|
receiveTime?: Date;
|
||||||
|
/** 收货备注 */
|
||||||
|
receiveReason?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 拒绝售后请求 */
|
||||||
|
export interface DisagreeRequest {
|
||||||
|
/** 售后编号 */
|
||||||
|
id: number;
|
||||||
|
/** 拒绝原因 */
|
||||||
|
reason: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得交易售后分页 */
|
||||||
|
export function getAfterSalePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallAfterSaleApi.AfterSale>>(
|
||||||
|
'/trade/after-sale/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得交易售后详情 */
|
||||||
|
export function getAfterSale(id: number) {
|
||||||
|
return requestClient.get<MallAfterSaleApi.AfterSale>(
|
||||||
|
`/trade/after-sale/get-detail?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 同意售后 */
|
||||||
|
export function agree(id: number) {
|
||||||
|
return requestClient.put(`/trade/after-sale/agree?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 拒绝售后 */
|
||||||
|
export function disagree(data: MallAfterSaleApi.DisagreeRequest) {
|
||||||
|
return requestClient.put('/trade/after-sale/disagree', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认收货 */
|
||||||
|
export function receive(id: number) {
|
||||||
|
return requestClient.put(`/trade/after-sale/receive?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 拒绝收货 */
|
||||||
|
export function refuse(id: number) {
|
||||||
|
return requestClient.put(`/trade/after-sale/refuse?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认退款 */
|
||||||
|
export function refund(id: number) {
|
||||||
|
return requestClient.put(`/trade/after-sale/refund?id=${id}`);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBrokerageRecordApi {
|
||||||
|
/** 佣金记录 */
|
||||||
|
export interface BrokerageRecord {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
/** 用户昵称 */
|
||||||
|
userNickname: string;
|
||||||
|
/** 用户头像 */
|
||||||
|
userAvatar: string;
|
||||||
|
/** 佣金金额,单位:分 */
|
||||||
|
price: number;
|
||||||
|
/** 佣金类型 */
|
||||||
|
type: number;
|
||||||
|
/** 关联订单编号 */
|
||||||
|
orderId: number;
|
||||||
|
/** 关联订单号 */
|
||||||
|
orderNo: string;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime: Date;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
/** 结算时间 */
|
||||||
|
settlementTime: Date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询佣金记录列表 */
|
||||||
|
export function getBrokerageRecordPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallBrokerageRecordApi.BrokerageRecord>>(
|
||||||
|
'/trade/brokerage-record/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询佣金记录详情 */
|
||||||
|
export function getBrokerageRecord(id: number) {
|
||||||
|
return requestClient.get<MallBrokerageRecordApi.BrokerageRecord>(
|
||||||
|
`/trade/brokerage-record/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBrokerageUserApi {
|
||||||
|
/** 分销用户 */
|
||||||
|
export interface BrokerageUser {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 推广员编号 */
|
||||||
|
bindUserId: number;
|
||||||
|
/** 推广员绑定时间 */
|
||||||
|
bindUserTime: Date;
|
||||||
|
/** 是否启用分销 */
|
||||||
|
brokerageEnabled: boolean;
|
||||||
|
/** 分销资格时间 */
|
||||||
|
brokerageTime: Date;
|
||||||
|
/** 可提现金额,单位:分 */
|
||||||
|
price: number;
|
||||||
|
/** 冻结金额,单位:分 */
|
||||||
|
frozenPrice: number;
|
||||||
|
/** 用户昵称 */
|
||||||
|
nickname: string;
|
||||||
|
/** 用户头像 */
|
||||||
|
avatar: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建分销用户请求 */
|
||||||
|
export interface CreateRequest {
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改推广员请求 */
|
||||||
|
export interface UpdateBindUserRequest {
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
/** 推广员编号 */
|
||||||
|
bindUserId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 清除推广员请求 */
|
||||||
|
export interface ClearBindUserRequest {
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改推广资格请求 */
|
||||||
|
export interface UpdateBrokerageEnabledRequest {
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
/** 是否启用分销 */
|
||||||
|
brokerageEnabled: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建分销用户 */
|
||||||
|
export function createBrokerageUser(data: MallBrokerageUserApi.CreateRequest) {
|
||||||
|
return requestClient.post('/trade/brokerage-user/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询分销用户列表 */
|
||||||
|
export function getBrokerageUserPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallBrokerageUserApi.BrokerageUser>>(
|
||||||
|
'/trade/brokerage-user/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询分销用户详情 */
|
||||||
|
export function getBrokerageUser(id: number) {
|
||||||
|
return requestClient.get<MallBrokerageUserApi.BrokerageUser>(
|
||||||
|
`/trade/brokerage-user/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改推广员 */
|
||||||
|
export function updateBindUser(
|
||||||
|
data: MallBrokerageUserApi.UpdateBindUserRequest,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/trade/brokerage-user/update-bind-user', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 清除推广员 */
|
||||||
|
export function clearBindUser(data: MallBrokerageUserApi.ClearBindUserRequest) {
|
||||||
|
return requestClient.put('/trade/brokerage-user/clear-bind-user', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改推广资格 */
|
||||||
|
export function updateBrokerageEnabled(
|
||||||
|
data: MallBrokerageUserApi.UpdateBrokerageEnabledRequest,
|
||||||
|
) {
|
||||||
|
return requestClient.put(
|
||||||
|
'/trade/brokerage-user/update-brokerage-enable',
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallBrokerageWithdrawApi {
|
||||||
|
/** 佣金提现 */
|
||||||
|
export interface BrokerageWithdraw {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId: number;
|
||||||
|
/** 提现金额,单位:分 */
|
||||||
|
price: number;
|
||||||
|
/** 手续费,单位:分 */
|
||||||
|
feePrice: number;
|
||||||
|
/** 总金额,单位:分 */
|
||||||
|
totalPrice: number;
|
||||||
|
/** 提现类型 */
|
||||||
|
type: number;
|
||||||
|
/** 用户名称 */
|
||||||
|
userName: string;
|
||||||
|
/** 用户账号 */
|
||||||
|
userAccount: string;
|
||||||
|
/** 银行名称 */
|
||||||
|
bankName: string;
|
||||||
|
/** 银行地址 */
|
||||||
|
bankAddress: string;
|
||||||
|
/** 收款码地址 */
|
||||||
|
qrCodeUrl: string;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
/** 审核备注 */
|
||||||
|
auditReason: string;
|
||||||
|
/** 审核时间 */
|
||||||
|
auditTime: Date;
|
||||||
|
/** 备注 */
|
||||||
|
remark: string;
|
||||||
|
/** 支付转账编号 */
|
||||||
|
payTransferId?: number;
|
||||||
|
/** 转账渠道编码 */
|
||||||
|
transferChannelCode?: string;
|
||||||
|
/** 转账时间 */
|
||||||
|
transferTime?: Date;
|
||||||
|
/** 转账错误信息 */
|
||||||
|
transferErrorMsg?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 驳回申请请求 */
|
||||||
|
export interface RejectRequest {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 驳回原因 */
|
||||||
|
auditReason: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询佣金提现列表 */
|
||||||
|
export function getBrokerageWithdrawPage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MallBrokerageWithdrawApi.BrokerageWithdraw>
|
||||||
|
>('/trade/brokerage-withdraw/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询佣金提现详情 */
|
||||||
|
export function getBrokerageWithdraw(id: number) {
|
||||||
|
return requestClient.get<MallBrokerageWithdrawApi.BrokerageWithdraw>(
|
||||||
|
`/trade/brokerage-withdraw/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 佣金提现 - 通过申请 */
|
||||||
|
export function approveBrokerageWithdraw(id: number) {
|
||||||
|
return requestClient.put(`/trade/brokerage-withdraw/approve?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 审核佣金提现 - 驳回申请 */
|
||||||
|
export function rejectBrokerageWithdraw(
|
||||||
|
data: MallBrokerageWithdrawApi.RejectRequest,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/trade/brokerage-withdraw/reject', data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallTradeConfigApi {
|
||||||
|
/** 交易中心配置 */
|
||||||
|
export interface Config {
|
||||||
|
id?: number;
|
||||||
|
afterSaleRefundReasons?: string[];
|
||||||
|
afterSaleReturnReasons?: string[];
|
||||||
|
deliveryExpressFreeEnabled?: boolean;
|
||||||
|
deliveryExpressFreePrice?: number;
|
||||||
|
deliveryPickUpEnabled?: boolean;
|
||||||
|
brokerageEnabled?: boolean;
|
||||||
|
brokerageEnabledCondition?: number;
|
||||||
|
brokerageBindMode?: number;
|
||||||
|
brokeragePosterUrls?: string;
|
||||||
|
brokerageFirstPercent?: number;
|
||||||
|
brokerageSecondPercent?: number;
|
||||||
|
brokerageWithdrawMinPrice?: number;
|
||||||
|
brokerageFrozenDays?: number;
|
||||||
|
brokerageWithdrawTypes?: string;
|
||||||
|
tencentLbsKey?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询交易中心配置详情 */
|
||||||
|
export function getTradeConfig() {
|
||||||
|
return requestClient.get<MallTradeConfigApi.Config>('/trade/config/get');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 保存交易中心配置 */
|
||||||
|
export function saveTradeConfig(data: MallTradeConfigApi.Config) {
|
||||||
|
return requestClient.put('/trade/config/save', data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallDeliveryExpressApi {
|
||||||
|
/** 快递公司 */
|
||||||
|
export interface DeliveryExpress {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 快递公司编码 */
|
||||||
|
code: string;
|
||||||
|
/** 快递公司名称 */
|
||||||
|
name: string;
|
||||||
|
/** 快递公司 logo */
|
||||||
|
logo: string;
|
||||||
|
/** 排序 */
|
||||||
|
sort: number;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 快递公司精简信息 */
|
||||||
|
export interface SimpleDeliveryExpress {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 快递公司编码 */
|
||||||
|
code: string;
|
||||||
|
/** 快递公司名称 */
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询快递公司列表 */
|
||||||
|
export function getDeliveryExpressPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallDeliveryExpressApi.DeliveryExpress>>(
|
||||||
|
'/trade/delivery/express/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询快递公司详情 */
|
||||||
|
export function getDeliveryExpress(id: number) {
|
||||||
|
return requestClient.get<MallDeliveryExpressApi.DeliveryExpress>(
|
||||||
|
`/trade/delivery/express/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获得快递公司精简信息列表 */
|
||||||
|
export function getSimpleDeliveryExpressList() {
|
||||||
|
return requestClient.get<MallDeliveryExpressApi.SimpleDeliveryExpress[]>(
|
||||||
|
'/trade/delivery/express/list-all-simple',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增快递公司 */
|
||||||
|
export function createDeliveryExpress(
|
||||||
|
data: MallDeliveryExpressApi.DeliveryExpress,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/trade/delivery/express/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改快递公司 */
|
||||||
|
export function updateDeliveryExpress(
|
||||||
|
data: MallDeliveryExpressApi.DeliveryExpress,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/trade/delivery/express/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除快递公司 */
|
||||||
|
export function deleteDeliveryExpress(id: number) {
|
||||||
|
return requestClient.delete(`/trade/delivery/express/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出快递公司 Excel */
|
||||||
|
export function exportDeliveryExpress(params: PageParam) {
|
||||||
|
return requestClient.download('/trade/delivery/express/export-excel', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallDeliveryExpressTemplateApi {
|
||||||
|
/** 运费模板计费 */
|
||||||
|
export interface TemplateCharge {
|
||||||
|
/** 区域编号列表 */
|
||||||
|
areaIds: number[];
|
||||||
|
/** 首件数量 */
|
||||||
|
startCount: number;
|
||||||
|
/** 首件价格,单位:分 */
|
||||||
|
startPrice: number;
|
||||||
|
/** 续件数量 */
|
||||||
|
extraCount: number;
|
||||||
|
/** 续件价格,单位:分 */
|
||||||
|
extraPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 运费模板包邮 */
|
||||||
|
export interface TemplateFree {
|
||||||
|
/** 区域编号列表 */
|
||||||
|
areaIds: number[];
|
||||||
|
/** 包邮件数 */
|
||||||
|
freeCount: number;
|
||||||
|
/** 包邮金额,单位:分 */
|
||||||
|
freePrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 快递运费模板 */
|
||||||
|
export interface ExpressTemplate {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 模板名称 */
|
||||||
|
name: string;
|
||||||
|
/** 计费方式 */
|
||||||
|
chargeMode: number;
|
||||||
|
/** 排序 */
|
||||||
|
sort: number;
|
||||||
|
/** 计费区域列表 */
|
||||||
|
templateCharge: TemplateCharge[];
|
||||||
|
/** 包邮区域列表 */
|
||||||
|
templateFree: TemplateFree[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 运费模板精简信息 */
|
||||||
|
export interface SimpleTemplate {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 模板名称 */
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询快递运费模板列表 */
|
||||||
|
export function getDeliveryExpressTemplatePage(params: PageParam) {
|
||||||
|
return requestClient.get<
|
||||||
|
PageResult<MallDeliveryExpressTemplateApi.ExpressTemplate>
|
||||||
|
>('/trade/delivery/express-template/page', { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询快递运费模板详情 */
|
||||||
|
export function getDeliveryExpressTemplate(id: number) {
|
||||||
|
return requestClient.get<MallDeliveryExpressTemplateApi.ExpressTemplate>(
|
||||||
|
`/trade/delivery/express-template/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询快递运费模板详情 */
|
||||||
|
export function getSimpleTemplateList() {
|
||||||
|
return requestClient.get<MallDeliveryExpressTemplateApi.SimpleTemplate[]>(
|
||||||
|
'/trade/delivery/express-template/list-all-simple',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增快递运费模板 */
|
||||||
|
export function createDeliveryExpressTemplate(
|
||||||
|
data: MallDeliveryExpressTemplateApi.ExpressTemplate,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/trade/delivery/express-template/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改快递运费模板 */
|
||||||
|
export function updateDeliveryExpressTemplate(
|
||||||
|
data: MallDeliveryExpressTemplateApi.ExpressTemplate,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/trade/delivery/express-template/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除快递运费模板 */
|
||||||
|
export function deleteDeliveryExpressTemplate(id: number) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/trade/delivery/express-template/delete?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallDeliveryPickUpStoreApi {
|
||||||
|
/** 自提门店 */
|
||||||
|
export interface PickUpStore {
|
||||||
|
/** 编号 */
|
||||||
|
id: number;
|
||||||
|
/** 门店名称 */
|
||||||
|
name: string;
|
||||||
|
/** 门店简介 */
|
||||||
|
introduction: string;
|
||||||
|
/** 联系电话 */
|
||||||
|
phone: string;
|
||||||
|
/** 区域编号 */
|
||||||
|
areaId: number;
|
||||||
|
/** 详细地址 */
|
||||||
|
detailAddress: string;
|
||||||
|
/** 门店 logo */
|
||||||
|
logo: string;
|
||||||
|
/** 营业开始时间 */
|
||||||
|
openingTime: string;
|
||||||
|
/** 营业结束时间 */
|
||||||
|
closingTime: string;
|
||||||
|
/** 纬度 */
|
||||||
|
latitude: number;
|
||||||
|
/** 经度 */
|
||||||
|
longitude: number;
|
||||||
|
/** 状态 */
|
||||||
|
status: number;
|
||||||
|
/** 绑定用户编号组数 */
|
||||||
|
verifyUserIds: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 绑定自提店员请求 */
|
||||||
|
export interface BindStaffRequest {
|
||||||
|
id?: number;
|
||||||
|
/** 门店名称 */
|
||||||
|
name: string;
|
||||||
|
/** 门店编号 */
|
||||||
|
storeId: number;
|
||||||
|
/** 用户编号列表 */
|
||||||
|
userIds: number[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询自提门店列表 */
|
||||||
|
export function getDeliveryPickUpStorePage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallDeliveryPickUpStoreApi.PickUpStore>>(
|
||||||
|
'/trade/delivery/pick-up-store/page',
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询自提门店详情 */
|
||||||
|
export function getDeliveryPickUpStore(id: number) {
|
||||||
|
return requestClient.get<MallDeliveryPickUpStoreApi.PickUpStore>(
|
||||||
|
`/trade/delivery/pick-up-store/get?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询自提门店精简列表 */
|
||||||
|
export function getSimpleDeliveryPickUpStoreList() {
|
||||||
|
return requestClient.get<MallDeliveryPickUpStoreApi.PickUpStore[]>(
|
||||||
|
'/trade/delivery/pick-up-store/simple-list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增自提门店 */
|
||||||
|
export function createDeliveryPickUpStore(
|
||||||
|
data: MallDeliveryPickUpStoreApi.PickUpStore,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/trade/delivery/pick-up-store/create', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改自提门店 */
|
||||||
|
export function updateDeliveryPickUpStore(
|
||||||
|
data: MallDeliveryPickUpStoreApi.PickUpStore,
|
||||||
|
) {
|
||||||
|
return requestClient.put('/trade/delivery/pick-up-store/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除自提门店 */
|
||||||
|
export function deleteDeliveryPickUpStore(id: number) {
|
||||||
|
return requestClient.delete(`/trade/delivery/pick-up-store/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 绑定自提店员 */
|
||||||
|
export function bindStoreStaffId(
|
||||||
|
data: MallDeliveryPickUpStoreApi.BindStaffRequest,
|
||||||
|
) {
|
||||||
|
return requestClient.post('/trade/delivery/pick-up-store/bind', data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,298 @@
|
||||||
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace MallOrderApi {
|
||||||
|
/** 商品属性 */
|
||||||
|
export interface ProductProperty {
|
||||||
|
/** 属性的编号 */
|
||||||
|
propertyId?: null | number;
|
||||||
|
/** 属性的名称 */
|
||||||
|
propertyName?: string;
|
||||||
|
/** 属性值的编号 */
|
||||||
|
valueId?: null | number;
|
||||||
|
/** 属性值的名称 */
|
||||||
|
valueName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单项 */
|
||||||
|
export interface OrderItem {
|
||||||
|
/** 编号 */
|
||||||
|
id?: null | number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId?: null | number;
|
||||||
|
/** 订单编号 */
|
||||||
|
orderId?: null | number;
|
||||||
|
/** 商品 SPU 编号 */
|
||||||
|
spuId?: null | number;
|
||||||
|
/** 商品 SPU 名称 */
|
||||||
|
spuName?: string;
|
||||||
|
/** 商品 SKU 编号 */
|
||||||
|
skuId?: null | number;
|
||||||
|
/** 商品图片 */
|
||||||
|
picUrl?: string;
|
||||||
|
/** 购买数量 */
|
||||||
|
count?: null | number;
|
||||||
|
/** 商品原价(总) */
|
||||||
|
originalPrice?: null | number;
|
||||||
|
/** 商品原价(单) */
|
||||||
|
originalUnitPrice?: null | number;
|
||||||
|
/** 商品优惠(总) */
|
||||||
|
discountPrice?: null | number;
|
||||||
|
/** 商品实付金额(总) */
|
||||||
|
payPrice?: null | number;
|
||||||
|
/** 子订单分摊金额(总) */
|
||||||
|
orderPartPrice?: null | number;
|
||||||
|
/** 分摊后子订单实付金额(总) */
|
||||||
|
orderDividePrice?: null | number;
|
||||||
|
/** 售后状态 */
|
||||||
|
afterSaleStatus?: null | number;
|
||||||
|
/** 属性数组 */
|
||||||
|
properties?: ProductProperty[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单日志 */
|
||||||
|
export interface OrderLog {
|
||||||
|
/** 日志内容 */
|
||||||
|
content?: string;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTime?: Date;
|
||||||
|
/** 用户类型 */
|
||||||
|
userType?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单 */
|
||||||
|
export interface Order {
|
||||||
|
/** 订单编号 */
|
||||||
|
id?: null | number;
|
||||||
|
/** 订单流水号 */
|
||||||
|
no?: string;
|
||||||
|
/** 下单时间 */
|
||||||
|
createTime?: Date | null;
|
||||||
|
/** 订单类型 */
|
||||||
|
type?: null | number;
|
||||||
|
/** 订单来源 */
|
||||||
|
terminal?: null | number;
|
||||||
|
/** 用户编号 */
|
||||||
|
userId?: null | number;
|
||||||
|
/** 用户 IP */
|
||||||
|
userIp?: string;
|
||||||
|
/** 用户备注 */
|
||||||
|
userRemark?: string;
|
||||||
|
/** 订单状态 */
|
||||||
|
status?: null | number;
|
||||||
|
/** 购买的商品数量 */
|
||||||
|
productCount?: null | number;
|
||||||
|
/** 订单完成时间 */
|
||||||
|
finishTime?: Date | null;
|
||||||
|
/** 订单取消时间 */
|
||||||
|
cancelTime?: Date | null;
|
||||||
|
/** 取消类型 */
|
||||||
|
cancelType?: null | number;
|
||||||
|
/** 商家备注 */
|
||||||
|
remark?: string;
|
||||||
|
/** 支付订单编号 */
|
||||||
|
payOrderId?: null | number;
|
||||||
|
/** 是否已支付 */
|
||||||
|
payStatus?: boolean;
|
||||||
|
/** 付款时间 */
|
||||||
|
payTime?: Date | null;
|
||||||
|
/** 支付渠道 */
|
||||||
|
payChannelCode?: string;
|
||||||
|
/** 商品原价(总) */
|
||||||
|
totalPrice?: null | number;
|
||||||
|
/** 订单优惠(总) */
|
||||||
|
discountPrice?: null | number;
|
||||||
|
/** 运费金额 */
|
||||||
|
deliveryPrice?: null | number;
|
||||||
|
/** 订单调价(总) */
|
||||||
|
adjustPrice?: null | number;
|
||||||
|
/** 应付金额(总) */
|
||||||
|
payPrice?: null | number;
|
||||||
|
/** 发货方式 */
|
||||||
|
deliveryType?: null | number;
|
||||||
|
/** 自提门店编号 */
|
||||||
|
pickUpStoreId?: number;
|
||||||
|
/** 自提核销码 */
|
||||||
|
pickUpVerifyCode?: string;
|
||||||
|
/** 配送模板编号 */
|
||||||
|
deliveryTemplateId?: null | number;
|
||||||
|
/** 发货物流公司编号 */
|
||||||
|
logisticsId?: null | number;
|
||||||
|
/** 发货物流单号 */
|
||||||
|
logisticsNo?: string;
|
||||||
|
/** 发货时间 */
|
||||||
|
deliveryTime?: Date | null;
|
||||||
|
/** 收货时间 */
|
||||||
|
receiveTime?: Date | null;
|
||||||
|
/** 收件人名称 */
|
||||||
|
receiverName?: string;
|
||||||
|
/** 收件人手机 */
|
||||||
|
receiverMobile?: string;
|
||||||
|
/** 收件人邮编 */
|
||||||
|
receiverPostCode?: null | number;
|
||||||
|
/** 收件人地区编号 */
|
||||||
|
receiverAreaId?: null | number;
|
||||||
|
/** 收件人地区名字 */
|
||||||
|
receiverAreaName?: string;
|
||||||
|
/** 收件人详细地址 */
|
||||||
|
receiverDetailAddress?: string;
|
||||||
|
/** 售后状态 */
|
||||||
|
afterSaleStatus?: null | number;
|
||||||
|
/** 退款金额 */
|
||||||
|
refundPrice?: null | number;
|
||||||
|
/** 优惠劵编号 */
|
||||||
|
couponId?: null | number;
|
||||||
|
/** 优惠劵减免金额 */
|
||||||
|
couponPrice?: null | number;
|
||||||
|
/** 积分抵扣的金额 */
|
||||||
|
pointPrice?: null | number;
|
||||||
|
/** VIP 减免金额 */
|
||||||
|
vipPrice?: null | number;
|
||||||
|
/** 订单项列表 */
|
||||||
|
items?: OrderItem[];
|
||||||
|
/** 下单用户信息 */
|
||||||
|
user?: {
|
||||||
|
/** 用户头像 */
|
||||||
|
avatar?: string;
|
||||||
|
/** 用户编号 */
|
||||||
|
id?: null | number;
|
||||||
|
/** 用户昵称 */
|
||||||
|
nickname?: string;
|
||||||
|
};
|
||||||
|
/** 推广用户信息 */
|
||||||
|
brokerageUser?: {
|
||||||
|
/** 用户头像 */
|
||||||
|
avatar?: string;
|
||||||
|
/** 用户编号 */
|
||||||
|
id?: null | number;
|
||||||
|
/** 用户昵称 */
|
||||||
|
nickname?: string;
|
||||||
|
};
|
||||||
|
/** 订单操作日志 */
|
||||||
|
logs?: OrderLog[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 交易订单统计 */
|
||||||
|
export interface OrderSummary {
|
||||||
|
/** 订单数量 */
|
||||||
|
orderCount: number;
|
||||||
|
/** 订单金额 */
|
||||||
|
orderPayPrice: number;
|
||||||
|
/** 退款单数 */
|
||||||
|
afterSaleCount: number;
|
||||||
|
/** 退款金额 */
|
||||||
|
afterSalePrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单发货请求 */
|
||||||
|
export interface DeliveryRequest {
|
||||||
|
/** 订单编号 */
|
||||||
|
id?: number;
|
||||||
|
/** 发货方式 */
|
||||||
|
expressType: string;
|
||||||
|
/** 物流公司编号 */
|
||||||
|
logisticsId: null | number;
|
||||||
|
/** 物流编号 */
|
||||||
|
logisticsNo: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单备注请求 */
|
||||||
|
export interface RemarkRequest {
|
||||||
|
/** 订单编号 */
|
||||||
|
id: number;
|
||||||
|
/** 备注 */
|
||||||
|
remark: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单调价请求 */
|
||||||
|
export interface PriceRequest {
|
||||||
|
/** 订单编号 */
|
||||||
|
id: number;
|
||||||
|
/** 调整金额,单位:分 */
|
||||||
|
adjustPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单地址请求 */
|
||||||
|
export interface AddressRequest {
|
||||||
|
/** 订单编号 */
|
||||||
|
id: number;
|
||||||
|
/** 收件人名称 */
|
||||||
|
receiverName: string;
|
||||||
|
/** 收件人手机 */
|
||||||
|
receiverMobile: string;
|
||||||
|
/** 收件人地区编号 */
|
||||||
|
receiverAreaId: number;
|
||||||
|
/** 收件人详细地址 */
|
||||||
|
receiverDetailAddress: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询交易订单列表 */
|
||||||
|
export function getOrderPage(params: PageParam) {
|
||||||
|
return requestClient.get<PageResult<MallOrderApi.Order>>(
|
||||||
|
'/trade/order/page',
|
||||||
|
{
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询交易订单统计 */
|
||||||
|
export function getOrderSummary(params: PageParam) {
|
||||||
|
return requestClient.get<MallOrderApi.OrderSummary>('/trade/order/summary', {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询交易订单详情 */
|
||||||
|
export function getOrder(id: number) {
|
||||||
|
return requestClient.get<MallOrderApi.Order>(
|
||||||
|
`/trade/order/get-detail?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询交易订单物流详情 */
|
||||||
|
export function getExpressTrackList(id: number) {
|
||||||
|
return requestClient.get(`/trade/order/get-express-track-list?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单发货 */
|
||||||
|
export function deliveryOrder(data: MallOrderApi.DeliveryRequest) {
|
||||||
|
return requestClient.put('/trade/order/delivery', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单备注 */
|
||||||
|
export function updateOrderRemark(data: MallOrderApi.RemarkRequest) {
|
||||||
|
return requestClient.put('/trade/order/update-remark', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单调价 */
|
||||||
|
export function updateOrderPrice(data: MallOrderApi.PriceRequest) {
|
||||||
|
return requestClient.put('/trade/order/update-price', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改订单地址 */
|
||||||
|
export function updateOrderAddress(data: MallOrderApi.AddressRequest) {
|
||||||
|
return requestClient.put('/trade/order/update-address', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单核销 */
|
||||||
|
export function pickUpOrder(id: number) {
|
||||||
|
return requestClient.put(`/trade/order/pick-up-by-id?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单核销 */
|
||||||
|
export function pickUpOrderByVerifyCode(pickUpVerifyCode: string) {
|
||||||
|
return requestClient.put('/trade/order/pick-up-by-verify-code', {
|
||||||
|
params: { pickUpVerifyCode },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询核销码对应的订单 */
|
||||||
|
export function getOrderByPickUpVerifyCode(pickUpVerifyCode: string) {
|
||||||
|
return requestClient.get<MallOrderApi.Order>(
|
||||||
|
'/trade/order/get-by-pick-up-verify-code',
|
||||||
|
{ params: { pickUpVerifyCode } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { isDocAlertEnable } from '@vben/hooks';
|
|
||||||
import { openWindow } from '@vben/utils';
|
|
||||||
|
|
||||||
import { Alert, Typography } from 'ant-design-vue';
|
|
||||||
|
|
||||||
export interface DocAlertProps {
|
|
||||||
/**
|
|
||||||
* 文档标题
|
|
||||||
*/
|
|
||||||
title: string;
|
|
||||||
/**
|
|
||||||
* 文档 URL 地址
|
|
||||||
*/
|
|
||||||
url: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<DocAlertProps>();
|
|
||||||
|
|
||||||
/** 跳转 URL 链接 */
|
|
||||||
const goToUrl = () => {
|
|
||||||
openWindow(props.url);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Alert v-if="isDocAlertEnable()" type="info" show-icon class="mb-2 rounded">
|
|
||||||
<template #message>
|
|
||||||
<Typography.Link @click="goToUrl">
|
|
||||||
【{{ title }}】文档地址:{{ url }}
|
|
||||||
</Typography.Link>
|
|
||||||
</template>
|
|
||||||
</Alert>
|
|
||||||
</template>
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export { default as DocAlert } from './doc-alert.vue';
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { ref } from 'vue';
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { handleTree } from '@vben/utils';
|
import { handleTree } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, Card, Col, Row, Tree } from 'ant-design-vue';
|
import { Card, Col, Row, Tree } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getSimpleDeptList } from '#/api/system/dept';
|
import { getSimpleDeptList } from '#/api/system/dept';
|
||||||
|
|
||||||
|
|
@ -41,24 +41,6 @@ const emit = defineEmits<{
|
||||||
confirm: [deptList: SystemDeptApi.Dept[]];
|
confirm: [deptList: SystemDeptApi.Dept[]];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 对话框配置
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
title: props.title,
|
|
||||||
async onOpenChange(isOpen: boolean) {
|
|
||||||
if (!isOpen) {
|
|
||||||
resetData();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
modalApi.setState({ loading: true });
|
|
||||||
try {
|
|
||||||
deptData.value = await getSimpleDeptList();
|
|
||||||
deptTree.value = handleTree(deptData.value) as DataNode[];
|
|
||||||
} finally {
|
|
||||||
modalApi.setState({ loading: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroyOnClose: true,
|
|
||||||
});
|
|
||||||
type checkedKeys = number[] | { checked: number[]; halfChecked: number[] };
|
type checkedKeys = number[] | { checked: number[]; halfChecked: number[] };
|
||||||
// 部门树形结构
|
// 部门树形结构
|
||||||
const deptTree = ref<DataNode[]>([]);
|
const deptTree = ref<DataNode[]>([]);
|
||||||
|
|
@ -67,25 +49,56 @@ const selectedDeptIds = ref<checkedKeys>([]);
|
||||||
// 部门数据
|
// 部门数据
|
||||||
const deptData = ref<SystemDeptApi.Dept[]>([]);
|
const deptData = ref<SystemDeptApi.Dept[]>([]);
|
||||||
|
|
||||||
/** 打开对话框 */
|
// 对话框配置
|
||||||
const open = async (selectedList?: SystemDeptApi.Dept[]) => {
|
const [Modal, modalApi] = useVbenModal({
|
||||||
modalApi.open();
|
async onConfirm() {
|
||||||
// // 设置已选择的部门
|
// 获取选中的部门ID
|
||||||
if (selectedList?.length) {
|
const selectedIds: number[] = Array.isArray(selectedDeptIds.value)
|
||||||
const selectedIds = selectedList
|
? selectedDeptIds.value
|
||||||
.map((dept) => dept.id)
|
: selectedDeptIds.value.checked || [];
|
||||||
.filter((id): id is number => id !== undefined);
|
const deptArray = deptData.value.filter((dept) =>
|
||||||
selectedDeptIds.value = props.checkStrictly
|
selectedIds.includes(dept.id!),
|
||||||
? {
|
);
|
||||||
checked: selectedIds,
|
emit('confirm', deptArray);
|
||||||
halfChecked: [],
|
// 关闭并提示
|
||||||
}
|
await modalApi.close();
|
||||||
: selectedIds;
|
},
|
||||||
}
|
async onOpenChange(isOpen: boolean) {
|
||||||
};
|
if (!isOpen) {
|
||||||
|
deptTree.value = [];
|
||||||
|
selectedDeptIds.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 加载数据
|
||||||
|
const data = modalApi.getData();
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modalApi.lock();
|
||||||
|
try {
|
||||||
|
deptData.value = await getSimpleDeptList();
|
||||||
|
deptTree.value = handleTree(deptData.value) as DataNode[];
|
||||||
|
// // 设置已选择的部门
|
||||||
|
if (data.selectedList?.length) {
|
||||||
|
const selectedIds = data.selectedList
|
||||||
|
.map((dept: SystemDeptApi.Dept) => dept.id)
|
||||||
|
.filter((id: number) => id !== undefined);
|
||||||
|
selectedDeptIds.value = props.checkStrictly
|
||||||
|
? {
|
||||||
|
checked: selectedIds,
|
||||||
|
halfChecked: [],
|
||||||
|
}
|
||||||
|
: selectedIds;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
modalApi.unlock();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
/** 处理选中状态变化 */
|
/** 处理选中状态变化 */
|
||||||
const handleCheck = () => {
|
function handleCheck() {
|
||||||
if (!props.multiple) {
|
if (!props.multiple) {
|
||||||
// 单选模式下,只保留最后选择的节点
|
// 单选模式下,只保留最后选择的节点
|
||||||
if (Array.isArray(selectedDeptIds.value)) {
|
if (Array.isArray(selectedDeptIds.value)) {
|
||||||
|
|
@ -106,37 +119,10 @@ const handleCheck = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 提交选择 */
|
|
||||||
const handleConfirm = async () => {
|
|
||||||
// 获取选中的部门ID
|
|
||||||
const selectedIds: number[] = Array.isArray(selectedDeptIds.value)
|
|
||||||
? selectedDeptIds.value
|
|
||||||
: selectedDeptIds.value.checked || [];
|
|
||||||
const deptArray = deptData.value.filter((dept) =>
|
|
||||||
selectedIds.includes(dept.id!),
|
|
||||||
);
|
|
||||||
// 关闭并提示
|
|
||||||
await modalApi.close();
|
|
||||||
emit('confirm', deptArray);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
modalApi.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 重置数据 */
|
|
||||||
const resetData = () => {
|
|
||||||
deptTree.value = [];
|
|
||||||
selectedDeptIds.value = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 提供 open 方法,用于打开对话框 */
|
|
||||||
defineExpose({ open });
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Modal>
|
<Modal :title="title" key="dept-select-modal" class="w-[40%]">
|
||||||
<Row class="h-full">
|
<Row class="h-full">
|
||||||
<Col :span="24">
|
<Col :span="24">
|
||||||
<Card class="h-full">
|
<Card class="h-full">
|
||||||
|
|
@ -153,9 +139,5 @@ defineExpose({ open });
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<template #footer>
|
|
||||||
<Button @click="handleCancel">{{ cancelText }}</Button>
|
|
||||||
<Button type="primary" @click="handleConfirm">{{ confirmText }}</Button>
|
|
||||||
</template>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// TODO @芋艿:是否有更好的组织形式?!
|
// TODO @芋艿:是否有更好的组织形式?!
|
||||||
|
// TODO @xingyu:你感觉,这个放到每个 system、infra 模块下,然后新建一个 components,表示每个模块,有一些共享的组件?然后,全局只放通用的(无业务含义的),可以哇?
|
||||||
import type { Key } from 'ant-design-vue/es/table/interface';
|
import type { Key } from 'ant-design-vue/es/table/interface';
|
||||||
|
|
||||||
import type { SystemDeptApi } from '#/api/system/dept';
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
|
@ -17,7 +18,6 @@ import {
|
||||||
message,
|
message,
|
||||||
Pagination,
|
Pagination,
|
||||||
Row,
|
Row,
|
||||||
Spin,
|
|
||||||
Transfer,
|
Transfer,
|
||||||
Tree,
|
Tree,
|
||||||
} from 'ant-design-vue';
|
} from 'ant-design-vue';
|
||||||
|
|
@ -66,16 +66,66 @@ const expandedKeys = ref<Key[]>([]);
|
||||||
const selectedDeptId = ref<number>();
|
const selectedDeptId = ref<number>();
|
||||||
const deptSearchKeys = ref('');
|
const deptSearchKeys = ref('');
|
||||||
|
|
||||||
// 加载状态
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
// 用户数据管理
|
// 用户数据管理
|
||||||
const userList = ref<SystemUserApi.User[]>([]); // 存储所有已知用户
|
const userList = ref<SystemUserApi.User[]>([]); // 存储所有已知用户
|
||||||
const selectedUserIds = ref<string[]>([]);
|
const selectedUserIds = ref<string[]>([]);
|
||||||
|
|
||||||
|
// 弹窗配置
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
onCancel: handleCancel,
|
||||||
|
onClosed: handleClosed,
|
||||||
|
async onOpenChange(isOpen: boolean) {
|
||||||
|
if (!isOpen) {
|
||||||
|
resetData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 加载数据
|
||||||
|
const data = modalApi.getData();
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modalApi.lock();
|
||||||
|
try {
|
||||||
|
// 加载部门数据
|
||||||
|
const deptData = await getSimpleDeptList();
|
||||||
|
deptList.value = deptData;
|
||||||
|
const treeData = handleTree(deptData);
|
||||||
|
deptTree.value = treeData.map((node) => processDeptNode(node));
|
||||||
|
expandedKeys.value = deptTree.value.map((node) => node.key);
|
||||||
|
|
||||||
|
// 加载初始用户数据
|
||||||
|
await loadUserData(1, leftListState.value.pagination.pageSize);
|
||||||
|
|
||||||
|
// 设置已选用户
|
||||||
|
if (data.userIds?.length) {
|
||||||
|
selectedUserIds.value = data.userIds.map(String);
|
||||||
|
// 加载已选用户的完整信息 TODO 目前接口暂不支持 多个用户ID 查询, 需要后端支持
|
||||||
|
const { list } = await getUserPage({
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 100, // 临时使用固定值确保能加载所有已选用户
|
||||||
|
userIds: data.userIds,
|
||||||
|
});
|
||||||
|
// 使用 Map 来去重,以用户 ID 为 key
|
||||||
|
const userMap = new Map(userList.value.map((user) => [user.id, user]));
|
||||||
|
list.forEach((user) => {
|
||||||
|
if (!userMap.has(user.id)) {
|
||||||
|
userMap.set(user.id, user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
userList.value = [...userMap.values()];
|
||||||
|
updateRightListData();
|
||||||
|
}
|
||||||
|
|
||||||
|
modalApi.open();
|
||||||
|
} finally {
|
||||||
|
modalApi.unlock();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
// 左侧列表状态
|
// 左侧列表状态
|
||||||
const leftListState = ref({
|
const leftListState = ref({
|
||||||
loading: false,
|
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
dataSource: [] as SystemUserApi.User[],
|
dataSource: [] as SystemUserApi.User[],
|
||||||
pagination: {
|
pagination: {
|
||||||
|
|
@ -145,8 +195,7 @@ const filteredDeptTree = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载用户数据
|
// 加载用户数据
|
||||||
const loadUserData = async (pageNo: number, pageSize: number) => {
|
async function loadUserData(pageNo: number, pageSize: number) {
|
||||||
leftListState.value.loading = true;
|
|
||||||
try {
|
try {
|
||||||
const { list, total } = await getUserPage({
|
const { list, total } = await getUserPage({
|
||||||
pageNo,
|
pageNo,
|
||||||
|
|
@ -167,13 +216,11 @@ const loadUserData = async (pageNo: number, pageSize: number) => {
|
||||||
if (newUsers.length > 0) {
|
if (newUsers.length > 0) {
|
||||||
userList.value.push(...newUsers);
|
userList.value.push(...newUsers);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {}
|
||||||
leftListState.value.loading = false;
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新右侧列表数据
|
// 更新右侧列表数据
|
||||||
const updateRightListData = () => {
|
function updateRightListData() {
|
||||||
// 使用 Set 来去重选中的用户ID
|
// 使用 Set 来去重选中的用户ID
|
||||||
const uniqueSelectedIds = new Set(selectedUserIds.value);
|
const uniqueSelectedIds = new Set(selectedUserIds.value);
|
||||||
|
|
||||||
|
|
@ -202,22 +249,22 @@ const updateRightListData = () => {
|
||||||
const endIndex = startIndex + pageSize;
|
const endIndex = startIndex + pageSize;
|
||||||
|
|
||||||
rightListState.value.dataSource = filteredUsers.slice(startIndex, endIndex);
|
rightListState.value.dataSource = filteredUsers.slice(startIndex, endIndex);
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理左侧分页变化
|
// 处理左侧分页变化
|
||||||
const handleLeftPaginationChange = async (page: number, pageSize: number) => {
|
async function handleLeftPaginationChange(page: number, pageSize: number) {
|
||||||
await loadUserData(page, pageSize);
|
await loadUserData(page, pageSize);
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理右侧分页变化
|
// 处理右侧分页变化
|
||||||
const handleRightPaginationChange = (page: number, pageSize: number) => {
|
function handleRightPaginationChange(page: number, pageSize: number) {
|
||||||
rightListState.value.pagination.current = page;
|
rightListState.value.pagination.current = page;
|
||||||
rightListState.value.pagination.pageSize = pageSize;
|
rightListState.value.pagination.pageSize = pageSize;
|
||||||
updateRightListData();
|
updateRightListData();
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理用户搜索
|
// 处理用户搜索
|
||||||
const handleUserSearch = async (direction: string, value: string) => {
|
async function handleUserSearch(direction: string, value: string) {
|
||||||
if (direction === 'left') {
|
if (direction === 'left') {
|
||||||
leftListState.value.searchValue = value;
|
leftListState.value.searchValue = value;
|
||||||
leftListState.value.pagination.current = 1;
|
leftListState.value.pagination.current = 1;
|
||||||
|
|
@ -227,18 +274,18 @@ const handleUserSearch = async (direction: string, value: string) => {
|
||||||
rightListState.value.pagination.current = 1;
|
rightListState.value.pagination.current = 1;
|
||||||
updateRightListData();
|
updateRightListData();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理用户选择变化
|
// 处理用户选择变化
|
||||||
const handleUserChange = (targetKeys: string[]) => {
|
function handleUserChange(targetKeys: string[]) {
|
||||||
// 使用 Set 来去重选中的用户ID
|
// 使用 Set 来去重选中的用户ID
|
||||||
selectedUserIds.value = [...new Set(targetKeys)];
|
selectedUserIds.value = [...new Set(targetKeys)];
|
||||||
emit('update:value', selectedUserIds.value.map(Number));
|
emit('update:value', selectedUserIds.value.map(Number));
|
||||||
updateRightListData();
|
updateRightListData();
|
||||||
};
|
}
|
||||||
|
|
||||||
// 重置数据
|
// 重置数据
|
||||||
const resetData = () => {
|
function resetData() {
|
||||||
userList.value = [];
|
userList.value = [];
|
||||||
selectedUserIds.value = [];
|
selectedUserIds.value = [];
|
||||||
|
|
||||||
|
|
@ -249,7 +296,6 @@ const resetData = () => {
|
||||||
selectedUserIds.value = [];
|
selectedUserIds.value = [];
|
||||||
|
|
||||||
leftListState.value = {
|
leftListState.value = {
|
||||||
loading: false,
|
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
dataSource: [],
|
dataSource: [],
|
||||||
pagination: {
|
pagination: {
|
||||||
|
|
@ -268,61 +314,20 @@ const resetData = () => {
|
||||||
total: 0,
|
total: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
// 打开弹窗
|
|
||||||
const open = async (userIds: string[]) => {
|
|
||||||
resetData();
|
|
||||||
loading.value = true;
|
|
||||||
try {
|
|
||||||
// 加载部门数据
|
|
||||||
const deptData = await getSimpleDeptList();
|
|
||||||
deptList.value = deptData;
|
|
||||||
const treeData = handleTree(deptData);
|
|
||||||
deptTree.value = treeData.map((node) => processDeptNode(node));
|
|
||||||
expandedKeys.value = deptTree.value.map((node) => node.key);
|
|
||||||
|
|
||||||
// 加载初始用户数据
|
|
||||||
await loadUserData(1, leftListState.value.pagination.pageSize);
|
|
||||||
|
|
||||||
// 设置已选用户
|
|
||||||
if (userIds?.length) {
|
|
||||||
selectedUserIds.value = userIds.map(String);
|
|
||||||
// 加载已选用户的完整信息 TODO 目前接口暂不支持 多个用户ID 查询, 需要后端支持
|
|
||||||
const { list } = await getUserPage({
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 100, // 临时使用固定值确保能加载所有已选用户
|
|
||||||
userIds,
|
|
||||||
});
|
|
||||||
// 使用 Map 来去重,以用户 ID 为 key
|
|
||||||
const userMap = new Map(userList.value.map((user) => [user.id, user]));
|
|
||||||
list.forEach((user) => {
|
|
||||||
if (!userMap.has(user.id)) {
|
|
||||||
userMap.set(user.id, user);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
userList.value = [...userMap.values()];
|
|
||||||
updateRightListData();
|
|
||||||
}
|
|
||||||
|
|
||||||
modalApi.open();
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO 后端接口目前仅支持 username 检索, 筛选条件需要跟后端请求参数保持一致。
|
// TODO 后端接口目前仅支持 username 检索, 筛选条件需要跟后端请求参数保持一致。
|
||||||
const filterOption = (inputValue: string, option: any) => {
|
function filterOption(inputValue: string, option: any) {
|
||||||
return option.username.toLowerCase().includes(inputValue.toLowerCase());
|
return option.username.toLowerCase().includes(inputValue.toLowerCase());
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理部门树展开/折叠
|
// 处理部门树展开/折叠
|
||||||
const handleExpand = (keys: Key[]) => {
|
function handleExpand(keys: Key[]) {
|
||||||
expandedKeys.value = keys;
|
expandedKeys.value = keys;
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理部门搜索
|
// 处理部门搜索
|
||||||
const handleDeptSearch = (value: string) => {
|
function handleDeptSearch(value: string) {
|
||||||
deptSearchKeys.value = value;
|
deptSearchKeys.value = value;
|
||||||
|
|
||||||
// 如果有搜索结果,自动展开所有节点
|
// 如果有搜索结果,自动展开所有节点
|
||||||
|
|
@ -342,10 +347,10 @@ const handleDeptSearch = (value: string) => {
|
||||||
// 清空搜索时,只展开第一级节点
|
// 清空搜索时,只展开第一级节点
|
||||||
expandedKeys.value = deptTree.value.map((node) => node.key);
|
expandedKeys.value = deptTree.value.map((node) => node.key);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// 处理部门选择
|
// 处理部门选择
|
||||||
const handleDeptSelect = async (selectedKeys: Key[], _info: any) => {
|
async function handleDeptSelect(selectedKeys: Key[], _info: any) {
|
||||||
// 更新选中的部门ID
|
// 更新选中的部门ID
|
||||||
const newDeptId =
|
const newDeptId =
|
||||||
selectedKeys.length > 0 ? Number(selectedKeys[0]) : undefined;
|
selectedKeys.length > 0 ? Number(selectedKeys[0]) : undefined;
|
||||||
|
|
@ -356,10 +361,10 @@ const handleDeptSelect = async (selectedKeys: Key[], _info: any) => {
|
||||||
const { pageSize } = leftListState.value.pagination;
|
const { pageSize } = leftListState.value.pagination;
|
||||||
leftListState.value.pagination.current = 1;
|
leftListState.value.pagination.current = 1;
|
||||||
await loadUserData(1, pageSize);
|
await loadUserData(1, pageSize);
|
||||||
};
|
}
|
||||||
|
|
||||||
// 确认选择
|
// 确认选择
|
||||||
const handleConfirm = () => {
|
function handleConfirm() {
|
||||||
if (selectedUserIds.value.length === 0) {
|
if (selectedUserIds.value.length === 0) {
|
||||||
message.warning('请选择用户');
|
message.warning('请选择用户');
|
||||||
return;
|
return;
|
||||||
|
|
@ -371,115 +376,101 @@ const handleConfirm = () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
modalApi.close();
|
modalApi.close();
|
||||||
};
|
}
|
||||||
|
|
||||||
// 取消选择
|
// 取消选择
|
||||||
const handleCancel = () => {
|
function handleCancel() {
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
modalApi.close();
|
modalApi.close();
|
||||||
// 确保在动画结束后再重置数据
|
// 确保在动画结束后再重置数据
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resetData();
|
resetData();
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
}
|
||||||
|
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const handleClosed = () => {
|
function handleClosed() {
|
||||||
emit('closed');
|
emit('closed');
|
||||||
resetData();
|
resetData();
|
||||||
};
|
}
|
||||||
|
|
||||||
// 弹窗配置
|
|
||||||
const [ModalComponent, modalApi] = useVbenModal({
|
|
||||||
title: props.title,
|
|
||||||
onCancel: handleCancel,
|
|
||||||
onClosed: handleClosed,
|
|
||||||
destroyOnClose: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 递归处理部门树节点
|
// 递归处理部门树节点
|
||||||
const processDeptNode = (node: any): DeptTreeNode => {
|
function processDeptNode(node: any): DeptTreeNode {
|
||||||
return {
|
return {
|
||||||
key: String(node.id),
|
key: String(node.id),
|
||||||
title: `${node.name} (${node.id})`,
|
title: `${node.name} (${node.id})`,
|
||||||
name: node.name,
|
name: node.name,
|
||||||
children: node.children?.map((child: any) => processDeptNode(child)),
|
children: node.children?.map((child: any) => processDeptNode(child)),
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open,
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ModalComponent class="w-[1000px]" key="user-select-modal">
|
<Modal class="w-[40%]" key="user-select-modal" :title="title">
|
||||||
<Spin :spinning="loading">
|
<Row :gutter="[16, 16]">
|
||||||
<Row :gutter="[16, 16]">
|
<Col :span="6">
|
||||||
<Col :span="6">
|
<div class="h-[500px] overflow-auto rounded border">
|
||||||
<div class="h-[500px] overflow-auto rounded border">
|
<div class="border-b p-2">
|
||||||
<div class="border-b p-2">
|
<Input
|
||||||
<Input
|
v-model:value="deptSearchKeys"
|
||||||
v-model:value="deptSearchKeys"
|
placeholder="搜索部门"
|
||||||
placeholder="搜索部门"
|
allow-clear
|
||||||
allow-clear
|
@input="(e) => handleDeptSearch(e.target?.value ?? '')"
|
||||||
@input="(e) => handleDeptSearch(e.target?.value ?? '')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Tree
|
|
||||||
:tree-data="filteredDeptTree"
|
|
||||||
:expanded-keys="expandedKeys"
|
|
||||||
:selected-keys="selectedDeptId ? [String(selectedDeptId)] : []"
|
|
||||||
@select="handleDeptSelect"
|
|
||||||
@expand="handleExpand"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
<Tree
|
||||||
<Col :span="18">
|
:tree-data="filteredDeptTree"
|
||||||
<Transfer
|
:expanded-keys="expandedKeys"
|
||||||
:row-key="(record) => String(record.id)"
|
:selected-keys="selectedDeptId ? [String(selectedDeptId)] : []"
|
||||||
:data-source="transferDataSource"
|
@select="handleDeptSelect"
|
||||||
v-model:target-keys="selectedUserIds"
|
@expand="handleExpand"
|
||||||
:titles="['未选', '已选']"
|
/>
|
||||||
:show-search="true"
|
</div>
|
||||||
:show-select-all="true"
|
</Col>
|
||||||
:filter-option="filterOption"
|
<Col :span="18">
|
||||||
@change="handleUserChange"
|
<Transfer
|
||||||
@search="handleUserSearch"
|
:row-key="(record) => String(record.id)"
|
||||||
>
|
:data-source="transferDataSource"
|
||||||
<template #render="item">
|
v-model:target-keys="selectedUserIds"
|
||||||
<span>{{ item?.nickname }} ({{ item?.username }})</span>
|
:titles="['未选', '已选']"
|
||||||
</template>
|
:show-search="true"
|
||||||
|
:show-select-all="true"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
@change="handleUserChange"
|
||||||
|
@search="handleUserSearch"
|
||||||
|
>
|
||||||
|
<template #render="item">
|
||||||
|
<span>{{ item?.nickname }} ({{ item?.username }})</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #footer="{ direction }">
|
<template #footer="{ direction }">
|
||||||
<div v-if="direction === 'left'">
|
<div v-if="direction === 'left'">
|
||||||
<Pagination
|
<Pagination
|
||||||
v-model:current="leftListState.pagination.current"
|
v-model:current="leftListState.pagination.current"
|
||||||
v-model:page-size="leftListState.pagination.pageSize"
|
v-model:page-size="leftListState.pagination.pageSize"
|
||||||
:total="leftListState.pagination.total"
|
:total="leftListState.pagination.total"
|
||||||
:show-size-changer="true"
|
:show-size-changer="true"
|
||||||
:show-total="(total) => `共 ${total} 条`"
|
:show-total="(total) => `共 ${total} 条`"
|
||||||
size="small"
|
size="small"
|
||||||
@change="handleLeftPaginationChange"
|
@change="handleLeftPaginationChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="direction === 'right'">
|
<div v-if="direction === 'right'">
|
||||||
<Pagination
|
<Pagination
|
||||||
v-model:current="rightListState.pagination.current"
|
v-model:current="rightListState.pagination.current"
|
||||||
v-model:page-size="rightListState.pagination.pageSize"
|
v-model:page-size="rightListState.pagination.pageSize"
|
||||||
:total="rightListState.pagination.total"
|
:total="rightListState.pagination.total"
|
||||||
:show-size-changer="true"
|
:show-size-changer="true"
|
||||||
:show-total="(total) => `共 ${total} 条`"
|
:show-total="(total) => `共 ${total} 条`"
|
||||||
size="small"
|
size="small"
|
||||||
@change="handleRightPaginationChange"
|
@change="handleRightPaginationChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Transfer>
|
</Transfer>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Spin>
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|
@ -490,7 +481,7 @@ defineExpose({
|
||||||
</Button>
|
</Button>
|
||||||
<Button @click="handleCancel">{{ cancelText }}</Button>
|
<Button @click="handleCancel">{{ cancelText }}</Button>
|
||||||
</template>
|
</template>
|
||||||
</ModalComponent>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ function getRouterNode(node: any) {
|
||||||
defineExpose({ openDrawer }); // 暴露方法给父组件
|
defineExpose({ openDrawer }); // 暴露方法给父组件
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Drawer class="w-[630px]">
|
<Drawer class="w-[40%]">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<Input
|
<Input
|
||||||
|
|
|
||||||
|
|
@ -1074,7 +1074,7 @@ onMounted(() => {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="currentNode.type === NodeType.USER_TASK_NODE">
|
<div v-if="currentNode.type === BpmNodeTypeEnum.USER_TASK_NODE">
|
||||||
<Divider content-position="left">是否需要签名</Divider>
|
<Divider content-position="left">是否需要签名</Divider>
|
||||||
<FormItem name="signEnable">
|
<FormItem name="signEnable">
|
||||||
<Switch
|
<Switch
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
// TODO @芋艿:后续是不是把业务组件,挪到每个模块里;待定;
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
|
|
||||||
import type { SimpleFlowNode } from '../../consts';
|
import type { SimpleFlowNode } from '../../consts';
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ defineExpose({ validate });
|
||||||
:readonly="false"
|
:readonly="false"
|
||||||
@save="saveSimpleFlowModel"
|
@save="saveSimpleFlowModel"
|
||||||
/>
|
/>
|
||||||
<ErrorModal title="流程设计校验不通过" class="w-[600px]">
|
<ErrorModal title="流程设计校验不通过" class="w-[40%]">
|
||||||
<div class="mb-2 text-base">以下节点配置不完善,请修改相关配置</div>
|
<div class="mb-2 text-base">以下节点配置不完善,请修改相关配置</div>
|
||||||
<div
|
<div
|
||||||
class="mb-3 rounded-md bg-gray-100 p-2 text-sm"
|
class="mb-3 rounded-md bg-gray-100 p-2 text-sm"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as SummaryCard } from './summary-card.vue';
|
||||||
|
export type { SummaryCardProps } from './typing';
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { SummaryCardProps } from './typing';
|
||||||
|
|
||||||
|
import { CountTo } from '@vben/common-ui';
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { Tooltip } from 'ant-design-vue';
|
||||||
|
|
||||||
|
/** 统计卡片 */
|
||||||
|
defineOptions({ name: 'SummaryCard' });
|
||||||
|
|
||||||
|
defineProps<SummaryCardProps>();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="flex flex-row items-center gap-3 rounded bg-[var(--el-bg-color-overlay)] p-4"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="rounded-1 flex h-12 w-12 flex-shrink-0 items-center justify-center"
|
||||||
|
:class="`${iconColor} ${iconBgColor}`"
|
||||||
|
>
|
||||||
|
<IconifyIcon v-if="icon" :icon="icon" class="!text-6" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<span class="text-3.5">{{ title }}</span>
|
||||||
|
<Tooltip :content="tooltip" placement="topLeft" v-if="tooltip">
|
||||||
|
<IconifyIcon icon="ep:warning" class="item-center !text-3 flex" />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row items-baseline gap-2">
|
||||||
|
<div class="text-7">
|
||||||
|
<CountTo
|
||||||
|
:prefix="prefix"
|
||||||
|
:end-val="value ?? 0"
|
||||||
|
:decimals="decimals ?? 0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="percent !== undefined"
|
||||||
|
:class="Number(percent) > 0 ? 'text-red-500' : 'text-green-500'"
|
||||||
|
>
|
||||||
|
<span class="text-sm">{{ Math.abs(Number(percent)) }}%</span>
|
||||||
|
<IconifyIcon
|
||||||
|
:icon="Number(percent) > 0 ? 'ep:caret-top' : 'ep:caret-bottom'"
|
||||||
|
class="!text-3 ml-0.5"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
export interface SummaryCardProps {
|
||||||
|
title: string;
|
||||||
|
tooltip?: string;
|
||||||
|
icon?: string;
|
||||||
|
iconColor?: string;
|
||||||
|
iconBgColor?: string;
|
||||||
|
prefix?: string;
|
||||||
|
value?: number;
|
||||||
|
decimals?: number;
|
||||||
|
percent?: number | string;
|
||||||
|
}
|
||||||
|
|
@ -100,7 +100,6 @@ async function handleRemove(file: UploadFile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function beforeUpload(file: File) {
|
async function beforeUpload(file: File) {
|
||||||
// 使用现代的Blob.text()方法替代FileReader
|
|
||||||
const fileContent = await file.text();
|
const fileContent = await file.text();
|
||||||
emit('returnText', fileContent);
|
emit('returnText', fileContent);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
// TODO @xingyu:这个组件,只有 pay 在用,和现有的 file-upload 和 image-upload 有点不一致。是不是可以考虑移除,只在 pay 那搞个复用的组件;
|
||||||
import type { InputProps, TextAreaProps } from 'ant-design-vue';
|
import type { InputProps, TextAreaProps } from 'ant-design-vue';
|
||||||
|
|
||||||
import type { FileUploadProps } from './typing';
|
import type { FileUploadProps } from './typing';
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,18 @@ const routes: RouteRecordRaw[] = [
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'manager/model/:type/:id',
|
||||||
|
component: () => import('#/views/bpm/model/form/index.vue'),
|
||||||
|
name: 'BpmModelUpdate',
|
||||||
|
meta: {
|
||||||
|
title: '修改流程',
|
||||||
|
activePath: '/bpm/manager/model',
|
||||||
|
icon: 'carbon:flow-connection',
|
||||||
|
hideInMenu: true,
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
// import type { RouteRecordRaw } from 'vue-router';
|
||||||
|
|
||||||
|
// const routes: RouteRecordRaw[] = [
|
||||||
|
// {
|
||||||
|
// path: '/mall/product',
|
||||||
|
// name: 'ProductCenter',
|
||||||
|
// meta: {
|
||||||
|
// title: '商品中心',
|
||||||
|
// icon: 'lucide:shopping-bag',
|
||||||
|
// keepAlive: true,
|
||||||
|
// hideInMenu: true,
|
||||||
|
// },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: 'spu/add',
|
||||||
|
// name: 'ProductSpuAdd',
|
||||||
|
// meta: {
|
||||||
|
// title: '商品添加',
|
||||||
|
// activeMenu: '/mall/product/spu',
|
||||||
|
// },
|
||||||
|
// component: () => import('#/views/mall/product/spu/form/index.vue'),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: String.raw`spu/edit/:id(\d+)`,
|
||||||
|
// name: 'ProductSpuEdit',
|
||||||
|
// meta: {
|
||||||
|
// title: '商品编辑',
|
||||||
|
// activeMenu: '/mall/product/spu',
|
||||||
|
// },
|
||||||
|
// component: () => import('#/views/mall/product/spu/form/index.vue'),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: String.raw`spu/detail/:id(\d+)`,
|
||||||
|
// name: 'ProductSpuDetail',
|
||||||
|
// meta: {
|
||||||
|
// title: '商品详情',
|
||||||
|
// activeMenu: '/crm/business',
|
||||||
|
// },
|
||||||
|
// component: () => import('#/views/mall/product/spu/form/index.vue'),
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/mall/trade',
|
||||||
|
// name: 'TradeCenter',
|
||||||
|
// meta: {
|
||||||
|
// title: '交易中心',
|
||||||
|
// icon: 'lucide:shopping-cart',
|
||||||
|
// keepAlive: true,
|
||||||
|
// hideInMenu: true,
|
||||||
|
// },
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// path: String.raw`order/detail/:id(\d+)`,
|
||||||
|
// name: 'TradeOrderDetail',
|
||||||
|
// meta: {
|
||||||
|
// title: '订单详情',
|
||||||
|
// activeMenu: '/mall/trade/order',
|
||||||
|
// },
|
||||||
|
// component: () => import('#/views/mall/trade/order/detail/index.vue'),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: String.raw`after-sale/detail/:id(\d+)`,
|
||||||
|
// name: 'TradeAfterSaleDetail',
|
||||||
|
// meta: {
|
||||||
|
// title: '退款详情',
|
||||||
|
// activeMenu: '/mall/trade/after-sale',
|
||||||
|
// },
|
||||||
|
// component: () =>
|
||||||
|
// import('#/views/mall/trade/afterSale/detail/index.vue'),
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// export default routes;
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* 下载工具模块
|
* 下载工具模块
|
||||||
* 提供多种文件格式的下载功能
|
* 提供多种文件格式的下载功能
|
||||||
*/
|
*/
|
||||||
// 请使用 @vben/utils/download 代替 packages/@core/base/shared/src/utils/download.ts
|
// TODO @ziye:请使用 @vben/utils/download 代替 packages/@core/base/shared/src/utils/download.ts
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片下载配置接口
|
* 图片下载配置接口
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// TODO @xingyu:感觉 formatToFraction 可以整合起来;【优先级:低】
|
||||||
/**
|
/**
|
||||||
* 将一个整数转换为分数保留两位小数
|
* 将一个整数转换为分数保留两位小数
|
||||||
* @param num
|
* @param num
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
/**
|
|
||||||
* 将毫秒,转换成时间字符串。例如说,xx 分钟
|
|
||||||
*
|
|
||||||
* @param ms 毫秒
|
|
||||||
* @returns {string} 字符串
|
|
||||||
*/
|
|
||||||
// TODO @xingyu:这个要融合到哪里去 date 么?
|
|
||||||
export function formatPast2(ms: number): string {
|
|
||||||
// 定义时间单位常量,便于维护
|
|
||||||
const SECOND = 1000;
|
|
||||||
const MINUTE = 60 * SECOND;
|
|
||||||
const HOUR = 60 * MINUTE;
|
|
||||||
const DAY = 24 * HOUR;
|
|
||||||
|
|
||||||
// 计算各时间单位
|
|
||||||
const day = Math.floor(ms / DAY);
|
|
||||||
const hour = Math.floor((ms % DAY) / HOUR);
|
|
||||||
const minute = Math.floor((ms % HOUR) / MINUTE);
|
|
||||||
const second = Math.floor((ms % MINUTE) / SECOND);
|
|
||||||
|
|
||||||
// 根据时间长短返回不同格式
|
|
||||||
if (day > 0) {
|
|
||||||
return `${day} 天${hour} 小时 ${minute} 分钟`;
|
|
||||||
}
|
|
||||||
if (hour > 0) {
|
|
||||||
return `${hour} 小时 ${minute} 分钟`;
|
|
||||||
}
|
|
||||||
if (minute > 0) {
|
|
||||||
return `${minute} 分钟`;
|
|
||||||
}
|
|
||||||
return second > 0 ? `${second} 秒` : `${0} 秒`;
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,6 @@ export * from './constants';
|
||||||
export * from './dict';
|
export * from './dict';
|
||||||
export * from './download';
|
export * from './download';
|
||||||
export * from './formatNumber';
|
export * from './formatNumber';
|
||||||
export * from './formatTime';
|
|
||||||
export * from './formCreate';
|
export * from './formCreate';
|
||||||
export * from './rangePickerProps';
|
export * from './rangePickerProps';
|
||||||
export * from './routerHelper';
|
export * from './routerHelper';
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { defineAsyncComponent } from 'vue';
|
import { defineAsyncComponent } from 'vue';
|
||||||
|
|
||||||
const modules = import.meta.glob('../views/**/*.{vue,tsx}');
|
const modules = import.meta.glob('../views/**/*.{vue,tsx}');
|
||||||
// TODO @xingyu:这个要不要融合到哪个 router util 里?
|
// TODO @xingyu:这个要不要融合到哪个 router util 里? utils 里面没有引入 vue 使用不了 defineAsyncComponent
|
||||||
/**
|
/**
|
||||||
* 注册一个异步组件
|
* 注册一个异步组件
|
||||||
* @param componentPath 例:/bpm/oa/leave/detail
|
* @param componentPath 例:/bpm/oa/leave/detail
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 对话聊天" url="https://doc.iocoder.cn/ai/chat/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 对话聊天" url="https://doc.iocoder.cn/ai/chat/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 绘图创作" url="https://doc.iocoder.cn/ai/image/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 绘图创作" url="https://doc.iocoder.cn/ai/image/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 知识库" url="https://doc.iocoder.cn/ai/knowledge/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 知识库" url="https://doc.iocoder.cn/ai/knowledge/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 思维导图" url="https://doc.iocoder.cn/ai/mindmap/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 思维导图" url="https://doc.iocoder.cn/ai/mindmap/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 手册" url="https://doc.iocoder.cn/ai/build/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 手册" url="https://doc.iocoder.cn/ai/build/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 对话聊天" url="https://doc.iocoder.cn/ai/chat/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 对话聊天" url="https://doc.iocoder.cn/ai/chat/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 手册" url="https://doc.iocoder.cn/ai/build/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 手册" url="https://doc.iocoder.cn/ai/build/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert
|
<template #doc>
|
||||||
title="AI 工具调用(function calling)"
|
<DocAlert
|
||||||
url="https://doc.iocoder.cn/ai/tool/"
|
title="AI 工具调用(function calling)"
|
||||||
/>
|
url="https://doc.iocoder.cn/ai/tool/"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 音乐创作" url="https://doc.iocoder.cn/ai/music/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 音乐创作" url="https://doc.iocoder.cn/ai/music/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<DocAlert title="AI 写作助手" url="https://doc.iocoder.cn/ai/write/" />
|
<template #doc>
|
||||||
|
<DocAlert title="AI 写作助手" url="https://doc.iocoder.cn/ai/write/" />
|
||||||
|
</template>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
type="link"
|
type="link"
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
import type { BpmCategoryApi } from '#/api/bpm/category';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -106,9 +102,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = BpmCategoryApi.CategoryVO>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -146,29 +140,10 @@ export function useGridColumns<T = BpmCategoryApi.CategoryVO>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 180,
|
width: 180,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '流程分类',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['bpm:category:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['bpm:category:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type {
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
OnActionClickParams,
|
|
||||||
VxeTableGridOptions,
|
|
||||||
} from '#/adapter/vxe-table';
|
|
||||||
import type { BpmCategoryApi } from '#/api/bpm/category';
|
import type { BpmCategoryApi } from '#/api/bpm/category';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
|
||||||
|
|
||||||
import { Button, message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { deleteCategory, getCategoryPage } from '#/api/bpm/category';
|
import { deleteCategory, getCategoryPage } from '#/api/bpm/category';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
|
|
@ -22,12 +17,46 @@ const [FormModal, formModalApi] = useVbenModal({
|
||||||
connectedComponent: Form,
|
connectedComponent: Form,
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** 刷新表格 */
|
||||||
|
function onRefresh() {
|
||||||
|
gridApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建流程分类 */
|
||||||
|
function handleCreate() {
|
||||||
|
formModalApi.setData(null).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 编辑流程分类 */
|
||||||
|
function handleEdit(row: BpmCategoryApi.CategoryVO) {
|
||||||
|
formModalApi.setData(row).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除流程分类 */
|
||||||
|
async function handleDelete(row: BpmCategoryApi.CategoryVO) {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting', [row.code]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteCategory(row.id as number);
|
||||||
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.code]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
|
onRefresh();
|
||||||
|
} catch {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
formOptions: {
|
formOptions: {
|
||||||
schema: useGridFormSchema(),
|
schema: useGridFormSchema(),
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick),
|
columns: useGridColumns(),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
|
|
@ -50,54 +79,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<BpmCategoryApi.CategoryVO>,
|
} as VxeTableGridOptions<BpmCategoryApi.CategoryVO>,
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<BpmCategoryApi.CategoryVO>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 刷新表格 */
|
|
||||||
function onRefresh() {
|
|
||||||
gridApi.query();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 创建流程分类 */
|
|
||||||
function onCreate() {
|
|
||||||
formModalApi.setData(null).open();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 编辑流程分类 */
|
|
||||||
function onEdit(row: BpmCategoryApi.CategoryVO) {
|
|
||||||
formModalApi.setData(row).open();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除流程分类 */
|
|
||||||
async function onDelete(row: BpmCategoryApi.CategoryVO) {
|
|
||||||
const hideLoading = message.loading({
|
|
||||||
content: $t('ui.actionMessage.deleting', [row.code]),
|
|
||||||
duration: 0,
|
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
await deleteCategory(row.id as number);
|
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.code]));
|
|
||||||
onRefresh();
|
|
||||||
} catch {
|
|
||||||
hideLoading();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -109,14 +90,41 @@ async function onDelete(row: BpmCategoryApi.CategoryVO) {
|
||||||
<FormModal @success="onRefresh" />
|
<FormModal @success="onRefresh" />
|
||||||
<Grid table-title="流程分类">
|
<Grid table-title="流程分类">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['bpm:category:create']"
|
label: $t('ui.actionTitle.create', ['流程分类']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['流程分类']) }}
|
auth: ['bpm:category:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['bpm:category:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['bpm:category:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,9 @@
|
||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
import type { BpmFormApi } from '#/api/bpm/form';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
import { $t } from '@vben/locales';
|
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -68,9 +62,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = BpmFormApi.FormVO>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -103,41 +95,10 @@ export function useGridColumns<T = BpmFormApi.FormVO>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 200,
|
width: 240,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '流程名称',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'copy',
|
|
||||||
text: $t('ui.actionTitle.copy'),
|
|
||||||
show: hasAccessByCodes(['bpm:form:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
text: $t('ui.actionTitle.edit'),
|
|
||||||
show: hasAccessByCodes(['bpm:form:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: $t('ui.actionTitle.detail'),
|
|
||||||
show: hasAccessByCodes(['bpm:form:query']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
text: $t('ui.actionTitle.delete'),
|
|
||||||
show: hasAccessByCodes(['bpm:form:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ async function initializeDesigner() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO @ziye:注释使用 /** */ 风格,高亮更明显哈,方法注释;
|
||||||
// 保存表单
|
// 保存表单
|
||||||
function handleSave() {
|
function handleSave() {
|
||||||
formModalApi
|
formModalApi
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,97 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type {
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
OnActionClickParams,
|
|
||||||
VxeTableGridOptions,
|
|
||||||
} from '#/adapter/vxe-table';
|
|
||||||
import type { BpmFormApi } from '#/api/bpm/form';
|
import type { BpmFormApi } from '#/api/bpm/form';
|
||||||
|
|
||||||
import { ref, watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
import FormCreate from '@form-create/ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { Button, message } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { deleteForm, getFormDetail, getFormPage } from '#/api/bpm/form';
|
import { deleteForm, getFormPage } from '#/api/bpm/form';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
import { router } from '#/router';
|
import { router } from '#/router';
|
||||||
import { setConfAndFields2 } from '#/utils';
|
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
|
import Detail from './modules/detail.vue';
|
||||||
|
|
||||||
defineOptions({ name: 'BpmForm' });
|
defineOptions({ name: 'BpmForm' });
|
||||||
|
|
||||||
|
/** 刷新表格 */
|
||||||
|
function onRefresh() {
|
||||||
|
gridApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增 */
|
||||||
|
function handleCreate() {
|
||||||
|
router.push({
|
||||||
|
name: 'BpmFormEditor',
|
||||||
|
query: {
|
||||||
|
type: 'create',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 编辑 */
|
||||||
|
function handleEdit(row: BpmFormApi.FormVO) {
|
||||||
|
router.push({
|
||||||
|
name: 'BpmFormEditor',
|
||||||
|
query: {
|
||||||
|
id: row.id,
|
||||||
|
type: 'edit',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 复制 */
|
||||||
|
function handleCopy(row: BpmFormApi.FormVO) {
|
||||||
|
router.push({
|
||||||
|
name: 'BpmFormEditor',
|
||||||
|
query: {
|
||||||
|
copyId: row.id,
|
||||||
|
type: 'copy',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除 */
|
||||||
|
async function handleDelete(row: BpmFormApi.FormVO) {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteForm(row.id as number);
|
||||||
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function handleDetail(row: BpmFormApi.FormVO) {
|
||||||
|
detailModalApi.setData(row).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 详情弹窗 */
|
||||||
|
const [DetailModal, detailModalApi] = useVbenModal({
|
||||||
|
connectedComponent: Detail,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 检测路由参数 */
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
formOptions: {
|
formOptions: {
|
||||||
schema: useGridFormSchema(),
|
schema: useGridFormSchema(),
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick),
|
columns: useGridColumns(),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
|
|
@ -57,101 +118,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
} as VxeTableGridOptions<BpmFormApi.FormVO>,
|
} as VxeTableGridOptions<BpmFormApi.FormVO>,
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({ code, row }: OnActionClickParams<BpmFormApi.FormVO>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'copy': {
|
|
||||||
onCopy(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** 复制 */
|
|
||||||
function onCopy(row: BpmFormApi.FormVO) {
|
|
||||||
router.push({
|
|
||||||
name: 'BpmFormEditor',
|
|
||||||
query: {
|
|
||||||
copyId: row.id,
|
|
||||||
type: 'copy',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除 */
|
|
||||||
async function onDelete(row: BpmFormApi.FormVO) {
|
|
||||||
const hideLoading = message.loading({
|
|
||||||
content: $t('ui.actionMessage.deleting', [row.id]),
|
|
||||||
duration: 0,
|
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
await deleteForm(row.id as number);
|
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
|
||||||
onRefresh();
|
|
||||||
} finally {
|
|
||||||
hideLoading();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 详情 */
|
|
||||||
const formConfig = ref<any>({});
|
|
||||||
async function onDetail(row: BpmFormApi.FormVO) {
|
|
||||||
formConfig.value = await getFormDetail(row.id as number);
|
|
||||||
|
|
||||||
setConfAndFields2(
|
|
||||||
formConfig.value,
|
|
||||||
formConfig.value.conf,
|
|
||||||
formConfig.value.fields,
|
|
||||||
);
|
|
||||||
detailModalApi.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 编辑 */
|
|
||||||
function onEdit(row: BpmFormApi.FormVO) {
|
|
||||||
router.push({
|
|
||||||
name: 'BpmFormEditor',
|
|
||||||
query: {
|
|
||||||
id: row.id,
|
|
||||||
type: 'edit',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 刷新表格 */
|
|
||||||
function onRefresh() {
|
|
||||||
gridApi.query();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增 */
|
|
||||||
function onCreate() {
|
|
||||||
router.push({
|
|
||||||
name: 'BpmFormEditor',
|
|
||||||
query: {
|
|
||||||
type: 'create',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 详情弹窗 */
|
|
||||||
const [DetailModal, detailModalApi] = useVbenModal({
|
|
||||||
destroyOnClose: true,
|
|
||||||
footer: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 检测路由参数 */
|
|
||||||
const route = useRoute();
|
|
||||||
watch(
|
watch(
|
||||||
() => route.query.refresh,
|
() => route.query.refresh,
|
||||||
(val) => {
|
(val) => {
|
||||||
|
|
@ -171,25 +137,60 @@ watch(
|
||||||
url="https://doc.iocoder.cn/bpm/use-bpm-form/"
|
url="https://doc.iocoder.cn/bpm/use-bpm-form/"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<DetailModal />
|
||||||
<Grid table-title="流程表单">
|
<Grid table-title="流程表单">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button type="primary" @click="onCreate">
|
<TableAction
|
||||||
<Plus class="size-5" />
|
:actions="[
|
||||||
{{ $t('ui.actionTitle.create', ['流程表单']) }}
|
{
|
||||||
</Button>
|
label: $t('ui.actionTitle.create', ['流程表单']),
|
||||||
|
type: 'primary',
|
||||||
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['bpm:form:create'],
|
||||||
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('ui.actionTitle.copy'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.COPY,
|
||||||
|
auth: ['bpm:form:update'],
|
||||||
|
onClick: handleCopy.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['bpm:form:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['bpm:form:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['bpm:form:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<DetailModal
|
|
||||||
title="流程表单详情"
|
|
||||||
class="w-[800px]"
|
|
||||||
:body-style="{
|
|
||||||
maxHeight: '100px',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div class="mx-4">
|
|
||||||
<FormCreate :option="formConfig.option" :rule="formConfig.rule" />
|
|
||||||
</div>
|
|
||||||
</DetailModal>
|
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import FormCreate from '@form-create/ant-design-vue';
|
||||||
|
|
||||||
|
import { getFormDetail } from '#/api/bpm/form';
|
||||||
|
import { setConfAndFields2 } from '#/utils';
|
||||||
|
|
||||||
|
/** 详情 */
|
||||||
|
const formConfig = ref<any>({});
|
||||||
|
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
footer: false,
|
||||||
|
async onOpenChange(isOpen: boolean) {
|
||||||
|
if (!isOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 加载数据
|
||||||
|
const data = modalApi.getData();
|
||||||
|
if (!data || !data.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
modalApi.lock();
|
||||||
|
try {
|
||||||
|
formConfig.value = await getFormDetail(data.id as number);
|
||||||
|
setConfAndFields2(
|
||||||
|
formConfig.value,
|
||||||
|
formConfig.value.conf,
|
||||||
|
formConfig.value.fields,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
modalApi.unlock();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
class="w-[40%]"
|
||||||
|
title="流程表单详情"
|
||||||
|
:body-style="{
|
||||||
|
maxHeight: '100px',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<FormCreate :option="formConfig.option" :rule="formConfig.rule" />
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
@ -106,7 +106,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal :title="getTitle" class="w-[600px]">
|
<Modal :title="getTitle" class="w-[40%]">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4" />
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
import type { BpmCategoryApi } from '#/api/bpm/category';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { getSimpleUserList } from '#/api/system/user';
|
import { getSimpleUserList } from '#/api/system/user';
|
||||||
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -99,10 +95,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = BpmCategoryApi.CategoryVO>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
getMemberNames: (userIds: number[]) => string,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -123,9 +116,7 @@ export function useGridColumns<T = BpmCategoryApi.CategoryVO>(
|
||||||
field: 'userIds',
|
field: 'userIds',
|
||||||
title: '成员',
|
title: '成员',
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
formatter: ({ cellValue }) => {
|
slots: { default: 'userIds' },
|
||||||
return getMemberNames(cellValue);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
|
|
@ -143,29 +134,10 @@ export function useGridColumns<T = BpmCategoryApi.CategoryVO>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 180,
|
width: 180,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '用户分组',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['bpm:user-group:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['bpm:user-group:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,17 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type {
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
OnActionClickParams,
|
|
||||||
VxeTableGridOptions,
|
|
||||||
} from '#/adapter/vxe-table';
|
|
||||||
import type { BpmUserGroupApi } from '#/api/bpm/userGroup';
|
import type { BpmUserGroupApi } from '#/api/bpm/userGroup';
|
||||||
import type { SystemUserApi } from '#/api/system/user';
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
|
||||||
|
|
||||||
import { Button, message } from 'ant-design-vue';
|
import { message, Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { deleteUserGroup, getUserGroupPage } from '#/api/bpm/userGroup';
|
import { deleteUserGroup, getUserGroupPage } from '#/api/bpm/userGroup';
|
||||||
import { getSimpleUserList } from '#/api/system/user';
|
import { getSimpleUserList } from '#/api/system/user';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
|
|
@ -26,12 +21,53 @@ const [FormModal, formModalApi] = useVbenModal({
|
||||||
connectedComponent: Form,
|
connectedComponent: Form,
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** 刷新表格 */
|
||||||
|
function onRefresh() {
|
||||||
|
gridApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建用户分组 */
|
||||||
|
function handleCreate() {
|
||||||
|
formModalApi.setData(null).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 编辑用户分组 */
|
||||||
|
function handleEdit(row: BpmUserGroupApi.UserGroupVO) {
|
||||||
|
formModalApi.setData(row).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除用户分组 */
|
||||||
|
async function handleDelete(row: BpmUserGroupApi.UserGroupVO) {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteUserGroup(row.id as number);
|
||||||
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
|
onRefresh();
|
||||||
|
} catch {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const userList = ref<SystemUserApi.User[]>([]);
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
// 加载用户列表
|
||||||
|
userList.value = await getSimpleUserList();
|
||||||
|
});
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
formOptions: {
|
formOptions: {
|
||||||
schema: useGridFormSchema(),
|
schema: useGridFormSchema(),
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick, getMemberNames),
|
columns: useGridColumns(),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
|
|
@ -54,73 +90,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<BpmUserGroupApi.UserGroupVO>,
|
} as VxeTableGridOptions<BpmUserGroupApi.UserGroupVO>,
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 获取分组成员姓名 */
|
|
||||||
function getMemberNames(userIds: number[]) {
|
|
||||||
const userMap = new Map(
|
|
||||||
userList.value.map((user) => [user.id, user.nickname]),
|
|
||||||
);
|
|
||||||
return userIds
|
|
||||||
.map((userId) => userMap.get(userId))
|
|
||||||
.filter(Boolean)
|
|
||||||
.join('、');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<BpmUserGroupApi.UserGroupVO>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 刷新表格 */
|
|
||||||
function onRefresh() {
|
|
||||||
gridApi.query();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 创建用户分组 */
|
|
||||||
function onCreate() {
|
|
||||||
formModalApi.setData(null).open();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 编辑用户分组 */
|
|
||||||
function onEdit(row: BpmUserGroupApi.UserGroupVO) {
|
|
||||||
formModalApi.setData(row).open();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除用户分组 */
|
|
||||||
async function onDelete(row: BpmUserGroupApi.UserGroupVO) {
|
|
||||||
const hideLoading = message.loading({
|
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
|
||||||
duration: 0,
|
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
await deleteUserGroup(row.id as number);
|
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
|
||||||
onRefresh();
|
|
||||||
} catch {
|
|
||||||
hideLoading();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
const userList = ref<SystemUserApi.User[]>([]);
|
|
||||||
/** 初始化 */
|
|
||||||
onMounted(async () => {
|
|
||||||
// 加载用户列表
|
|
||||||
userList.value = await getSimpleUserList();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -132,18 +101,46 @@ onMounted(async () => {
|
||||||
<FormModal @success="onRefresh" />
|
<FormModal @success="onRefresh" />
|
||||||
<Grid table-title="用户分组">
|
<Grid table-title="用户分组">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['bpm:category:create']"
|
label: $t('ui.actionTitle.create', ['用户分组']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['用户分组']) }}
|
auth: ['bpm:user-group:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<template #userIds="{ row }">
|
||||||
<template #userIds-cell="{ row }">
|
<Tag v-for="userId in row.userIds" :key="userId" color="blue">
|
||||||
<span>{{ row.nicknames }}</span>
|
{{ userList.find((u) => u.id === userId)?.nickname }}
|
||||||
|
</Tag>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['bpm:user-group:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['bpm:user-group:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
},
|
},
|
||||||
async onOpenChange(isOpen: boolean) {
|
async onOpenChange(isOpen: boolean) {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
formData.value = undefined;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 加载数据
|
// 加载数据
|
||||||
|
|
@ -85,7 +84,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal :title="getTitle">
|
<Modal :title="getTitle" class="w-[40%]">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4" />
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -60,24 +60,24 @@ const processDesignRef = ref<InstanceType<typeof ProcessDesign>>();
|
||||||
const extraSettingRef = ref<InstanceType<typeof ExtraSetting>>();
|
const extraSettingRef = ref<InstanceType<typeof ExtraSetting>>();
|
||||||
|
|
||||||
/** 步骤校验函数 */
|
/** 步骤校验函数 */
|
||||||
const validateBasic = async () => {
|
async function validateBasic() {
|
||||||
await basicInfoRef.value?.validate();
|
await basicInfoRef.value?.validate();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 表单设计校验 */
|
/** 表单设计校验 */
|
||||||
const validateForm = async () => {
|
async function validateForm() {
|
||||||
await formDesignRef.value?.validate();
|
await formDesignRef.value?.validate();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 流程设计校验 */
|
/** 流程设计校验 */
|
||||||
const validateProcess = async () => {
|
async function validateProcess() {
|
||||||
await processDesignRef.value?.validate();
|
await processDesignRef.value?.validate();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 更多设置校验 */
|
/** 更多设置校验 */
|
||||||
const validateExtra = async () => {
|
async function validateExtra() {
|
||||||
await extraSettingRef.value?.validate();
|
await extraSettingRef.value?.validate();
|
||||||
};
|
}
|
||||||
|
|
||||||
const currentStep = ref(-1); // 步骤控制。-1 用于,一开始全部不展示等当前页面数据初始化完成
|
const currentStep = ref(-1); // 步骤控制。-1 用于,一开始全部不展示等当前页面数据初始化完成
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ const deptList = ref<SystemDeptApi.Dept[]>([]);
|
||||||
|
|
||||||
/** 初始化数据 */
|
/** 初始化数据 */
|
||||||
const actionType = route.params.type as string;
|
const actionType = route.params.type as string;
|
||||||
const initData = async () => {
|
async function initData() {
|
||||||
if (actionType === 'definition') {
|
if (actionType === 'definition') {
|
||||||
// 情况一:流程定义场景(恢复)
|
// 情况一:流程定义场景(恢复)
|
||||||
const definitionId = route.params.id as string;
|
const definitionId = route.params.id as string;
|
||||||
|
|
@ -200,7 +200,7 @@ const initData = async () => {
|
||||||
|
|
||||||
// 以前未配置更多设置的流程
|
// 以前未配置更多设置的流程
|
||||||
extraSettingRef.value?.initData();
|
extraSettingRef.value?.initData();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 根据类型切换流程数据 */
|
/** 根据类型切换流程数据 */
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -218,7 +218,7 @@ watch(
|
||||||
);
|
);
|
||||||
|
|
||||||
/** 校验所有步骤数据是否完整 */
|
/** 校验所有步骤数据是否完整 */
|
||||||
const validateAllSteps = async () => {
|
async function validateAllSteps() {
|
||||||
// 基本信息校验
|
// 基本信息校验
|
||||||
try {
|
try {
|
||||||
await validateBasic();
|
await validateBasic();
|
||||||
|
|
@ -254,10 +254,10 @@ const validateAllSteps = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 保存操作 */
|
/** 保存操作 */
|
||||||
const handleSave = async () => {
|
async function handleSave() {
|
||||||
try {
|
try {
|
||||||
// 保存前校验所有步骤的数据
|
// 保存前校验所有步骤的数据
|
||||||
const result = await validateAllSteps();
|
const result = await validateAllSteps();
|
||||||
|
|
@ -305,16 +305,16 @@ const handleSave = async () => {
|
||||||
|
|
||||||
// 返回列表页(排除更新的情况)
|
// 返回列表页(排除更新的情况)
|
||||||
if (actionType !== 'update') {
|
if (actionType !== 'update') {
|
||||||
await router.push({ name: 'BpmModel' });
|
router.push({ path: '/bpm/manager/model' });
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('保存失败:', error);
|
console.error('保存失败:', error);
|
||||||
// message.warning(error.msg || '请完善所有步骤的必填信息');
|
// message.warning(error.msg || '请完善所有步骤的必填信息');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 发布操作 */
|
/** 发布操作 */
|
||||||
const handleDeploy = async () => {
|
async function handleDeploy() {
|
||||||
try {
|
try {
|
||||||
// 修改场景下直接发布,新增场景下需要先确认
|
// 修改场景下直接发布,新增场景下需要先确认
|
||||||
if (!formData.value.id) {
|
if (!formData.value.id) {
|
||||||
|
|
@ -339,16 +339,15 @@ const handleDeploy = async () => {
|
||||||
// 发布
|
// 发布
|
||||||
await deployModel(formData.value.id);
|
await deployModel(formData.value.id);
|
||||||
message.success('发布成功');
|
message.success('发布成功');
|
||||||
// TODO 返回列表页
|
await router.push({ path: '/bpm/manager/model' });
|
||||||
await router.push({ name: 'BpmModel' });
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('发布失败:', error);
|
console.error('发布失败:', error);
|
||||||
message.warning(error.message || '发布失败');
|
message.warning(error.message || '发布失败');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 步骤切换处理 */
|
/** 步骤切换处理 */
|
||||||
const handleStepClick = async (index: number) => {
|
async function handleStepClick(index: number) {
|
||||||
try {
|
try {
|
||||||
if (index !== 0) {
|
if (index !== 0) {
|
||||||
await validateBasic();
|
await validateBasic();
|
||||||
|
|
@ -370,17 +369,17 @@ const handleStepClick = async (index: number) => {
|
||||||
message.warning('请先完善当前步骤必填信息');
|
message.warning('请先完善当前步骤必填信息');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const tabs = useTabs();
|
const tabs = useTabs();
|
||||||
|
|
||||||
/** 返回列表页 */
|
/** 返回列表页 */
|
||||||
const handleBack = () => {
|
function handleBack() {
|
||||||
// 关闭当前页签
|
// 关闭当前页签
|
||||||
tabs.closeCurrentTab();
|
tabs.closeCurrentTab();
|
||||||
// 跳转到列表页,使用路径, 目前后端的路由 name: 'name'+ menuId
|
// 跳转到列表页,使用路径, 目前后端的路由 name: 'name'+ menuId
|
||||||
router.push({ path: '/bpm/manager/model' });
|
router.push({ path: '/bpm/manager/model' });
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|
@ -419,11 +418,11 @@ onBeforeUnmount(() => {
|
||||||
|
|
||||||
<!-- 步骤条 -->
|
<!-- 步骤条 -->
|
||||||
<div class="flex h-full flex-1 items-center justify-center">
|
<div class="flex h-full flex-1 items-center justify-center">
|
||||||
<div class="flex h-full w-[400px] items-center justify-between">
|
<div class="flex h-full w-auto items-center justify-center">
|
||||||
<div
|
<div
|
||||||
v-for="(step, index) in steps"
|
v-for="(step, index) in steps"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="relative mx-[15px] flex h-full cursor-pointer items-center"
|
class="relative mx-6 flex h-full cursor-pointer items-center"
|
||||||
:class="[
|
:class="[
|
||||||
currentStep === index
|
currentStep === index
|
||||||
? 'border-b-2 border-solid border-blue-500 text-blue-500'
|
? 'border-b-2 border-solid border-blue-500 text-blue-500'
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { CircleHelp, IconifyIcon, Plus, X } from '@vben/icons';
|
import { CircleHelp, IconifyIcon, Plus, X } from '@vben/icons';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -41,6 +42,16 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [UserSelectModalComp, userSelectModalApi] = useVbenModal({
|
||||||
|
connectedComponent: UserSelectModal,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [DeptSelectModalComp, deptSelectModalApi] = useVbenModal({
|
||||||
|
connectedComponent: DeptSelectModal,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
// 表单引用
|
// 表单引用
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
|
||||||
|
|
@ -52,8 +63,6 @@ const selectedStartDepts = ref<SystemDeptApi.Dept[]>([]);
|
||||||
|
|
||||||
// 选中的流程管理员
|
// 选中的流程管理员
|
||||||
const selectedManagerUsers = ref<SystemUserApi.User[]>([]);
|
const selectedManagerUsers = ref<SystemUserApi.User[]>([]);
|
||||||
const userSelectFormRef = ref();
|
|
||||||
const deptSelectFormRef = ref();
|
|
||||||
const currentSelectType = ref<'manager' | 'start'>('start');
|
const currentSelectType = ref<'manager' | 'start'>('start');
|
||||||
// 选中的用户
|
// 选中的用户
|
||||||
const selectedUsers = ref<number[]>();
|
const selectedUsers = ref<number[]>();
|
||||||
|
|
@ -98,37 +107,37 @@ watch(
|
||||||
);
|
);
|
||||||
|
|
||||||
/** 打开发起人选择 */
|
/** 打开发起人选择 */
|
||||||
const openStartUserSelect = () => {
|
function openStartUserSelect() {
|
||||||
currentSelectType.value = 'start';
|
currentSelectType.value = 'start';
|
||||||
selectedUsers.value = selectedStartUsers.value.map(
|
selectedUsers.value = selectedStartUsers.value.map(
|
||||||
(user) => user.id,
|
(user) => user.id,
|
||||||
) as number[];
|
) as number[];
|
||||||
userSelectFormRef.value.open(selectedUsers.value);
|
userSelectModalApi.setData({ userIds: selectedUsers.value }).open();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 打开部门选择 */
|
/** 打开部门选择 */
|
||||||
const openStartDeptSelect = () => {
|
function openStartDeptSelect() {
|
||||||
deptSelectFormRef.value.open(selectedStartDepts.value);
|
deptSelectModalApi.setData({ selectedList: selectedStartDepts.value }).open();
|
||||||
};
|
}
|
||||||
/** 处理部门选择确认 */
|
/** 处理部门选择确认 */
|
||||||
const handleDeptSelectConfirm = (depts: SystemDeptApi.Dept[]) => {
|
function handleDeptSelectConfirm(depts: SystemDeptApi.Dept[]) {
|
||||||
modelData.value = {
|
modelData.value = {
|
||||||
...modelData.value,
|
...modelData.value,
|
||||||
startDeptIds: depts.map((d) => d.id),
|
startDeptIds: depts.map((d) => d.id),
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 打开管理员选择 */
|
/** 打开管理员选择 */
|
||||||
const openManagerUserSelect = () => {
|
function openManagerUserSelect() {
|
||||||
currentSelectType.value = 'manager';
|
currentSelectType.value = 'manager';
|
||||||
selectedUsers.value = selectedManagerUsers.value.map(
|
selectedUsers.value = selectedManagerUsers.value.map(
|
||||||
(user) => user.id,
|
(user) => user.id,
|
||||||
) as number[];
|
) as number[];
|
||||||
userSelectFormRef.value.open(selectedUsers.value);
|
userSelectModalApi.setData({ userIds: selectedUsers.value }).open();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 处理用户选择确认 */
|
/** 处理用户选择确认 */
|
||||||
const handleUserSelectConfirm = (userList: SystemUserApi.User[]) => {
|
function handleUserSelectConfirm(userList: SystemUserApi.User[]) {
|
||||||
modelData.value =
|
modelData.value =
|
||||||
currentSelectType.value === 'start'
|
currentSelectType.value === 'start'
|
||||||
? {
|
? {
|
||||||
|
|
@ -139,20 +148,20 @@ const handleUserSelectConfirm = (userList: SystemUserApi.User[]) => {
|
||||||
...modelData.value,
|
...modelData.value,
|
||||||
managerUserIds: userList.map((u) => u.id),
|
managerUserIds: userList.map((u) => u.id),
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 用户选择弹窗关闭 */
|
/** 用户选择弹窗关闭 */
|
||||||
const handleUserSelectClosed = () => {
|
function handleUserSelectClosed() {
|
||||||
selectedUsers.value = [];
|
selectedUsers.value = [];
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 用户选择弹窗取消 */
|
/** 用户选择弹窗取消 */
|
||||||
const handleUserSelectCancel = () => {
|
function handleUserSelectCancel() {
|
||||||
selectedUsers.value = [];
|
selectedUsers.value = [];
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 处理发起人类型变化 */
|
/** 处理发起人类型变化 */
|
||||||
const handleStartUserTypeChange = (value: SelectValue) => {
|
function handleStartUserTypeChange(value: SelectValue) {
|
||||||
const numValue = Number(value);
|
const numValue = Number(value);
|
||||||
switch (numValue) {
|
switch (numValue) {
|
||||||
case 0: {
|
case 0: {
|
||||||
|
|
@ -181,270 +190,266 @@ const handleStartUserTypeChange = (value: SelectValue) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 移除发起人 */
|
/** 移除发起人 */
|
||||||
const handleRemoveStartUser = (user: SystemUserApi.User) => {
|
function handleRemoveStartUser(user: SystemUserApi.User) {
|
||||||
modelData.value = {
|
modelData.value = {
|
||||||
...modelData.value,
|
...modelData.value,
|
||||||
startUserIds: modelData.value.startUserIds.filter(
|
startUserIds: modelData.value.startUserIds.filter(
|
||||||
(id: number) => id !== user.id,
|
(id: number) => id !== user.id,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 移除部门 */
|
/** 移除部门 */
|
||||||
const handleRemoveStartDept = (dept: SystemDeptApi.Dept) => {
|
function handleRemoveStartDept(dept: SystemDeptApi.Dept) {
|
||||||
modelData.value = {
|
modelData.value = {
|
||||||
...modelData.value,
|
...modelData.value,
|
||||||
startDeptIds: modelData.value.startDeptIds.filter(
|
startDeptIds: modelData.value.startDeptIds.filter(
|
||||||
(id: number) => id !== dept.id,
|
(id: number) => id !== dept.id,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 移除管理员 */
|
/** 移除管理员 */
|
||||||
const handleRemoveManagerUser = (user: SystemUserApi.User) => {
|
function handleRemoveManagerUser(user: SystemUserApi.User) {
|
||||||
modelData.value = {
|
modelData.value = {
|
||||||
...modelData.value,
|
...modelData.value,
|
||||||
managerUserIds: modelData.value.managerUserIds.filter(
|
managerUserIds: modelData.value.managerUserIds.filter(
|
||||||
(id: number) => id !== user.id,
|
(id: number) => id !== user.id,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 表单校验 */
|
/** 表单校验 */
|
||||||
const validate = async () => {
|
async function validate() {
|
||||||
await formRef.value?.validate();
|
await formRef.value?.validate();
|
||||||
};
|
}
|
||||||
|
|
||||||
defineExpose({ validate });
|
defineExpose({ validate });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Form
|
<div>
|
||||||
ref="formRef"
|
<Form
|
||||||
:model="modelData"
|
ref="formRef"
|
||||||
:rules="rules"
|
:model="modelData"
|
||||||
:label-col="{ span: 4 }"
|
:rules="rules"
|
||||||
:wrapper-col="{ span: 20 }"
|
:label-col="{ span: 4 }"
|
||||||
class="mt-5"
|
:wrapper-col="{ span: 20 }"
|
||||||
>
|
class="mt-5"
|
||||||
<Form.Item label="流程标识" name="key" class="mb-5">
|
>
|
||||||
<div class="flex items-center">
|
<Form.Item label="流程标识" name="key" class="mb-5">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Input
|
||||||
|
class="w-full"
|
||||||
|
v-model:value="modelData.key"
|
||||||
|
:disabled="!!modelData.id"
|
||||||
|
placeholder="请输入流程标识,以字母或下划线开头"
|
||||||
|
/>
|
||||||
|
<Tooltip
|
||||||
|
:title="
|
||||||
|
modelData.id ? '流程标识不可修改!' : '新建后,流程标识不可修改!'
|
||||||
|
"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<CircleHelp class="ml-1 size-5 text-gray-900" />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="流程名称" name="name" class="mb-5">
|
||||||
<Input
|
<Input
|
||||||
class="w-full"
|
v-model:value="modelData.name"
|
||||||
v-model:value="modelData.key"
|
|
||||||
:disabled="!!modelData.id"
|
:disabled="!!modelData.id"
|
||||||
placeholder="请输入流程标识,以字母或下划线开头"
|
allow-clear
|
||||||
|
placeholder="请输入流程名称"
|
||||||
/>
|
/>
|
||||||
<Tooltip
|
</Form.Item>
|
||||||
:title="
|
<Form.Item label="流程分类" name="category" class="mb-5">
|
||||||
modelData.id ? '流程标识不可修改!' : '新建后,流程标识不可修改!'
|
<Select
|
||||||
"
|
class="w-full"
|
||||||
placement="top"
|
v-model:value="modelData.category"
|
||||||
|
allow-clear
|
||||||
|
placeholder="请选择流程分类"
|
||||||
>
|
>
|
||||||
<CircleHelp class="ml-1 size-5 text-gray-900" />
|
<Select.Option
|
||||||
</Tooltip>
|
v-for="category in categoryList"
|
||||||
</div>
|
:key="category.code"
|
||||||
</Form.Item>
|
:value="category.code"
|
||||||
<Form.Item label="流程名称" name="name" class="mb-5">
|
>
|
||||||
<Input
|
{{ category.name }}
|
||||||
v-model:value="modelData.name"
|
</Select.Option>
|
||||||
:disabled="!!modelData.id"
|
</Select>
|
||||||
allow-clear
|
</Form.Item>
|
||||||
placeholder="请输入流程名称"
|
<Form.Item label="流程图标" class="mb-5">
|
||||||
/>
|
<ImageUpload v-model:value="modelData.icon" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="流程分类" name="category" class="mb-5">
|
<Form.Item label="流程描述" name="description" class="mb-5">
|
||||||
<Select
|
<Input.TextArea v-model:value="modelData.description" allow-clear />
|
||||||
class="w-full"
|
</Form.Item>
|
||||||
v-model:value="modelData.category"
|
<Form.Item label="流程类型" name="type" class="mb-5">
|
||||||
allow-clear
|
<Radio.Group v-model:value="modelData.type">
|
||||||
placeholder="请选择流程分类"
|
<!-- TODO BPMN 流程类型需要整合,暂时禁用 -->
|
||||||
>
|
<Radio
|
||||||
<Select.Option
|
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_TYPE)"
|
||||||
v-for="category in categoryList"
|
:key="dict.value"
|
||||||
:key="category.code"
|
:value="dict.value"
|
||||||
:value="category.code"
|
:disabled="dict.value === 10"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="是否可见" name="visible" class="mb-5">
|
||||||
|
<Radio.Group v-model:value="modelData.visible">
|
||||||
|
<Radio
|
||||||
|
v-for="(dict, index) in getBoolDictOptions(
|
||||||
|
DICT_TYPE.INFRA_BOOLEAN_STRING,
|
||||||
|
)"
|
||||||
|
:key="index"
|
||||||
|
:value="dict.value"
|
||||||
|
>
|
||||||
|
{{ dict.label }}
|
||||||
|
</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="谁可以发起" name="startUserType" class="mb-5">
|
||||||
|
<Select
|
||||||
|
v-model:value="modelData.startUserType"
|
||||||
|
placeholder="请选择谁可以发起"
|
||||||
|
@change="handleStartUserTypeChange"
|
||||||
>
|
>
|
||||||
{{ category.name }}
|
<Select.Option :value="0">全员</Select.Option>
|
||||||
</Select.Option>
|
<Select.Option :value="1">指定人员</Select.Option>
|
||||||
</Select>
|
<Select.Option :value="2">指定部门</Select.Option>
|
||||||
</Form.Item>
|
</Select>
|
||||||
<Form.Item label="流程图标" class="mb-5">
|
|
||||||
<ImageUpload v-model:value="modelData.icon" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="流程描述" name="description" class="mb-5">
|
|
||||||
<Input.TextArea v-model:value="modelData.description" allow-clear />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="流程类型" name="type" class="mb-5">
|
|
||||||
<Radio.Group v-model:value="modelData.type">
|
|
||||||
<!-- TODO BPMN 流程类型需要整合,暂时禁用 -->
|
|
||||||
<Radio
|
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_TYPE)"
|
|
||||||
:key="dict.value"
|
|
||||||
:value="dict.value"
|
|
||||||
:disabled="dict.value === 10"
|
|
||||||
>
|
|
||||||
{{ dict.label }}
|
|
||||||
</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="是否可见" name="visible" class="mb-5">
|
|
||||||
<Radio.Group v-model:value="modelData.visible">
|
|
||||||
<Radio
|
|
||||||
v-for="(dict, index) in getBoolDictOptions(
|
|
||||||
DICT_TYPE.INFRA_BOOLEAN_STRING,
|
|
||||||
)"
|
|
||||||
:key="index"
|
|
||||||
:value="dict.value"
|
|
||||||
>
|
|
||||||
{{ dict.label }}
|
|
||||||
</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="谁可以发起" name="startUserType" class="mb-5">
|
|
||||||
<Select
|
|
||||||
v-model:value="modelData.startUserType"
|
|
||||||
placeholder="请选择谁可以发起"
|
|
||||||
@change="handleStartUserTypeChange"
|
|
||||||
>
|
|
||||||
<Select.Option :value="0">全员</Select.Option>
|
|
||||||
<Select.Option :value="1">指定人员</Select.Option>
|
|
||||||
<Select.Option :value="2">指定部门</Select.Option>
|
|
||||||
</Select>
|
|
||||||
<div
|
|
||||||
v-if="modelData.startUserType === 1"
|
|
||||||
class="mt-2 flex flex-wrap gap-2"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
v-for="user in selectedStartUsers"
|
v-if="modelData.startUserType === 1"
|
||||||
:key="user.id"
|
class="mt-2 flex flex-wrap gap-1"
|
||||||
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2"
|
|
||||||
>
|
>
|
||||||
<Avatar
|
<div
|
||||||
class="m-1"
|
v-for="user in selectedStartUsers"
|
||||||
:size="28"
|
:key="user.id"
|
||||||
v-if="user.avatar"
|
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2 hover:bg-gray-200"
|
||||||
:src="user.avatar"
|
>
|
||||||
/>
|
<Avatar
|
||||||
<Avatar class="m-1" :size="28" v-else>
|
class="m-1"
|
||||||
{{ user.nickname?.substring(0, 1) }}
|
:size="28"
|
||||||
</Avatar>
|
v-if="user.avatar"
|
||||||
{{ user.nickname }}
|
:src="user.avatar"
|
||||||
<X
|
/>
|
||||||
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
<Avatar class="m-1" :size="28" v-else>
|
||||||
@click="handleRemoveStartUser(user)"
|
{{ user.nickname?.substring(0, 1) }}
|
||||||
/>
|
</Avatar>
|
||||||
|
{{ user.nickname }}
|
||||||
|
<X
|
||||||
|
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||||
|
@click="handleRemoveStartUser(user)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
@click="openStartUserSelect"
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<IconifyIcon
|
||||||
|
icon="mdi:account-plus-outline"
|
||||||
|
class="size-[18px]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
选择人员
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
@click="openStartUserSelect"
|
|
||||||
class="flex items-center"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<IconifyIcon icon="mdi:account-plus-outline" class="size-[18px]" />
|
|
||||||
</template>
|
|
||||||
选择人员
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="modelData.startUserType === 2"
|
|
||||||
class="mt-2 flex flex-wrap gap-2"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
v-for="dept in selectedStartDepts"
|
v-if="modelData.startUserType === 2"
|
||||||
:key="dept.id"
|
class="mt-2 flex flex-wrap gap-1"
|
||||||
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2"
|
|
||||||
>
|
>
|
||||||
<IconifyIcon icon="ep:office-building" class="size-6 px-1" />
|
<div
|
||||||
{{ dept.name }}
|
v-for="dept in selectedStartDepts"
|
||||||
<X
|
:key="dept.id"
|
||||||
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2 shadow-sm hover:bg-gray-200"
|
||||||
@click="handleRemoveStartDept(dept)"
|
>
|
||||||
/>
|
<IconifyIcon icon="ep:office-building" class="size-6 px-1" />
|
||||||
|
{{ dept.name }}
|
||||||
|
<X
|
||||||
|
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||||
|
@click="handleRemoveStartDept(dept)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
@click="openStartDeptSelect"
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<Plus class="size-[18px]" />
|
||||||
|
</template>
|
||||||
|
选择部门
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
</Form.Item>
|
||||||
type="link"
|
<Form.Item label="流程管理员" name="managerUserIds" class="mb-5">
|
||||||
@click="openStartDeptSelect"
|
<div class="flex flex-wrap gap-1">
|
||||||
class="flex items-center"
|
<div
|
||||||
>
|
v-for="user in selectedManagerUsers"
|
||||||
<template #icon>
|
:key="user.id"
|
||||||
<Plus class="size-[18px]" />
|
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2 hover:bg-gray-200"
|
||||||
</template>
|
>
|
||||||
选择部门
|
<Avatar
|
||||||
</Button>
|
class="m-1"
|
||||||
</div>
|
:size="28"
|
||||||
</Form.Item>
|
v-if="user.avatar"
|
||||||
<Form.Item label="流程管理员" name="managerUserIds" class="mb-5">
|
:src="user.avatar"
|
||||||
<div class="flex flex-wrap gap-2">
|
/>
|
||||||
<div
|
<Avatar class="m-1" :size="28" v-else>
|
||||||
v-for="user in selectedManagerUsers"
|
{{ user.nickname?.substring(0, 1) }}
|
||||||
:key="user.id"
|
</Avatar>
|
||||||
class="relative flex h-9 items-center rounded-full bg-gray-100 pr-2"
|
{{ user.nickname }}
|
||||||
>
|
<X
|
||||||
<Avatar
|
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
||||||
class="m-1"
|
@click="handleRemoveManagerUser(user)"
|
||||||
:size="28"
|
/>
|
||||||
v-if="user.avatar"
|
</div>
|
||||||
:src="user.avatar"
|
<Button
|
||||||
/>
|
type="link"
|
||||||
<Avatar class="m-1" :size="28" v-else>
|
@click="openManagerUserSelect"
|
||||||
{{ user.nickname?.substring(0, 1) }}
|
class="flex items-center"
|
||||||
</Avatar>
|
>
|
||||||
{{ user.nickname }}
|
<template #icon>
|
||||||
<X
|
<IconifyIcon
|
||||||
class="ml-2 size-4 cursor-pointer text-gray-400 hover:text-red-500"
|
icon="mdi:account-plus-outline"
|
||||||
@click="handleRemoveManagerUser(user)"
|
class="size-[18px]"
|
||||||
/>
|
/>
|
||||||
|
</template>
|
||||||
|
选择人员
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
</Form.Item>
|
||||||
type="link"
|
</Form>
|
||||||
@click="openManagerUserSelect"
|
|
||||||
class="flex items-center"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<IconifyIcon icon="mdi:account-plus-outline" class="size-[18px]" />
|
|
||||||
</template>
|
|
||||||
选择人员
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
|
|
||||||
<!-- 用户选择弹窗 -->
|
<!-- 用户选择弹窗 -->
|
||||||
<UserSelectModal
|
<UserSelectModalComp
|
||||||
ref="userSelectFormRef"
|
v-model:value="selectedUsers"
|
||||||
v-model:value="selectedUsers"
|
:multiple="true"
|
||||||
:multiple="true"
|
title="选择用户"
|
||||||
title="选择用户"
|
@confirm="handleUserSelectConfirm"
|
||||||
@confirm="handleUserSelectConfirm"
|
@closed="handleUserSelectClosed"
|
||||||
@closed="handleUserSelectClosed"
|
@cancel="handleUserSelectCancel"
|
||||||
@cancel="handleUserSelectCancel"
|
/>
|
||||||
/>
|
<!-- 部门选择对话框 -->
|
||||||
<!-- 部门选择对话框 -->
|
<DeptSelectModalComp
|
||||||
<DeptSelectModal
|
title="发起人部门选择"
|
||||||
ref="deptSelectFormRef"
|
:check-strictly="true"
|
||||||
title="发起人部门选择"
|
@confirm="handleDeptSelectConfirm"
|
||||||
:check-strictly="true"
|
/>
|
||||||
@confirm="handleDeptSelectConfirm"
|
</div>
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.bg-gray-100 {
|
|
||||||
background-color: #f5f7fa;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #e6e8eb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-img-placeholder {
|
.upload-img-placeholder {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: #fafafa;
|
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
||||||
|
|
@ -91,9 +91,9 @@ const numberExample = computed(() => {
|
||||||
|
|
||||||
/** 是否开启流程前置通知 */
|
/** 是否开启流程前置通知 */
|
||||||
const processBeforeTriggerEnable = ref(false);
|
const processBeforeTriggerEnable = ref(false);
|
||||||
const handleProcessBeforeTriggerEnableChange = (
|
function handleProcessBeforeTriggerEnableChange(
|
||||||
val: boolean | number | string,
|
val: boolean | number | string,
|
||||||
) => {
|
) {
|
||||||
modelData.value.processBeforeTriggerSetting = val
|
modelData.value.processBeforeTriggerSetting = val
|
||||||
? {
|
? {
|
||||||
url: '',
|
url: '',
|
||||||
|
|
@ -102,13 +102,11 @@ const handleProcessBeforeTriggerEnableChange = (
|
||||||
response: [],
|
response: [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 是否开启流程后置通知 */
|
/** 是否开启流程后置通知 */
|
||||||
const processAfterTriggerEnable = ref(false);
|
const processAfterTriggerEnable = ref(false);
|
||||||
const handleProcessAfterTriggerEnableChange = (
|
function handleProcessAfterTriggerEnableChange(val: boolean | number | string) {
|
||||||
val: boolean | number | string,
|
|
||||||
) => {
|
|
||||||
modelData.value.processAfterTriggerSetting = val
|
modelData.value.processAfterTriggerSetting = val
|
||||||
? {
|
? {
|
||||||
url: '',
|
url: '',
|
||||||
|
|
@ -117,13 +115,11 @@ const handleProcessAfterTriggerEnableChange = (
|
||||||
response: [],
|
response: [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 是否开启任务前置通知 */
|
/** 是否开启任务前置通知 */
|
||||||
const taskBeforeTriggerEnable = ref(false);
|
const taskBeforeTriggerEnable = ref(false);
|
||||||
const handleTaskBeforeTriggerEnableChange = (
|
function handleTaskBeforeTriggerEnableChange(val: boolean | number | string) {
|
||||||
val: boolean | number | string,
|
|
||||||
) => {
|
|
||||||
modelData.value.taskBeforeTriggerSetting = val
|
modelData.value.taskBeforeTriggerSetting = val
|
||||||
? {
|
? {
|
||||||
url: '',
|
url: '',
|
||||||
|
|
@ -132,11 +128,11 @@ const handleTaskBeforeTriggerEnableChange = (
|
||||||
response: [],
|
response: [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 是否开启任务后置通知 */
|
/** 是否开启任务后置通知 */
|
||||||
const taskAfterTriggerEnable = ref(false);
|
const taskAfterTriggerEnable = ref(false);
|
||||||
const handleTaskAfterTriggerEnableChange = (val: boolean | number | string) => {
|
function handleTaskAfterTriggerEnableChange(val: boolean | number | string) {
|
||||||
modelData.value.taskAfterTriggerSetting = val
|
modelData.value.taskAfterTriggerSetting = val
|
||||||
? {
|
? {
|
||||||
url: '',
|
url: '',
|
||||||
|
|
@ -145,7 +141,7 @@ const handleTaskAfterTriggerEnableChange = (val: boolean | number | string) => {
|
||||||
response: [],
|
response: [],
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 表单选项 */
|
/** 表单选项 */
|
||||||
const formField = ref<Array<{ field: string; title: string }>>([]);
|
const formField = ref<Array<{ field: string; title: string }>>([]);
|
||||||
|
|
@ -181,7 +177,7 @@ const formFieldOptions4Summary = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 兼容以前未配置更多设置的流程 */
|
/** 兼容以前未配置更多设置的流程 */
|
||||||
const initData = () => {
|
function initData() {
|
||||||
if (!modelData.value.processIdRule) {
|
if (!modelData.value.processIdRule) {
|
||||||
modelData.value.processIdRule = {
|
modelData.value.processIdRule = {
|
||||||
enable: false,
|
enable: false,
|
||||||
|
|
@ -218,7 +214,7 @@ const initData = () => {
|
||||||
if (modelData.value.taskAfterTriggerSetting) {
|
if (modelData.value.taskAfterTriggerSetting) {
|
||||||
taskAfterTriggerEnable.value = true;
|
taskAfterTriggerEnable.value = true;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 监听表单 ID 变化,加载表单数据 */
|
/** 监听表单 ID 变化,加载表单数据 */
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -242,9 +238,9 @@ watch(
|
||||||
// 表单引用
|
// 表单引用
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
/** 表单校验 */
|
/** 表单校验 */
|
||||||
const validate = async () => {
|
async function validate() {
|
||||||
await formRef.value?.validate();
|
await formRef.value?.validate();
|
||||||
};
|
}
|
||||||
|
|
||||||
defineExpose({ initData, validate });
|
defineExpose({ initData, validate });
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,9 @@ const rules: Record<string, Rule[]> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 表单校验 */
|
/** 表单校验 */
|
||||||
const validate = async () => {
|
async function validate() {
|
||||||
await formRef.value?.validate();
|
await formRef.value?.validate();
|
||||||
};
|
}
|
||||||
|
|
||||||
defineExpose({ validate });
|
defineExpose({ validate });
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -91,8 +91,8 @@ defineExpose({ validate });
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
:model="modelData"
|
:model="modelData"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
:label-col="{ span: 4 }"
|
:label-col="{ span: 3 }"
|
||||||
:wrapper-col="{ span: 20 }"
|
:wrapper-col="{ span: 21 }"
|
||||||
class="mt-5"
|
class="mt-5"
|
||||||
>
|
>
|
||||||
<FormItem label="表单类型" name="formType" class="mb-5">
|
<FormItem label="表单类型" name="formType" class="mb-5">
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const processData = inject('processData') as Ref;
|
||||||
const simpleDesign = ref();
|
const simpleDesign = ref();
|
||||||
|
|
||||||
/** 表单校验 */
|
/** 表单校验 */
|
||||||
const validate = async () => {
|
async function validate() {
|
||||||
// 获取最新的流程数据
|
// 获取最新的流程数据
|
||||||
if (!processData.value) {
|
if (!processData.value) {
|
||||||
throw new Error('请设计流程');
|
throw new Error('请设计流程');
|
||||||
|
|
@ -29,9 +29,9 @@ const validate = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
/** 处理设计器保存成功 */
|
/** 处理设计器保存成功 */
|
||||||
const handleDesignSuccess = async (data?: any) => {
|
async function handleDesignSuccess(data?: any) {
|
||||||
if (data) {
|
if (data) {
|
||||||
// 创建新的对象以触发响应式更新
|
// 创建新的对象以触发响应式更新
|
||||||
const newModelData = {
|
const newModelData = {
|
||||||
|
|
@ -44,7 +44,7 @@ const handleDesignSuccess = async (data?: any) => {
|
||||||
// 更新表单的模型数据部分
|
// 更新表单的模型数据部分
|
||||||
modelData.value = newModelData;
|
modelData.value = newModelData;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 是否显示设计器 */
|
/** 是否显示设计器 */
|
||||||
const showDesigner = computed(() => {
|
const showDesigner = computed(() => {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue