Merge remote-tracking branch 'yudao/dev' into dev
commit
8e88db8d11
|
|
@ -1,4 +1,4 @@
|
||||||
/* 来自 @vben/plugins/vxe-table style.css TODO @puhui999:可以写下目的哈; */
|
/* 来自 @vben/plugins/vxe-table style.css,覆盖 vxe-table 原有的样式定义,使用 vben 的样式主题 */
|
||||||
:root {
|
:root {
|
||||||
--vxe-ui-font-color: hsl(var(--foreground));
|
--vxe-ui-font-color: hsl(var(--foreground));
|
||||||
--vxe-ui-font-primary-color: hsl(var(--primary));
|
--vxe-ui-font-primary-color: hsl(var(--primary));
|
||||||
|
|
|
||||||
|
|
@ -300,4 +300,5 @@ export type OnActionClickParams<T = Recordable<any>> = {
|
||||||
export type OnActionClickFn<T = Recordable<any>> = (
|
export type OnActionClickFn<T = Recordable<any>> = (
|
||||||
params: OnActionClickParams<T>,
|
params: OnActionClickParams<T>,
|
||||||
) => void;
|
) => void;
|
||||||
|
export * from '#/components/table-action';
|
||||||
export type * from '@vben/plugins/vxe-table';
|
export type * from '@vben/plugins/vxe-table';
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export namespace Demo01ContactApi {
|
||||||
export interface Demo01Contact {
|
export interface Demo01Contact {
|
||||||
id: number; // 编号
|
id: number; // 编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
sex?: boolean; // 性别
|
sex?: number; // 性别
|
||||||
birthday?: Dayjs | string; // 出生年
|
birthday?: Dayjs | string; // 出生年
|
||||||
description?: string; // 简介
|
description?: string; // 简介
|
||||||
avatar: string; // 头像
|
avatar: string; // 头像
|
||||||
|
|
@ -46,6 +46,14 @@ export function deleteDemo01Contact(id: number) {
|
||||||
return requestClient.delete(`/infra/demo01-contact/delete?id=${id}`);
|
return requestClient.delete(`/infra/demo01-contact/delete?id=${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除示例联系人 */
|
||||||
|
// TODO @puhui999:ByIds,这种按照约定,是不带的,针对 Id 的情况哈。
|
||||||
|
export function deleteDemo01ContactListByIds(ids: number[]) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/infra/demo01-contact/delete-list?ids=${ids.join(',')}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出示例联系人 */
|
/** 导出示例联系人 */
|
||||||
export function exportDemo01Contact(params: any) {
|
export function exportDemo01Contact(params: any) {
|
||||||
return requestClient.download('/infra/demo01-contact/export-excel', params);
|
return requestClient.download('/infra/demo01-contact/export-excel', params);
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ export namespace Demo03StudentApi {
|
||||||
/** 查询学生分页 */
|
/** 查询学生分页 */
|
||||||
export function getDemo03StudentPage(params: PageParam) {
|
export function getDemo03StudentPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
||||||
'/infra/demo03-student/page',
|
'/infra/demo03-student-erp/page',
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -42,28 +42,38 @@ export function getDemo03StudentPage(params: PageParam) {
|
||||||
/** 查询学生详情 */
|
/** 查询学生详情 */
|
||||||
export function getDemo03Student(id: number) {
|
export function getDemo03Student(id: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
||||||
`/infra/demo03-student/get?id=${id}`,
|
`/infra/demo03-student-erp/get?id=${id}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增学生 */
|
/** 新增学生 */
|
||||||
export function createDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
export function createDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
||||||
return requestClient.post('/infra/demo03-student/create', data);
|
return requestClient.post('/infra/demo03-student-erp/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改学生 */
|
/** 修改学生 */
|
||||||
export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
||||||
return requestClient.put('/infra/demo03-student/update', data);
|
return requestClient.put('/infra/demo03-student-erp/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除学生 */
|
/** 删除学生 */
|
||||||
export function deleteDemo03Student(id: number) {
|
export function deleteDemo03Student(id: number) {
|
||||||
return requestClient.delete(`/infra/demo03-student/delete?id=${id}`);
|
return requestClient.delete(`/infra/demo03-student-erp/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
export function deleteDemo03StudentListByIds(ids: number[]) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/infra/demo03-student-erp/delete-list?ids=${ids.join(',')}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出学生 */
|
/** 导出学生 */
|
||||||
export function exportDemo03Student(params: any) {
|
export function exportDemo03Student(params: any) {
|
||||||
return requestClient.download('/infra/demo03-student/export-excel', params);
|
return requestClient.download(
|
||||||
|
'/infra/demo03-student-erp/export-excel',
|
||||||
|
params,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 子表(学生课程) ====================
|
// ==================== 子表(学生课程) ====================
|
||||||
|
|
@ -71,33 +81,44 @@ export function exportDemo03Student(params: any) {
|
||||||
/** 获得学生课程分页 */
|
/** 获得学生课程分页 */
|
||||||
export function getDemo03CoursePage(params: PageParam) {
|
export function getDemo03CoursePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo03StudentApi.Demo03Course>>(
|
return requestClient.get<PageResult<Demo03StudentApi.Demo03Course>>(
|
||||||
`/infra/demo03-student/demo03-course/page`,
|
`/infra/demo03-student-erp/demo03-course/page`,
|
||||||
{
|
{ params },
|
||||||
params,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/** 新增学生课程 */
|
/** 新增学生课程 */
|
||||||
export function createDemo03Course(data: Demo03StudentApi.Demo03Course) {
|
export function createDemo03Course(data: Demo03StudentApi.Demo03Course) {
|
||||||
return requestClient.post(`/infra/demo03-student/demo03-course/create`, data);
|
return requestClient.post(
|
||||||
|
`/infra/demo03-student-erp/demo03-course/create`,
|
||||||
|
data,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改学生课程 */
|
/** 修改学生课程 */
|
||||||
export function updateDemo03Course(data: Demo03StudentApi.Demo03Course) {
|
export function updateDemo03Course(data: Demo03StudentApi.Demo03Course) {
|
||||||
return requestClient.put(`/infra/demo03-student/demo03-course/update`, data);
|
return requestClient.put(
|
||||||
|
`/infra/demo03-student-erp/demo03-course/update`,
|
||||||
|
data,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除学生课程 */
|
/** 删除学生课程 */
|
||||||
export function deleteDemo03Course(id: number) {
|
export function deleteDemo03Course(id: number) {
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo03-student/demo03-course/delete?id=${id}`,
|
`/infra/demo03-student-erp/demo03-course/delete?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生课程 */
|
||||||
|
export function deleteDemo03CourseListByIds(ids: number[]) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/infra/demo03-student-erp/demo03-course/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获得学生课程 */
|
/** 获得学生课程 */
|
||||||
export function getDemo03Course(id: number) {
|
export function getDemo03Course(id: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Course>(
|
return requestClient.get<Demo03StudentApi.Demo03Course>(
|
||||||
`/infra/demo03-student/demo03-course/get?id=${id}`,
|
`/infra/demo03-student-erp/demo03-course/get?id=${id}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,32 +127,43 @@ export function getDemo03Course(id: number) {
|
||||||
/** 获得学生班级分页 */
|
/** 获得学生班级分页 */
|
||||||
export function getDemo03GradePage(params: PageParam) {
|
export function getDemo03GradePage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo03StudentApi.Demo03Grade>>(
|
return requestClient.get<PageResult<Demo03StudentApi.Demo03Grade>>(
|
||||||
`/infra/demo03-student/demo03-grade/page`,
|
`/infra/demo03-student-erp/demo03-grade/page`,
|
||||||
{
|
{ params },
|
||||||
params,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/** 新增学生班级 */
|
/** 新增学生班级 */
|
||||||
export function createDemo03Grade(data: Demo03StudentApi.Demo03Grade) {
|
export function createDemo03Grade(data: Demo03StudentApi.Demo03Grade) {
|
||||||
return requestClient.post(`/infra/demo03-student/demo03-grade/create`, data);
|
return requestClient.post(
|
||||||
|
`/infra/demo03-student-erp/demo03-grade/create`,
|
||||||
|
data,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改学生班级 */
|
/** 修改学生班级 */
|
||||||
export function updateDemo03Grade(data: Demo03StudentApi.Demo03Grade) {
|
export function updateDemo03Grade(data: Demo03StudentApi.Demo03Grade) {
|
||||||
return requestClient.put(`/infra/demo03-student/demo03-grade/update`, data);
|
return requestClient.put(
|
||||||
|
`/infra/demo03-student-erp/demo03-grade/update`,
|
||||||
|
data,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除学生班级 */
|
/** 删除学生班级 */
|
||||||
export function deleteDemo03Grade(id: number) {
|
export function deleteDemo03Grade(id: number) {
|
||||||
return requestClient.delete(
|
return requestClient.delete(
|
||||||
`/infra/demo03-student/demo03-grade/delete?id=${id}`,
|
`/infra/demo03-student-erp/demo03-grade/delete?id=${id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生班级 */
|
||||||
|
export function deleteDemo03GradeListByIds(ids: number[]) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/infra/demo03-student-erp/demo03-grade/delete-list?ids=${ids.join(',')}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获得学生班级 */
|
/** 获得学生班级 */
|
||||||
export function getDemo03Grade(id: number) {
|
export function getDemo03Grade(id: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Grade>(
|
return requestClient.get<Demo03StudentApi.Demo03Grade>(
|
||||||
`/infra/demo03-student/demo03-grade/get?id=${id}`,
|
`/infra/demo03-student-erp/demo03-grade/get?id=${id}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
@ -24,7 +26,7 @@ export namespace Demo03StudentApi {
|
||||||
id: number; // 编号
|
id: number; // 编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
sex?: number; // 性别
|
sex?: number; // 性别
|
||||||
birthday?: Date; // 出生日期
|
birthday?: Dayjs | string; // 出生日期
|
||||||
description?: string; // 简介
|
description?: string; // 简介
|
||||||
demo03courses?: Demo03Course[];
|
demo03courses?: Demo03Course[];
|
||||||
demo03grade?: Demo03Grade;
|
demo03grade?: Demo03Grade;
|
||||||
|
|
@ -34,7 +36,7 @@ export namespace Demo03StudentApi {
|
||||||
/** 查询学生分页 */
|
/** 查询学生分页 */
|
||||||
export function getDemo03StudentPage(params: PageParam) {
|
export function getDemo03StudentPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
||||||
'/infra/demo03-student/page',
|
'/infra/demo03-student-inner/page',
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -42,28 +44,38 @@ export function getDemo03StudentPage(params: PageParam) {
|
||||||
/** 查询学生详情 */
|
/** 查询学生详情 */
|
||||||
export function getDemo03Student(id: number) {
|
export function getDemo03Student(id: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
||||||
`/infra/demo03-student/get?id=${id}`,
|
`/infra/demo03-student-inner/get?id=${id}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增学生 */
|
/** 新增学生 */
|
||||||
export function createDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
export function createDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
||||||
return requestClient.post('/infra/demo03-student/create', data);
|
return requestClient.post('/infra/demo03-student-inner/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改学生 */
|
/** 修改学生 */
|
||||||
export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
||||||
return requestClient.put('/infra/demo03-student/update', data);
|
return requestClient.put('/infra/demo03-student-inner/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除学生 */
|
/** 删除学生 */
|
||||||
export function deleteDemo03Student(id: number) {
|
export function deleteDemo03Student(id: number) {
|
||||||
return requestClient.delete(`/infra/demo03-student/delete?id=${id}`);
|
return requestClient.delete(`/infra/demo03-student-inner/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
export function deleteDemo03StudentListByIds(ids: number[]) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/infra/demo03-student-inner/delete-list?ids=${ids.join(',')}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出学生 */
|
/** 导出学生 */
|
||||||
export function exportDemo03Student(params: any) {
|
export function exportDemo03Student(params: any) {
|
||||||
return requestClient.download('/infra/demo03-student/export-excel', params);
|
return requestClient.download(
|
||||||
|
'/infra/demo03-student-inner/export-excel',
|
||||||
|
params,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 子表(学生课程) ====================
|
// ==================== 子表(学生课程) ====================
|
||||||
|
|
@ -71,7 +83,7 @@ export function exportDemo03Student(params: any) {
|
||||||
/** 获得学生课程列表 */
|
/** 获得学生课程列表 */
|
||||||
export function getDemo03CourseListByStudentId(studentId: number) {
|
export function getDemo03CourseListByStudentId(studentId: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Course[]>(
|
return requestClient.get<Demo03StudentApi.Demo03Course[]>(
|
||||||
`/infra/demo03-student/demo03-course/list-by-student-id?studentId=${studentId}`,
|
`/infra/demo03-student-inner/demo03-course/list-by-student-id?studentId=${studentId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,6 +92,6 @@ export function getDemo03CourseListByStudentId(studentId: number) {
|
||||||
/** 获得学生班级 */
|
/** 获得学生班级 */
|
||||||
export function getDemo03GradeByStudentId(studentId: number) {
|
export function getDemo03GradeByStudentId(studentId: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Grade>(
|
return requestClient.get<Demo03StudentApi.Demo03Grade>(
|
||||||
`/infra/demo03-student/demo03-grade/get-by-student-id?studentId=${studentId}`,
|
`/infra/demo03-student-inner/demo03-grade/get-by-student-id?studentId=${studentId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export namespace Demo03StudentApi {
|
||||||
/** 查询学生分页 */
|
/** 查询学生分页 */
|
||||||
export function getDemo03StudentPage(params: PageParam) {
|
export function getDemo03StudentPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
return requestClient.get<PageResult<Demo03StudentApi.Demo03Student>>(
|
||||||
'/infra/demo03-student/page',
|
'/infra/demo03-student-normal/page',
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -44,28 +44,38 @@ export function getDemo03StudentPage(params: PageParam) {
|
||||||
/** 查询学生详情 */
|
/** 查询学生详情 */
|
||||||
export function getDemo03Student(id: number) {
|
export function getDemo03Student(id: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
return requestClient.get<Demo03StudentApi.Demo03Student>(
|
||||||
`/infra/demo03-student/get?id=${id}`,
|
`/infra/demo03-student-normal/get?id=${id}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增学生 */
|
/** 新增学生 */
|
||||||
export function createDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
export function createDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
||||||
return requestClient.post('/infra/demo03-student/create', data);
|
return requestClient.post('/infra/demo03-student-normal/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改学生 */
|
/** 修改学生 */
|
||||||
export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
export function updateDemo03Student(data: Demo03StudentApi.Demo03Student) {
|
||||||
return requestClient.put('/infra/demo03-student/update', data);
|
return requestClient.put('/infra/demo03-student-normal/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除学生 */
|
/** 删除学生 */
|
||||||
export function deleteDemo03Student(id: number) {
|
export function deleteDemo03Student(id: number) {
|
||||||
return requestClient.delete(`/infra/demo03-student/delete?id=${id}`);
|
return requestClient.delete(`/infra/demo03-student-normal/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
export function deleteDemo03StudentListByIds(ids: number[]) {
|
||||||
|
return requestClient.delete(
|
||||||
|
`/infra/demo03-student-normal/delete-list?ids=${ids.join(',')}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出学生 */
|
/** 导出学生 */
|
||||||
export function exportDemo03Student(params: any) {
|
export function exportDemo03Student(params: any) {
|
||||||
return requestClient.download('/infra/demo03-student/export-excel', params);
|
return requestClient.download(
|
||||||
|
'/infra/demo03-student-normal/export-excel',
|
||||||
|
params,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 子表(学生课程) ====================
|
// ==================== 子表(学生课程) ====================
|
||||||
|
|
@ -73,7 +83,7 @@ export function exportDemo03Student(params: any) {
|
||||||
/** 获得学生课程列表 */
|
/** 获得学生课程列表 */
|
||||||
export function getDemo03CourseListByStudentId(studentId: number) {
|
export function getDemo03CourseListByStudentId(studentId: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Course[]>(
|
return requestClient.get<Demo03StudentApi.Demo03Course[]>(
|
||||||
`/infra/demo03-student/demo03-course/list-by-student-id?studentId=${studentId}`,
|
`/infra/demo03-student-normal/demo03-course/list-by-student-id?studentId=${studentId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,6 +92,6 @@ export function getDemo03CourseListByStudentId(studentId: number) {
|
||||||
/** 获得学生班级 */
|
/** 获得学生班级 */
|
||||||
export function getDemo03GradeByStudentId(studentId: number) {
|
export function getDemo03GradeByStudentId(studentId: number) {
|
||||||
return requestClient.get<Demo03StudentApi.Demo03Grade>(
|
return requestClient.get<Demo03StudentApi.Demo03Grade>(
|
||||||
`/infra/demo03-student/demo03-grade/get-by-student-id?studentId=${studentId}`,
|
`/infra/demo03-student-normal/demo03-grade/get-by-student-id?studentId=${studentId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export namespace InfraJobApi {
|
||||||
retryInterval: number;
|
retryInterval: number;
|
||||||
monitorTimeout: number;
|
monitorTimeout: number;
|
||||||
createTime?: Date;
|
createTime?: Date;
|
||||||
|
nextTimes?: Date[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// TODO @芋艿:是否有更好的组织形式?!
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { DataNode } from 'ant-design-vue/es/tree';
|
import type { DataNode } from 'ant-design-vue/es/tree';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
export const ACTION_ICON = {
|
||||||
|
DOWNLOAD: 'lucide:download',
|
||||||
|
UPLOAD: 'lucide:upload',
|
||||||
|
ADD: 'lucide:plus',
|
||||||
|
EDIT: 'lucide:edit',
|
||||||
|
DELETE: 'lucide:trash',
|
||||||
|
REFRESH: 'lucide:refresh-cw',
|
||||||
|
SEARCH: 'lucide:search',
|
||||||
|
FILTER: 'lucide:filter',
|
||||||
|
MORE: 'lucide:ellipsis-vertical',
|
||||||
|
VIEW: 'lucide:eye',
|
||||||
|
COPY: 'lucide:copy',
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export { default as TableAction } from './table-action.vue';
|
export * from './icons';
|
||||||
|
|
||||||
export const ACTION_KEY = 'action_key_msg';
|
export { default as TableAction } from './table-action.vue';
|
||||||
export * from './typing';
|
export * from './typing';
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
<!-- add by 星语:参考 vben2 的方式,增加 TableAction 组件 -->
|
<!-- add by 星语:参考 vben2 的方式,增加 TableAction 组件 -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ButtonType } from 'ant-design-vue/es/button';
|
|
||||||
|
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
import type { ActionItem, PopConfirm } from './typing';
|
import type { ActionItem, PopConfirm } from './typing';
|
||||||
|
|
@ -69,7 +67,7 @@ const getActions = computed(() => {
|
||||||
.map((action) => {
|
.map((action) => {
|
||||||
const { popConfirm } = action;
|
const { popConfirm } = action;
|
||||||
return {
|
return {
|
||||||
type: 'link' as ButtonType,
|
type: action.type || 'link',
|
||||||
...action,
|
...action,
|
||||||
...popConfirm,
|
...popConfirm,
|
||||||
onConfirm: popConfirm?.confirm,
|
onConfirm: popConfirm?.confirm,
|
||||||
|
|
@ -183,10 +181,10 @@ function handleMenuClick(e: any) {
|
||||||
|
|
||||||
<Dropdown v-if="getDropdownList.length > 0" :trigger="['hover']">
|
<Dropdown v-if="getDropdownList.length > 0" :trigger="['hover']">
|
||||||
<slot name="more">
|
<slot name="more">
|
||||||
<Button size="small" type="link">
|
<Button :type="getDropdownList[0].type">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
{{ $t('page.action.more') }}
|
{{ $t('page.action.more') }}
|
||||||
<IconifyIcon class="icon-more" icon="ant-design:more-outlined" />
|
<IconifyIcon icon="lucide:ellipsis-vertical" />
|
||||||
</template>
|
</template>
|
||||||
</Button>
|
</Button>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
@ -230,7 +228,7 @@ function handleMenuClick(e: any) {
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.table-actions {
|
.table-actions {
|
||||||
.ant-btn {
|
.ant-btn-link {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
import type { ButtonProps } from 'ant-design-vue/es/button/buttonTypes';
|
import type {
|
||||||
|
ButtonProps,
|
||||||
|
ButtonType,
|
||||||
|
} from 'ant-design-vue/es/button/buttonTypes';
|
||||||
import type { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip';
|
import type { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip';
|
||||||
|
|
||||||
export interface PopConfirm {
|
export interface PopConfirm {
|
||||||
|
|
@ -13,6 +16,7 @@ export interface PopConfirm {
|
||||||
|
|
||||||
export interface ActionItem extends ButtonProps {
|
export interface ActionItem extends ButtonProps {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
|
type?: ButtonType;
|
||||||
label?: string;
|
label?: string;
|
||||||
color?: 'error' | 'success' | 'warning';
|
color?: 'error' | 'success' | 'warning';
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@ import type { TableToolbar } from '#/components/table-toolbar';
|
||||||
|
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
// TODO @puhui999:这里的注释、目的写下;
|
/**
|
||||||
|
* vxe 原生工具栏挂载封装
|
||||||
|
* 解决每个组件使用 vxe-table 组件时都需要写一遍的问题
|
||||||
|
*/
|
||||||
export function useTableToolbar() {
|
export function useTableToolbar() {
|
||||||
const hiddenSearchBar = ref(false); // 隐藏搜索栏
|
const hiddenSearchBar = ref(false); // 隐藏搜索栏
|
||||||
const tableToolbarRef = ref<InstanceType<typeof TableToolbar>>();
|
const tableToolbarRef = ref<InstanceType<typeof TableToolbar>>();
|
||||||
|
|
@ -15,7 +18,7 @@ export function useTableToolbar() {
|
||||||
const table = tableRef.value;
|
const table = tableRef.value;
|
||||||
const tableToolbar = tableToolbarRef.value;
|
const tableToolbar = tableToolbarRef.value;
|
||||||
if (table && tableToolbar) {
|
if (table && tableToolbar) {
|
||||||
// TODO @puhui999:通过 nexttick 可以解决么?
|
// 延迟 1 秒,确保 toolbar 组件已经挂载
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
const toolbar = tableToolbar.getToolbarRef();
|
const toolbar = tableToolbar.getToolbarRef();
|
||||||
if (!toolbar) {
|
if (!toolbar) {
|
||||||
|
|
@ -29,10 +32,9 @@ export function useTableToolbar() {
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => tableRef.value,
|
() => tableRef.value,
|
||||||
(val) => {
|
async (val) => {
|
||||||
if (!val || isBound.value) return;
|
if (!val || isBound.value) return;
|
||||||
// TODO @puhui999:这里要处理下 promise 的告警么?
|
await bindTableToolbar();
|
||||||
bindTableToolbar();
|
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import type { DefaultOptionType } from 'ant-design-vue/es/select';
|
|
||||||
// TODO @芋艿:后续再优化
|
// TODO @芋艿:后续再优化
|
||||||
// TODO @芋艿:可以共享么?
|
// TODO @芋艿:可以共享么?
|
||||||
|
|
||||||
|
|
@ -14,11 +13,11 @@ import { useDictStore } from '#/store';
|
||||||
type ColorType = 'error' | 'info' | 'success' | 'warning';
|
type ColorType = 'error' | 'info' | 'success' | 'warning';
|
||||||
|
|
||||||
export interface DictDataType {
|
export interface DictDataType {
|
||||||
dictType: string;
|
dictType?: string;
|
||||||
label: string;
|
label: string;
|
||||||
value: boolean | number | string;
|
value: boolean | number | string;
|
||||||
colorType: ColorType;
|
colorType?: ColorType;
|
||||||
cssClass: string;
|
cssClass?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NumberDictDataType extends DictDataType {
|
export interface NumberDictDataType extends DictDataType {
|
||||||
|
|
@ -62,14 +61,13 @@ function getDictObj(dictType: string, value: any) {
|
||||||
* @param valueType 字典值类型,默认 string 类型
|
* @param valueType 字典值类型,默认 string 类型
|
||||||
* @returns 字典数组
|
* @returns 字典数组
|
||||||
*/
|
*/
|
||||||
// TODO @puhui999:貌似可以定义一个类型?不使用 any[]
|
|
||||||
function getDictOptions(
|
function getDictOptions(
|
||||||
dictType: string,
|
dictType: string,
|
||||||
valueType: 'boolean' | 'number' | 'string' = 'string',
|
valueType: 'boolean' | 'number' | 'string' = 'string',
|
||||||
): any[] {
|
): DictDataType[] {
|
||||||
const dictStore = useDictStore();
|
const dictStore = useDictStore();
|
||||||
const dictOpts = dictStore.getDictOptions(dictType);
|
const dictOpts = dictStore.getDictOptions(dictType);
|
||||||
const dictOptions: DefaultOptionType = [];
|
const dictOptions: DictDataType[] = [];
|
||||||
if (dictOpts.length > 0) {
|
if (dictOpts.length > 0) {
|
||||||
let dictValue: boolean | number | string = '';
|
let dictValue: boolean | number | string = '';
|
||||||
dictOpts.forEach((d) => {
|
dictOpts.forEach((d) => {
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import ProcessDesign from './modules/process-design.vue';
|
||||||
defineOptions({ name: 'BpmModelCreate' });
|
defineOptions({ name: 'BpmModelCreate' });
|
||||||
|
|
||||||
// TODO 这个常量是不是所有 apps 都可以使用, 放 @utils/constant.ts 不能共享, @芋艿 这些常量放哪里合适!
|
// TODO 这个常量是不是所有 apps 都可以使用, 放 @utils/constant.ts 不能共享, @芋艿 这些常量放哪里合适!
|
||||||
|
// TODO @jason:/Users/yunai/Java/yudao-ui-admin-vben-v5/apps/web-antd/src/utils/constants.ts;先不多个 apps 共享哈;
|
||||||
const BpmModelType = {
|
const BpmModelType = {
|
||||||
BPMN: 10, // BPMN 设计器
|
BPMN: 10, // BPMN 设计器
|
||||||
SIMPLE: 20, // 简易设计器
|
SIMPLE: 20, // 简易设计器
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ const handleCategorySortSubmit = async () => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page auto-content-height>
|
<Page auto-content-height>
|
||||||
|
<!-- TODO @jaosn:没头像的图标,展示文字头像哈 -->
|
||||||
<!-- 流程分类表单弹窗 -->
|
<!-- 流程分类表单弹窗 -->
|
||||||
<CategoryFormModal @success="getList" />
|
<CategoryFormModal @success="getList" />
|
||||||
<Card
|
<Card
|
||||||
|
|
|
||||||
|
|
@ -59,14 +59,16 @@ function onEdit(row: CrmCustomerApi.Customer) {
|
||||||
async function onDelete(row: CrmCustomerApi.Customer) {
|
async function onDelete(row: CrmCustomerApi.Customer) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteCustomer(row.id as number);
|
await deleteCustomer(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
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 { InfraApiAccessLogApi } from '#/api/infra/api-access-log';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 列表的搜索表单 */
|
/** 列表的搜索表单 */
|
||||||
export function useGridFormSchema(): VbenFormSchema[] {
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -70,9 +65,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = InfraApiAccessLogApi.ApiAccessLog>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -148,26 +141,10 @@ export function useGridColumns<T = InfraApiAccessLogApi.ApiAccessLog>(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 80,
|
width: 80,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'id',
|
|
||||||
nameTitle: 'API访问日志',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: '详情',
|
|
||||||
show: hasAccessByCodes(['infra:api-access-log:query']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
<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 { InfraApiAccessLogApi } from '#/api/infra/api-access-log';
|
import type { InfraApiAccessLogApi } from '#/api/infra/api-access-log';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
import {
|
import {
|
||||||
exportApiAccessLog,
|
exportApiAccessLog,
|
||||||
getApiAccessLogPage,
|
getApiAccessLogPage,
|
||||||
|
|
@ -33,35 +27,22 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportApiAccessLog(await gridApi.formApi.getValues());
|
const data = await exportApiAccessLog(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: 'API 访问日志.xls', source: data });
|
downloadFileFromBlobPart({ fileName: 'API 访问日志.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看 API 访问日志详情 */
|
/** 查看 API 访问日志详情 */
|
||||||
function onDetail(row: InfraApiAccessLogApi.ApiAccessLog) {
|
function handleDetail(row: InfraApiAccessLogApi.ApiAccessLog) {
|
||||||
detailModalApi.setData(row).open();
|
detailModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<InfraApiAccessLogApi.ApiAccessLog>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -95,15 +76,30 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<DetailModal @success="onRefresh" />
|
<DetailModal @success="onRefresh" />
|
||||||
<Grid table-title="API 访问日志列表">
|
<Grid table-title="API 访问日志列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
class="ml-2"
|
{
|
||||||
@click="onExport"
|
label: $t('ui.actionTitle.export'),
|
||||||
v-access:code="['infra:api-access-log:export']"
|
type: 'primary',
|
||||||
>
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
<Download class="size-5" />
|
auth: ['infra:api-access-log:export'],
|
||||||
{{ $t('ui.actionTitle.export') }}
|
onClick: handleExport,
|
||||||
</Button>
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['infra:api-access-log:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
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 { InfraApiErrorLogApi } from '#/api/infra/api-error-log';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DICT_TYPE,
|
DICT_TYPE,
|
||||||
|
|
@ -11,8 +8,6 @@ import {
|
||||||
InfraApiErrorLogProcessStatusEnum,
|
InfraApiErrorLogProcessStatusEnum,
|
||||||
} from '#/utils';
|
} from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 列表的搜索表单 */
|
/** 列表的搜索表单 */
|
||||||
export function useGridFormSchema(): VbenFormSchema[] {
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -71,9 +66,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = InfraApiErrorLogApi.ApiErrorLog>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -130,46 +123,10 @@ export function useGridColumns<T = InfraApiErrorLogApi.ApiErrorLog>(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 200,
|
width: 200,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'id',
|
|
||||||
nameTitle: 'API错误日志',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: '详情',
|
|
||||||
show: hasAccessByCodes(['infra:api-error-log:query']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'done',
|
|
||||||
text: '已处理',
|
|
||||||
show: (row: InfraApiErrorLogApi.ApiErrorLog) => {
|
|
||||||
return (
|
|
||||||
row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT &&
|
|
||||||
hasAccessByCodes(['infra:api-error-log:update-status'])
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'ignore',
|
|
||||||
text: '已忽略',
|
|
||||||
show: (row: InfraApiErrorLogApi.ApiErrorLog) => {
|
|
||||||
return (
|
|
||||||
row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT &&
|
|
||||||
hasAccessByCodes(['infra:api-error-log:update-status'])
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +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 { InfraApiErrorLogApi } from '#/api/infra/api-error-log';
|
import type { InfraApiErrorLogApi } from '#/api/infra/api-error-log';
|
||||||
|
|
||||||
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
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 {
|
import {
|
||||||
exportApiErrorLog,
|
exportApiErrorLog,
|
||||||
getApiErrorLogPage,
|
getApiErrorLogPage,
|
||||||
|
|
@ -35,18 +31,18 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportApiErrorLog(await gridApi.formApi.getValues());
|
const data = await exportApiErrorLog(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: 'API 错误日志.xls', source: data });
|
downloadFileFromBlobPart({ fileName: 'API 错误日志.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看 API 错误日志详情 */
|
/** 查看 API 错误日志详情 */
|
||||||
function onDetail(row: InfraApiErrorLogApi.ApiErrorLog) {
|
function handleDetail(row: InfraApiErrorLogApi.ApiErrorLog) {
|
||||||
detailModalApi.setData(row).open();
|
detailModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 处理已处理 / 已忽略的操作 */
|
/** 处理已处理 / 已忽略的操作 */
|
||||||
async function onProcess(id: number, processStatus: number) {
|
async function handleProcess(id: number, processStatus: number) {
|
||||||
confirm({
|
confirm({
|
||||||
content: `确认标记为${InfraApiErrorLogProcessStatusEnum.DONE ? '已处理' : '已忽略'}?`,
|
content: `确认标记为${InfraApiErrorLogProcessStatusEnum.DONE ? '已处理' : '已忽略'}?`,
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
|
|
@ -57,33 +53,12 @@ async function onProcess(id: number, processStatus: number) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<InfraApiErrorLogApi.ApiErrorLog>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'done': {
|
|
||||||
onProcess(row.id, InfraApiErrorLogProcessStatusEnum.DONE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ignore': {
|
|
||||||
onProcess(row.id, InfraApiErrorLogProcessStatusEnum.IGNORE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -117,15 +92,54 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<DetailModal @success="onRefresh" />
|
<DetailModal @success="onRefresh" />
|
||||||
<Grid table-title="API 错误日志列表">
|
<Grid table-title="API 错误日志列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
class="ml-2"
|
{
|
||||||
@click="onExport"
|
label: $t('ui.actionTitle.export'),
|
||||||
v-access:code="['infra:api-error-log:export']"
|
type: 'primary',
|
||||||
>
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
<Download class="size-5" />
|
auth: ['infra:api-error-log:export'],
|
||||||
{{ $t('ui.actionTitle.export') }}
|
onClick: handleExport,
|
||||||
</Button>
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['infra:api-error-log:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '已处理',
|
||||||
|
type: 'link',
|
||||||
|
auth: ['infra:api-error-log:update-status'],
|
||||||
|
ifShow:
|
||||||
|
row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT,
|
||||||
|
onClick: handleProcess.bind(
|
||||||
|
null,
|
||||||
|
row.id,
|
||||||
|
InfraApiErrorLogProcessStatusEnum.DONE,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '已忽略',
|
||||||
|
type: 'link',
|
||||||
|
auth: ['infra:api-error-log:update-status'],
|
||||||
|
ifShow:
|
||||||
|
row.processStatus === InfraApiErrorLogProcessStatusEnum.INIT,
|
||||||
|
onClick: handleProcess.bind(
|
||||||
|
null,
|
||||||
|
row.id,
|
||||||
|
InfraApiErrorLogProcessStatusEnum.IGNORE,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -60,34 +60,35 @@ const formData = ref(''); // 表单数据
|
||||||
useFormCreateDesigner(designer); // 表单设计器增强
|
useFormCreateDesigner(designer); // 表单设计器增强
|
||||||
|
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const openModel = (title: string) => {
|
function openModel(title: string) {
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
dialogTitle.value = title;
|
dialogTitle.value = title;
|
||||||
modalApi.open();
|
modalApi.open();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 生成 JSON */
|
/** 生成 JSON */
|
||||||
const showJson = () => {
|
function showJson() {
|
||||||
openModel('生成 JSON');
|
openModel('生成 JSON');
|
||||||
formType.value = 0;
|
formType.value = 0;
|
||||||
formData.value = designer.value.getRule();
|
formData.value = designer.value.getRule();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 生成 Options */
|
/** 生成 Options */
|
||||||
const showOption = () => {
|
function showOption() {
|
||||||
openModel('生成 Options');
|
openModel('生成 Options');
|
||||||
formType.value = 1;
|
formType.value = 1;
|
||||||
formData.value = designer.value.getOption();
|
formData.value = designer.value.getOption();
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 生成组件 */
|
/** 生成组件 */
|
||||||
const showTemplate = () => {
|
function showTemplate() {
|
||||||
openModel('生成组件');
|
openModel('生成组件');
|
||||||
formType.value = 2;
|
formType.value = 2;
|
||||||
formData.value = makeTemplate();
|
formData.value = makeTemplate();
|
||||||
};
|
}
|
||||||
|
|
||||||
const makeTemplate = () => {
|
/** 生成组件 */
|
||||||
|
function makeTemplate() {
|
||||||
const rule = designer.value.getRule();
|
const rule = designer.value.getRule();
|
||||||
const opt = designer.value.getOption();
|
const opt = designer.value.getOption();
|
||||||
return `<template>
|
return `<template>
|
||||||
|
|
@ -111,10 +112,10 @@ const makeTemplate = () => {
|
||||||
}
|
}
|
||||||
init()
|
init()
|
||||||
<\/script>`;
|
<\/script>`;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 复制 */
|
/** 复制 */
|
||||||
const copy = async (text: string) => {
|
async function copy(text: string) {
|
||||||
const textToCopy = JSON.stringify(text, null, 2);
|
const textToCopy = JSON.stringify(text, null, 2);
|
||||||
const { copy, copied, isSupported } = useClipboard({ source: textToCopy });
|
const { copy, copied, isSupported } = useClipboard({ source: textToCopy });
|
||||||
if (isSupported) {
|
if (isSupported) {
|
||||||
|
|
@ -125,12 +126,10 @@ const copy = async (text: string) => {
|
||||||
} else {
|
} else {
|
||||||
message.error('复制失败');
|
message.error('复制失败');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/** 代码高亮 */
|
||||||
* 代码高亮
|
function highlightedCode(code: string) {
|
||||||
*/
|
|
||||||
const highlightedCode = (code: string) => {
|
|
||||||
// 处理语言和代码
|
// 处理语言和代码
|
||||||
let language = 'json';
|
let language = 'json';
|
||||||
if (formType.value === 2) {
|
if (formType.value === 2) {
|
||||||
|
|
@ -143,7 +142,7 @@ const highlightedCode = (code: string) => {
|
||||||
// 高亮
|
// 高亮
|
||||||
const result = hljs.highlight(code, { language, ignoreIllegals: true });
|
const result = hljs.highlight(code, { language, ignoreIllegals: true });
|
||||||
return result.value || ' ';
|
return result.value || ' ';
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
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 { InfraCodegenApi } from '#/api/infra/codegen';
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
import type { SystemMenuApi } from '#/api/system/menu';
|
import type { SystemMenuApi } from '#/api/system/menu';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
import { handleTree } from '@vben/utils';
|
import { handleTree } from '@vben/utils';
|
||||||
|
|
||||||
|
|
@ -16,8 +15,6 @@ import { getMenuList } from '#/api/system/menu';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 导入数据库表的表单 */
|
/** 导入数据库表的表单 */
|
||||||
export function useImportTableFormSchema(): VbenFormSchema[] {
|
export function useImportTableFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -350,7 +347,7 @@ export function useGenerationInfoSubTableFormSchema(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '一对一',
|
label: '一对一',
|
||||||
value: 'false',
|
value: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -393,8 +390,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = InfraCodegenApi.CodegenTable>(
|
export function useGridColumns(
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
getDataSourceConfigName?: (dataSourceConfigId: number) => string | undefined,
|
getDataSourceConfigName?: (dataSourceConfigId: number) => string | undefined,
|
||||||
): VxeTableGridOptions['columns'] {
|
): VxeTableGridOptions['columns'] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -432,44 +428,10 @@ export function useGridColumns<T = InfraCodegenApi.CodegenTable>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 300,
|
width: 280,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
slots: { default: 'actions' },
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'tableName',
|
|
||||||
nameTitle: '代码生成',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'preview',
|
|
||||||
text: '预览',
|
|
||||||
show: hasAccessByCodes(['infra:codegen:preview']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['infra:codegen:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['infra:codegen:delete']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'sync',
|
|
||||||
text: '同步',
|
|
||||||
show: hasAccessByCodes(['infra:codegen:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'generate',
|
|
||||||
text: '生成代码',
|
|
||||||
show: hasAccessByCodes(['infra:codegen:download']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const columnInfoRef = ref<InstanceType<typeof ColumnInfo>>();
|
||||||
const generateInfoRef = ref<InstanceType<typeof GenerationInfo>>();
|
const generateInfoRef = ref<InstanceType<typeof GenerationInfo>>();
|
||||||
|
|
||||||
/** 获取详情数据 */
|
/** 获取详情数据 */
|
||||||
const getDetail = async () => {
|
async function getDetail() {
|
||||||
const id = route.query.id as any;
|
const id = route.query.id as any;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -42,10 +42,10 @@ const getDetail = async () => {
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const submitForm = async () => {
|
async function submitForm() {
|
||||||
// 表单验证
|
// 表单验证
|
||||||
const basicInfoValid = await basicInfoRef.value?.validate();
|
const basicInfoValid = await basicInfoRef.value?.validate();
|
||||||
if (!basicInfoValid) {
|
if (!basicInfoValid) {
|
||||||
|
|
@ -61,7 +61,6 @@ const submitForm = async () => {
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.updating'),
|
content: $t('ui.actionMessage.updating'),
|
||||||
duration: 0,
|
|
||||||
key: 'action_process_msg',
|
key: 'action_process_msg',
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
|
@ -74,32 +73,35 @@ const submitForm = async () => {
|
||||||
columns,
|
columns,
|
||||||
});
|
});
|
||||||
// 关闭并提示
|
// 关闭并提示
|
||||||
message.success($t('ui.actionMessage.operationSuccess'));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.operationSuccess'),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
close();
|
close();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('保存失败', error);
|
console.error('保存失败', error);
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
const tabs = useTabs();
|
const tabs = useTabs();
|
||||||
/** 返回列表 */
|
/** 返回列表 */
|
||||||
const close = () => {
|
function close() {
|
||||||
tabs.closeCurrentTab();
|
tabs.closeCurrentTab();
|
||||||
router.push('/infra/codegen');
|
router.push('/infra/codegen');
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 下一步 */
|
/** 下一步 */
|
||||||
const nextStep = async () => {
|
function nextStep() {
|
||||||
currentStep.value += 1;
|
currentStep.value += 1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 上一步 */
|
/** 上一步 */
|
||||||
const prevStep = () => {
|
function prevStep() {
|
||||||
if (currentStep.value > 0) {
|
if (currentStep.value > 0) {
|
||||||
currentStep.value -= 1;
|
currentStep.value -= 1;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 步骤配置 */
|
/** 步骤配置 */
|
||||||
const steps = [
|
const steps = [
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
<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 { InfraCodegenApi } from '#/api/infra/codegen';
|
import type { InfraCodegenApi } from '#/api/infra/codegen';
|
||||||
import type { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
import type { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
||||||
|
|
||||||
|
|
@ -10,11 +7,10 @@ import { ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { 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 {
|
import {
|
||||||
deleteCodegenTable,
|
deleteCodegenTable,
|
||||||
downloadCodegen,
|
downloadCodegen,
|
||||||
|
|
@ -57,22 +53,22 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导入表格 */
|
/** 导入表格 */
|
||||||
function onImport() {
|
function handleImport() {
|
||||||
importModalApi.open();
|
importModalApi.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 预览代码 */
|
/** 预览代码 */
|
||||||
function onPreview(row: InfraCodegenApi.CodegenTable) {
|
function handlePreview(row: InfraCodegenApi.CodegenTable) {
|
||||||
previewModalApi.setData(row).open();
|
previewModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑表格 */
|
/** 编辑表格 */
|
||||||
function onEdit(row: InfraCodegenApi.CodegenTable) {
|
function handleEdit(row: InfraCodegenApi.CodegenTable) {
|
||||||
router.push({ name: 'InfraCodegenEdit', query: { id: row.id } });
|
router.push({ name: 'InfraCodegenEdit', query: { id: row.id } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除代码生成配置 */
|
/** 删除代码生成配置 */
|
||||||
async function onDelete(row: InfraCodegenApi.CodegenTable) {
|
async function handleDelete(row: InfraCodegenApi.CodegenTable) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.tableName]),
|
content: $t('ui.actionMessage.deleting', [row.tableName]),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
|
|
@ -88,15 +84,17 @@ async function onDelete(row: InfraCodegenApi.CodegenTable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 同步数据库 */
|
/** 同步数据库 */
|
||||||
async function onSync(row: InfraCodegenApi.CodegenTable) {
|
async function handleSync(row: InfraCodegenApi.CodegenTable) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.updating', [row.tableName]),
|
content: $t('ui.actionMessage.updating', [row.tableName]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await syncCodegenFromDB(row.id);
|
await syncCodegenFromDB(row.id);
|
||||||
message.success($t('ui.actionMessage.updateSuccess', [row.tableName]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.updateSuccess', [row.tableName]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
|
|
@ -104,11 +102,10 @@ async function onSync(row: InfraCodegenApi.CodegenTable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 生成代码 */
|
/** 生成代码 */
|
||||||
async function onGenerate(row: InfraCodegenApi.CodegenTable) {
|
async function handleGenerate(row: InfraCodegenApi.CodegenTable) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: '正在生成代码...',
|
content: '正在生成代码...',
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
const res = await downloadCodegen(row.id);
|
const res = await downloadCodegen(row.id);
|
||||||
|
|
@ -119,47 +116,21 @@ async function onGenerate(row: InfraCodegenApi.CodegenTable) {
|
||||||
link.download = `codegen-${row.className}.zip`;
|
link.download = `codegen-${row.className}.zip`;
|
||||||
link.click();
|
link.click();
|
||||||
window.URL.revokeObjectURL(url);
|
window.URL.revokeObjectURL(url);
|
||||||
message.success('代码生成成功');
|
message.success({
|
||||||
|
content: '代码生成成功',
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<InfraCodegenApi.CodegenTable>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'generate': {
|
|
||||||
onGenerate(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'preview': {
|
|
||||||
onPreview(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'sync': {
|
|
||||||
onSync(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
formOptions: {
|
formOptions: {
|
||||||
schema: useGridFormSchema(),
|
schema: useGridFormSchema(),
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick, getDataSourceConfigName),
|
columns: useGridColumns(getDataSourceConfigName),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
|
|
@ -217,14 +188,61 @@ initDataSourceConfig();
|
||||||
<PreviewModal />
|
<PreviewModal />
|
||||||
<Grid table-title="代码生成列表">
|
<Grid table-title="代码生成列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onImport"
|
{
|
||||||
v-access:code="['infra:codegen:create']"
|
label: $t('ui.actionTitle.import'),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
导入
|
auth: ['infra:codegen:create'],
|
||||||
</Button>
|
onClick: handleImport,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '预览',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['infra:codegen:preview'],
|
||||||
|
onClick: handlePreview.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生成代码',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
|
auth: ['infra:codegen:download'],
|
||||||
|
onClick: handleGenerate.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:drop-down-actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
auth: ['infra:codegen:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '同步',
|
||||||
|
type: 'link',
|
||||||
|
auth: ['infra:codegen:update'],
|
||||||
|
onClick: handleSync.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
auth: ['infra:codegen:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -96,15 +96,17 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
// 2. 提交请求
|
// 2. 提交请求
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: '导入中...',
|
content: '导入中...',
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'import_loading',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await createCodegenList(formData);
|
await createCodegenList(formData);
|
||||||
// 关闭并提示
|
// 关闭并提示
|
||||||
await modalApi.close();
|
await modalApi.close();
|
||||||
emit('success');
|
emit('success');
|
||||||
message.success($t('ui.actionMessage.operationSuccess'));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.operationSuccess'),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ const activeKey = ref<string>('');
|
||||||
|
|
||||||
/** 代码地图 */
|
/** 代码地图 */
|
||||||
const codeMap = ref<Map<string, string>>(new Map<string, string>());
|
const codeMap = ref<Map<string, string>>(new Map<string, string>());
|
||||||
const setCodeMap = (key: string, lang: string, code: string) => {
|
function setCodeMap(key: string, lang: string, code: string) {
|
||||||
// 处理可能的缩进问题,特别是对Java文件
|
// 处理可能的缩进问题,特别是对Java文件
|
||||||
const trimmedCode = code.trimStart();
|
const trimmedCode = code.trimStart();
|
||||||
// 如果已有缓存则不重新构建
|
// 如果已有缓存则不重新构建
|
||||||
|
|
@ -59,8 +59,10 @@ const setCodeMap = (key: string, lang: string, code: string) => {
|
||||||
} catch {
|
} catch {
|
||||||
codeMap.value.set(key, trimmedCode);
|
codeMap.value.set(key, trimmedCode);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
const removeCodeMapKey = (targetKey: any) => {
|
|
||||||
|
/** 删除代码地图 */
|
||||||
|
function removeCodeMapKey(targetKey: any) {
|
||||||
// 只有一个代码视图时不允许删除
|
// 只有一个代码视图时不允许删除
|
||||||
if (codeMap.value.size === 1) {
|
if (codeMap.value.size === 1) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -68,10 +70,10 @@ const removeCodeMapKey = (targetKey: any) => {
|
||||||
if (codeMap.value.has(targetKey)) {
|
if (codeMap.value.has(targetKey)) {
|
||||||
codeMap.value.delete(targetKey);
|
codeMap.value.delete(targetKey);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 复制代码 */
|
/** 复制代码 */
|
||||||
const copyCode = async () => {
|
async function copyCode() {
|
||||||
const { copy } = useClipboard();
|
const { copy } = useClipboard();
|
||||||
const file = previewFiles.value.find(
|
const file = previewFiles.value.find(
|
||||||
(item) => item.filePath === activeKey.value,
|
(item) => item.filePath === activeKey.value,
|
||||||
|
|
@ -80,10 +82,10 @@ const copyCode = async () => {
|
||||||
await copy(file.code);
|
await copy(file.code);
|
||||||
message.success('复制成功');
|
message.success('复制成功');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 文件节点点击事件 */
|
/** 文件节点点击事件 */
|
||||||
const handleNodeClick = (_: any[], e: any) => {
|
function handleNodeClick(_: any[], e: any) {
|
||||||
if (!e.node.isLeaf) return;
|
if (!e.node.isLeaf) return;
|
||||||
|
|
||||||
activeKey.value = e.node.key;
|
activeKey.value = e.node.key;
|
||||||
|
|
@ -100,10 +102,10 @@ const handleNodeClick = (_: any[], e: any) => {
|
||||||
|
|
||||||
const lang = file.filePath.split('.').pop() || '';
|
const lang = file.filePath.split('.').pop() || '';
|
||||||
setCodeMap(activeKey.value, lang, file.code);
|
setCodeMap(activeKey.value, lang, file.code);
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 处理文件树 */
|
/** 处理文件树 */
|
||||||
const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => {
|
function handleFiles(data: InfraCodegenApi.CodegenPreview[]): FileNode[] {
|
||||||
const exists: Record<string, boolean> = {};
|
const exists: Record<string, boolean> = {};
|
||||||
const files: FileNode[] = [];
|
const files: FileNode[] = [];
|
||||||
|
|
||||||
|
|
@ -176,17 +178,17 @@ const handleFiles = (data: InfraCodegenApi.CodegenPreview[]): FileNode[] => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 构建树形结构 */
|
/** 构建树形结构 */
|
||||||
const buildTree = (parentKey: string): FileNode[] => {
|
function buildTree(parentKey: string): FileNode[] {
|
||||||
return files
|
return files
|
||||||
.filter((file) => file.parentKey === parentKey)
|
.filter((file) => file.parentKey === parentKey)
|
||||||
.map((file) => ({
|
.map((file) => ({
|
||||||
...file,
|
...file,
|
||||||
children: buildTree(file.key),
|
children: buildTree(file.key),
|
||||||
}));
|
}));
|
||||||
};
|
}
|
||||||
|
|
||||||
return buildTree('/');
|
return buildTree('/');
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 模态框实例 */
|
/** 模态框实例 */
|
||||||
const [Modal, modalApi] = useVbenModal({
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
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 { InfraConfigApi } from '#/api/infra/config';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -122,9 +117,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = InfraConfigApi.Config>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -181,29 +174,10 @@ export function useGridColumns<T = InfraConfigApi.Config>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 130,
|
width: 160,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '参数',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['infra:config:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['infra:config:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +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 { InfraConfigApi } from '#/api/infra/config';
|
import type { InfraConfigApi } from '#/api/infra/config';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
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 { deleteConfig, exportConfig, getConfigPage } from '#/api/infra/config';
|
import { deleteConfig, exportConfig, getConfigPage } from '#/api/infra/config';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
|
@ -29,60 +25,46 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportConfig(await gridApi.formApi.getValues());
|
const data = await exportConfig(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '参数配置.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '参数配置.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建参数 */
|
/** 创建参数 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑参数 */
|
/** 编辑参数 */
|
||||||
function onEdit(row: InfraConfigApi.Config) {
|
function handleEdit(row: InfraConfigApi.Config) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除参数 */
|
/** 删除参数 */
|
||||||
async function onDelete(row: InfraConfigApi.Config) {
|
async function handleDelete(row: InfraConfigApi.Config) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
key: 'action_process_msg',
|
key: 'action_key_msg',
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteConfig(row.id as number);
|
await deleteConfig(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<InfraConfigApi.Config>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -112,23 +94,48 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<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="['infra:config:create']"
|
label: $t('ui.actionTitle.create', ['短信渠道']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['参数']) }}
|
auth: ['infra:config:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
<Button
|
},
|
||||||
type="primary"
|
{
|
||||||
class="ml-2"
|
label: $t('ui.actionTitle.export'),
|
||||||
@click="onExport"
|
type: 'primary',
|
||||||
v-access:code="['infra:config:export']"
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
>
|
auth: ['infra:config:export'],
|
||||||
<Download class="size-5" />
|
onClick: handleExport,
|
||||||
{{ $t('ui.actionTitle.export') }}
|
},
|
||||||
</Button>
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:post:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['system:post:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
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 { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
|
|
@ -58,9 +53,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = InfraDataSourceConfigApi.DataSourceConfig>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -89,31 +82,10 @@ export function useGridColumns<T = InfraDataSourceConfigApi.DataSourceConfig>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 130,
|
width: 160,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '数据源',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['infra:data-source-config:update']),
|
|
||||||
disabled: (row: any) => row.id === 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['infra:data-source-config:delete']),
|
|
||||||
disabled: (row: any) => row.id === 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
<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 { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
import type { InfraDataSourceConfigApi } from '#/api/infra/data-source-config';
|
||||||
|
|
||||||
import { onMounted } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { 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 {
|
import {
|
||||||
deleteDataSourceConfig,
|
deleteDataSourceConfig,
|
||||||
getDataSourceConfigList,
|
getDataSourceConfigList,
|
||||||
|
|
@ -28,51 +24,37 @@ const [FormModal, formModalApi] = useVbenModal({
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 创建数据源 */
|
/** 创建数据源 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑数据源 */
|
/** 编辑数据源 */
|
||||||
function onEdit(row: InfraDataSourceConfigApi.DataSourceConfig) {
|
function handleEdit(row: InfraDataSourceConfigApi.DataSourceConfig) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除数据源 */
|
/** 删除数据源 */
|
||||||
async function onDelete(row: InfraDataSourceConfigApi.DataSourceConfig) {
|
async function handleDelete(row: InfraDataSourceConfigApi.DataSourceConfig) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
key: 'action_process_msg',
|
key: 'action_key_msg',
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDataSourceConfig(row.id as number);
|
await deleteDataSourceConfig(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
await handleLoadData();
|
await handleLoadData();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<InfraDataSourceConfigApi.DataSourceConfig>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick),
|
columns: useGridColumns(),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
rowConfig: {
|
rowConfig: {
|
||||||
|
|
@ -94,11 +76,6 @@ async function handleLoadData() {
|
||||||
await gridApi.query();
|
await gridApi.query();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 刷新表格 */
|
|
||||||
async function onRefresh() {
|
|
||||||
await handleLoadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
handleLoadData();
|
handleLoadData();
|
||||||
|
|
@ -107,17 +84,44 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page auto-content-height>
|
<Page auto-content-height>
|
||||||
<FormModal @success="onRefresh" />
|
<FormModal @success="handleLoadData" />
|
||||||
<Grid table-title="数据源列表">
|
<Grid table-title="数据源列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['infra:data-source-config:create']"
|
label: $t('ui.actionTitle.create', ['数据源']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['数据源']) }}
|
auth: ['infra:data-source-config:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['infra:data-source-config:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['infra:data-source-config:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -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 { Demo01ContactApi } from '#/api/infra/demo/demo01';
|
import type { Demo01ContactApi } from '#/api/infra/demo/demo01';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -99,10 +95,9 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns(
|
export function useGridColumns(): VxeTableGridOptions<Demo01ContactApi.Demo01Contact>['columns'] {
|
||||||
onActionClick?: OnActionClickFn<Demo01ContactApi.Demo01Contact>,
|
|
||||||
): VxeTableGridOptions<Demo01ContactApi.Demo01Contact>['columns'] {
|
|
||||||
return [
|
return [
|
||||||
|
{ type: 'checkbox', width: 40 },
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
title: '编号',
|
title: '编号',
|
||||||
|
|
@ -145,32 +140,10 @@ export function useGridColumns(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 200,
|
width: 160,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
// TODO @puhui999:headerAlign 要使用 headerAlign: 'center' 么?看着现在分成了 align 和 headerAlign 两种
|
slots: { default: 'actions' },
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'id',
|
|
||||||
nameTitle: '示例联系人',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['infra:demo01-contact:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['infra:demo01-contact:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,18 @@ import type {
|
||||||
} from '#/adapter/vxe-table';
|
} from '#/adapter/vxe-table';
|
||||||
import type { Demo01ContactApi } from '#/api/infra/demo/demo01';
|
import type { Demo01ContactApi } from '#/api/infra/demo/demo01';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, message } from 'ant-design-vue';
|
import { Button, message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo01Contact,
|
deleteDemo01Contact,
|
||||||
|
deleteDemo01ContactListByIds,
|
||||||
exportDemo01Contact,
|
exportDemo01Contact,
|
||||||
getDemo01ContactPage,
|
getDemo01ContactPage,
|
||||||
} from '#/api/infra/demo/demo01';
|
} from '#/api/infra/demo/demo01';
|
||||||
|
|
@ -55,11 +56,38 @@ async function onDelete(row: Demo01ContactApi.Demo01Contact) {
|
||||||
await deleteDemo01Contact(row.id as number);
|
await deleteDemo01Contact(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除示例联系人 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo01ContactListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO @puhui999:方法名,改成 handleRowCheckboxChange;注释:处理选中表格行
|
||||||
|
// TODO @puhui999:deleteIds => checkedIds;然后注释去掉?
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除示例联系人 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo01ContactApi.Demo01Contact[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
const data = await exportDemo01Contact(await gridApi.formApi.getValues());
|
const data = await exportDemo01Contact(await gridApi.formApi.getValues());
|
||||||
|
|
@ -113,6 +141,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
search: true,
|
search: true,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<Demo01ContactApi.Demo01Contact>,
|
} as VxeTableGridOptions<Demo01ContactApi.Demo01Contact>,
|
||||||
|
gridEvents: {
|
||||||
|
checkboxAll: setDeleteIds,
|
||||||
|
checkboxChange: setDeleteIds,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -139,6 +171,17 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo01-contact:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
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 { Demo02CategoryApi } from '#/api/infra/demo/demo02';
|
import type { Demo02CategoryApi } from '#/api/infra/demo/demo02';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
import { handleTree } from '@vben/utils';
|
import { handleTree } from '@vben/utils';
|
||||||
|
|
||||||
import { getDemo02CategoryList } from '#/api/infra/demo/demo02';
|
import { getDemo02CategoryList } from '#/api/infra/demo/demo02';
|
||||||
import { getRangePickerDefaultProps } from '#/utils';
|
import { getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -89,9 +86,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns(
|
export function useGridColumns(): VxeTableGridOptions<Demo02CategoryApi.Demo02Category>['columns'] {
|
||||||
onActionClick?: OnActionClickFn<Demo02CategoryApi.Demo02Category>,
|
|
||||||
): VxeTableGridOptions<Demo02CategoryApi.Demo02Category>['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -116,39 +111,10 @@ export function useGridColumns(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 200,
|
width: 220,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
slots: { default: 'actions' },
|
||||||
showOverflow: false,
|
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'id',
|
|
||||||
nameTitle: '示例分类',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'append',
|
|
||||||
text: '新增下级',
|
|
||||||
show: hasAccessByCodes(['infra:demo02-category:create']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['infra:demo02-category:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['infra:demo02-category:delete']),
|
|
||||||
disabled: (row: Demo02CategoryApi.Demo02Category) => {
|
|
||||||
return !!(row.children && row.children.length > 0);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,15 @@
|
||||||
<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 { Demo02CategoryApi } from '#/api/infra/demo/demo02';
|
import type { Demo02CategoryApi } from '#/api/infra/demo/demo02';
|
||||||
|
|
||||||
import { h, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
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 {
|
import {
|
||||||
deleteDemo02Category,
|
deleteDemo02Category,
|
||||||
exportDemo02Category,
|
exportDemo02Category,
|
||||||
|
|
@ -42,69 +38,50 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportDemo02Category(await gridApi.formApi.getValues());
|
const data = await exportDemo02Category(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '示例分类.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '示例分类.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建示例分类 */
|
/** 创建示例分类 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑示例分类 */
|
/** 编辑示例分类 */
|
||||||
function onEdit(row: Demo02CategoryApi.Demo02Category) {
|
function handleEdit(row: Demo02CategoryApi.Demo02Category) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增下级示例分类 */
|
/** 新增下级示例分类 */
|
||||||
function onAppend(row: Demo02CategoryApi.Demo02Category) {
|
function handleAppend(row: Demo02CategoryApi.Demo02Category) {
|
||||||
formModalApi.setData({ parentId: row.id }).open();
|
formModalApi.setData({ parentId: row.id }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除示例分类 */
|
/** 删除示例分类 */
|
||||||
async function onDelete(row: Demo02CategoryApi.Demo02Category) {
|
async function handleDelete(row: Demo02CategoryApi.Demo02Category) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.id]),
|
content: $t('ui.actionMessage.deleting', [row.id]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo02Category(row.id as number);
|
await deleteDemo02Category(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<Demo02CategoryApi.Demo02Category>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'append': {
|
|
||||||
onAppend(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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',
|
||||||
treeConfig: {
|
treeConfig: {
|
||||||
parentField: 'parentId',
|
parentField: 'parentId',
|
||||||
|
|
@ -141,26 +118,60 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
|
||||||
<Grid table-title="示例分类列表">
|
<Grid table-title="示例分类列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button @click="toggleExpand" class="mr-2">
|
<TableAction
|
||||||
{{ isExpanded ? '收缩' : '展开' }}
|
:actions="[
|
||||||
</Button>
|
{
|
||||||
<Button
|
label: isExpanded ? '收缩' : '展开',
|
||||||
:icon="h(Plus)"
|
type: 'primary',
|
||||||
type="primary"
|
onClick: toggleExpand,
|
||||||
@click="onCreate"
|
},
|
||||||
v-access:code="['infra:demo02-category:create']"
|
{
|
||||||
>
|
label: $t('ui.actionTitle.create', ['菜单']),
|
||||||
{{ $t('ui.actionTitle.create', ['示例分类']) }}
|
type: 'primary',
|
||||||
</Button>
|
icon: ACTION_ICON.ADD,
|
||||||
<Button
|
auth: ['infra:demo02-category:create'],
|
||||||
:icon="h(Download)"
|
onClick: handleCreate,
|
||||||
type="primary"
|
},
|
||||||
class="ml-2"
|
{
|
||||||
@click="onExport"
|
label: $t('ui.actionTitle.export'),
|
||||||
v-access:code="['infra:demo02-category:export']"
|
type: 'primary',
|
||||||
>
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
{{ $t('ui.actionTitle.export') }}
|
auth: ['infra:demo02-category:export'],
|
||||||
</Button>
|
onClick: handleExport,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '新增下级',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['infra:demo02-category:create'],
|
||||||
|
onClick: handleAppend.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['infra:demo02-category:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['infra:demo02-category:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ export function useGridColumns(
|
||||||
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Student>,
|
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Student>,
|
||||||
): VxeTableGridOptions<Demo03StudentApi.Demo03Student>['columns'] {
|
): VxeTableGridOptions<Demo03StudentApi.Demo03Student>['columns'] {
|
||||||
return [
|
return [
|
||||||
|
{ type: 'checkbox', width: 40 },
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
title: '编号',
|
title: '编号',
|
||||||
|
|
@ -149,7 +150,6 @@ export function useGridColumns(
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
showOverflow: false,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|
@ -254,6 +254,7 @@ export function useDemo03CourseGridColumns(
|
||||||
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Course>,
|
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Course>,
|
||||||
): VxeTableGridOptions<Demo03StudentApi.Demo03Course>['columns'] {
|
): VxeTableGridOptions<Demo03StudentApi.Demo03Course>['columns'] {
|
||||||
return [
|
return [
|
||||||
|
{ type: 'checkbox', width: 40 },
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
title: '编号',
|
title: '编号',
|
||||||
|
|
@ -286,7 +287,7 @@ export function useDemo03CourseGridColumns(
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
showOverflow: false,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|
@ -391,6 +392,7 @@ export function useDemo03GradeGridColumns(
|
||||||
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Grade>,
|
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Grade>,
|
||||||
): VxeTableGridOptions<Demo03StudentApi.Demo03Grade>['columns'] {
|
): VxeTableGridOptions<Demo03StudentApi.Demo03Grade>['columns'] {
|
||||||
return [
|
return [
|
||||||
|
{ type: 'checkbox', width: 40 },
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
title: '编号',
|
title: '编号',
|
||||||
|
|
@ -423,7 +425,7 @@ export function useDemo03GradeGridColumns(
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
showOverflow: false,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,15 @@ import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
||||||
import { h, ref } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, message, Tabs } from 'ant-design-vue';
|
import { Button, message, Tabs } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Student,
|
deleteDemo03Student,
|
||||||
|
deleteDemo03StudentListByIds,
|
||||||
exportDemo03Student,
|
exportDemo03Student,
|
||||||
getDemo03StudentPage,
|
getDemo03StudentPage,
|
||||||
} from '#/api/infra/demo/demo03/erp';
|
} from '#/api/infra/demo/demo03/erp';
|
||||||
|
|
@ -61,11 +62,36 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
|
||||||
await deleteDemo03Student(row.id as number);
|
await deleteDemo03Student(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03StudentListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Grade[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
const data = await exportDemo03Student(await gridApi.formApi.getValues());
|
const data = await exportDemo03Student(await gridApi.formApi.getValues());
|
||||||
|
|
@ -124,6 +150,8 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
cellClick: ({ row }: { row: Demo03StudentApi.Demo03Student }) => {
|
cellClick: ({ row }: { row: Demo03StudentApi.Demo03Student }) => {
|
||||||
selectDemo03Student.value = row;
|
selectDemo03Student.value = row;
|
||||||
},
|
},
|
||||||
|
checkboxAll: setDeleteIds,
|
||||||
|
checkboxChange: setDeleteIds,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -152,6 +180,17 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,18 @@ import type {
|
||||||
} from '#/adapter/vxe-table';
|
} from '#/adapter/vxe-table';
|
||||||
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
||||||
|
|
||||||
import { h, nextTick, watch } from 'vue';
|
import { h, nextTick, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
import { Plus, Trash2 } from '@vben/icons';
|
||||||
|
import { isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, message } from 'ant-design-vue';
|
import { Button, message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Course,
|
deleteDemo03Course,
|
||||||
|
deleteDemo03CourseListByIds,
|
||||||
getDemo03CoursePage,
|
getDemo03CoursePage,
|
||||||
} from '#/api/infra/demo/demo03/erp';
|
} from '#/api/infra/demo/demo03/erp';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
@ -59,11 +61,36 @@ async function onDelete(row: Demo03StudentApi.Demo03Course) {
|
||||||
await deleteDemo03Course(row.id as number);
|
await deleteDemo03Course(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生课程 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03CourseListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生课程 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Course[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
/** 表格操作按钮的回调函数 */
|
||||||
function onActionClick({
|
function onActionClick({
|
||||||
code,
|
code,
|
||||||
|
|
@ -115,6 +142,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
isHover: true,
|
isHover: true,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<Demo03StudentApi.Demo03Course>,
|
} as VxeTableGridOptions<Demo03StudentApi.Demo03Course>,
|
||||||
|
gridEvents: {
|
||||||
|
checkboxAll: setDeleteIds,
|
||||||
|
checkboxChange: setDeleteIds,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 刷新表格 */
|
/** 刷新表格 */
|
||||||
|
|
@ -148,6 +179,17 @@ watch(
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.create', ['学生课程']) }}
|
{{ $t('ui.actionTitle.create', ['学生课程']) }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,18 @@ import type {
|
||||||
} from '#/adapter/vxe-table';
|
} from '#/adapter/vxe-table';
|
||||||
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
||||||
|
|
||||||
import { h, nextTick, watch } from 'vue';
|
import { h, nextTick, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
import { Plus, Trash2 } from '@vben/icons';
|
||||||
|
import { isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, message } from 'ant-design-vue';
|
import { Button, message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Grade,
|
deleteDemo03Grade,
|
||||||
|
deleteDemo03GradeListByIds,
|
||||||
getDemo03GradePage,
|
getDemo03GradePage,
|
||||||
} from '#/api/infra/demo/demo03/erp';
|
} from '#/api/infra/demo/demo03/erp';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
@ -59,11 +61,36 @@ async function onDelete(row: Demo03StudentApi.Demo03Grade) {
|
||||||
await deleteDemo03Grade(row.id as number);
|
await deleteDemo03Grade(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生班级 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03GradeListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生班级 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Grade[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
/** 表格操作按钮的回调函数 */
|
||||||
function onActionClick({
|
function onActionClick({
|
||||||
code,
|
code,
|
||||||
|
|
@ -115,6 +142,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
isHover: true,
|
isHover: true,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<Demo03StudentApi.Demo03Grade>,
|
} as VxeTableGridOptions<Demo03StudentApi.Demo03Grade>,
|
||||||
|
gridEvents: {
|
||||||
|
checkboxAll: setDeleteIds,
|
||||||
|
checkboxChange: setDeleteIds,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 刷新表格 */
|
/** 刷新表格 */
|
||||||
|
|
@ -148,6 +179,17 @@ watch(
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.create', ['学生班级']) }}
|
{{ $t('ui.actionTitle.create', ['学生班级']) }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
formData.value = undefined;
|
formData.value = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
let data = modalApi.getData<Demo03StudentApi.Demo03Student>();
|
let data = modalApi.getData<Demo03StudentApi.Demo03Student>();
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ export function useGridColumns(
|
||||||
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Student>,
|
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Student>,
|
||||||
): VxeTableGridOptions<Demo03StudentApi.Demo03Student>['columns'] {
|
): VxeTableGridOptions<Demo03StudentApi.Demo03Student>['columns'] {
|
||||||
return [
|
return [
|
||||||
|
{ type: 'checkbox', width: 40 },
|
||||||
{ type: 'expand', width: 80, slots: { content: 'expand_content' } },
|
{ type: 'expand', width: 80, slots: { content: 'expand_content' } },
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -150,7 +151,6 @@ export function useGridColumns(
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
showOverflow: false,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|
@ -199,7 +199,6 @@ export function useDemo03CourseGridEditColumns(
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
showOverflow: false,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,15 @@ import type { Demo03StudentApi } from '#/api/infra/demo/demo03/inner';
|
||||||
import { h, ref } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, message, Tabs } from 'ant-design-vue';
|
import { Button, message, Tabs } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Student,
|
deleteDemo03Student,
|
||||||
|
deleteDemo03StudentListByIds,
|
||||||
exportDemo03Student,
|
exportDemo03Student,
|
||||||
getDemo03StudentPage,
|
getDemo03StudentPage,
|
||||||
} from '#/api/infra/demo/demo03/inner';
|
} from '#/api/infra/demo/demo03/inner';
|
||||||
|
|
@ -60,11 +61,36 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
|
||||||
await deleteDemo03Student(row.id as number);
|
await deleteDemo03Student(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03StudentListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Student[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
const data = await exportDemo03Student(await gridApi.formApi.getValues());
|
const data = await exportDemo03Student(await gridApi.formApi.getValues());
|
||||||
|
|
@ -118,6 +144,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
search: true,
|
search: true,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<Demo03StudentApi.Demo03Student>,
|
} as VxeTableGridOptions<Demo03StudentApi.Demo03Student>,
|
||||||
|
gridEvents: {
|
||||||
|
checkboxAll: setDeleteIds,
|
||||||
|
checkboxChange: setDeleteIds,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -155,6 +185,17 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,18 @@ const props = defineProps<{
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useDemo03CourseGridColumns(),
|
columns: useDemo03CourseGridColumns(),
|
||||||
height: 'auto',
|
|
||||||
rowConfig: {
|
|
||||||
keyField: 'id',
|
|
||||||
isHover: true,
|
|
||||||
},
|
|
||||||
pagerConfig: {
|
pagerConfig: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
toolbarConfig: {
|
toolbarConfig: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<Demo03StudentApi.Demo03Student>,
|
height: '600px',
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<Demo03StudentApi.Demo03Course>,
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 刷新表格 */
|
/** 刷新表格 */
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,13 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
|
commonConfig: {
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
},
|
||||||
|
formItemClass: 'col-span-2',
|
||||||
|
labelWidth: 80,
|
||||||
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: useDemo03GradeFormSchema(),
|
schema: useDemo03GradeFormSchema(),
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,18 @@ const props = defineProps<{
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useDemo03GradeGridColumns(),
|
columns: useDemo03GradeGridColumns(),
|
||||||
height: 'auto',
|
|
||||||
rowConfig: {
|
|
||||||
keyField: 'id',
|
|
||||||
isHover: true,
|
|
||||||
},
|
|
||||||
pagerConfig: {
|
pagerConfig: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
toolbarConfig: {
|
toolbarConfig: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<Demo03StudentApi.Demo03Student>,
|
height: '600px',
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<Demo03StudentApi.Demo03Grade>,
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 刷新表格 */
|
/** 刷新表格 */
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const data = (await formApi.getValues()) as Demo03StudentApi.Demo03Student;
|
const data = (await formApi.getValues()) as Demo03StudentApi.Demo03Student;
|
||||||
// 拼接子表的数据
|
// 拼接子表的数据
|
||||||
data.demo03courses = demo03CourseFormRef.value?.getData();
|
data.demo03Courses = demo03CourseFormRef.value?.getData();
|
||||||
data.demo03grade = await demo03GradeFormRef.value?.getValues();
|
data.demo03Grade = await demo03GradeFormRef.value?.getValues();
|
||||||
try {
|
try {
|
||||||
await (formData.value?.id
|
await (formData.value?.id
|
||||||
? updateDemo03Student(data)
|
? updateDemo03Student(data)
|
||||||
|
|
@ -80,7 +80,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
formData.value = undefined;
|
formData.value = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
let data = modalApi.getData<Demo03StudentApi.Demo03Student>();
|
let data = modalApi.getData<Demo03StudentApi.Demo03Student>();
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ export function useGridColumns(
|
||||||
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Student>,
|
onActionClick?: OnActionClickFn<Demo03StudentApi.Demo03Student>,
|
||||||
): VxeTableGridOptions<Demo03StudentApi.Demo03Student>['columns'] {
|
): VxeTableGridOptions<Demo03StudentApi.Demo03Student>['columns'] {
|
||||||
return [
|
return [
|
||||||
|
{ type: 'checkbox', width: 40 },
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
title: '编号',
|
title: '编号',
|
||||||
|
|
@ -149,7 +150,6 @@ export function useGridColumns(
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
showOverflow: false,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|
@ -198,7 +198,6 @@ export function useDemo03CourseGridEditColumns(
|
||||||
minWidth: 60,
|
minWidth: 60,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
|
||||||
showOverflow: false,
|
showOverflow: false,
|
||||||
cellRender: {
|
cellRender: {
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,18 @@ import type {
|
||||||
} from '#/adapter/vxe-table';
|
} from '#/adapter/vxe-table';
|
||||||
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
|
import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, message } from 'ant-design-vue';
|
import { Button, message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Student,
|
deleteDemo03Student,
|
||||||
|
deleteDemo03StudentListByIds,
|
||||||
exportDemo03Student,
|
exportDemo03Student,
|
||||||
getDemo03StudentPage,
|
getDemo03StudentPage,
|
||||||
} from '#/api/infra/demo/demo03/normal';
|
} from '#/api/infra/demo/demo03/normal';
|
||||||
|
|
@ -55,7 +56,31 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
|
||||||
await deleteDemo03Student(row.id as number);
|
await deleteDemo03Student(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Student[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
/** 批量删除学生 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03StudentListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
onRefresh();
|
||||||
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,6 +138,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
search: true,
|
search: true,
|
||||||
},
|
},
|
||||||
} as VxeTableGridOptions<Demo03StudentApi.Demo03Student>,
|
} as VxeTableGridOptions<Demo03StudentApi.Demo03Student>,
|
||||||
|
gridEvents: {
|
||||||
|
checkboxAll: setDeleteIds,
|
||||||
|
checkboxChange: setDeleteIds,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -139,6 +168,17 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,13 @@ const props = defineProps<{
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
|
commonConfig: {
|
||||||
|
componentProps: {
|
||||||
|
class: 'w-full',
|
||||||
|
},
|
||||||
|
formItemClass: 'col-span-2',
|
||||||
|
labelWidth: 80,
|
||||||
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: useDemo03GradeFormSchema(),
|
schema: useDemo03GradeFormSchema(),
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const data = (await formApi.getValues()) as Demo03StudentApi.Demo03Student;
|
const data = (await formApi.getValues()) as Demo03StudentApi.Demo03Student;
|
||||||
// 拼接子表的数据
|
// 拼接子表的数据
|
||||||
data.demo03courses = demo03CourseFormRef.value?.getData();
|
data.demo03Courses = demo03CourseFormRef.value?.getData();
|
||||||
data.demo03grade = await demo03GradeFormRef.value?.getValues();
|
data.demo03Grade = await demo03GradeFormRef.value?.getValues();
|
||||||
try {
|
try {
|
||||||
await (formData.value?.id
|
await (formData.value?.id
|
||||||
? updateDemo03Student(data)
|
? updateDemo03Student(data)
|
||||||
|
|
@ -80,7 +80,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
formData.value = undefined;
|
formData.value = undefined;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
let data = modalApi.getData<Demo03StudentApi.Demo03Student>();
|
let data = modalApi.getData<Demo03StudentApi.Demo03Student>();
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,12 @@ import type { Demo01ContactApi } from '#/api/infra/demo/demo01';
|
||||||
import { h, onMounted, reactive, ref } from 'vue';
|
import { h, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import {
|
import {
|
||||||
cloneDeep,
|
cloneDeep,
|
||||||
downloadFileFromBlobPart,
|
downloadFileFromBlobPart,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
|
isEmpty,
|
||||||
} from '@vben/utils';
|
} from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -24,6 +25,7 @@ import {
|
||||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo01Contact,
|
deleteDemo01Contact,
|
||||||
|
deleteDemo01ContactListByIds,
|
||||||
exportDemo01Contact,
|
exportDemo01Contact,
|
||||||
getDemo01ContactPage,
|
getDemo01ContactPage,
|
||||||
} from '#/api/infra/demo/demo01';
|
} from '#/api/infra/demo/demo01';
|
||||||
|
|
@ -38,6 +40,7 @@ import Demo01ContactForm from './modules/form.vue';
|
||||||
|
|
||||||
const loading = ref(true); // 列表的加载中
|
const loading = ref(true); // 列表的加载中
|
||||||
const list = ref<Demo01ContactApi.Demo01Contact[]>([]); // 列表的数据
|
const list = ref<Demo01ContactApi.Demo01Contact[]>([]); // 列表的数据
|
||||||
|
|
||||||
const total = ref(0); // 列表的总页数
|
const total = ref(0); // 列表的总页数
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
|
|
@ -101,13 +104,41 @@ async function onDelete(row: Demo01ContactApi.Demo01Contact) {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo01Contact(row.id as number);
|
await deleteDemo01Contact(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
await getList();
|
await getList();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除示例联系人 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo01ContactListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除示例联系人 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo01ContactApi.Demo01Contact[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -205,9 +236,28 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo01-contact:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
</template>
|
</template>
|
||||||
<VxeTable ref="tableRef" :data="list" show-overflow :loading="loading">
|
<VxeTable
|
||||||
|
ref="tableRef"
|
||||||
|
:data="list"
|
||||||
|
show-overflow
|
||||||
|
:loading="loading"
|
||||||
|
@checkbox-all="setDeleteIds"
|
||||||
|
@checkbox-change="setDeleteIds"
|
||||||
|
>
|
||||||
|
<VxeColumn type="checkbox" width="40" />
|
||||||
<VxeColumn field="id" title="编号" align="center" />
|
<VxeColumn field="id" title="编号" align="center" />
|
||||||
<VxeColumn field="name" title="名字" align="center" />
|
<VxeColumn field="name" title="名字" align="center" />
|
||||||
<VxeColumn field="sex" title="性别" align="center">
|
<VxeColumn field="sex" title="性别" align="center">
|
||||||
|
|
@ -240,6 +290,7 @@ onMounted(() => {
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
type="link"
|
type="link"
|
||||||
|
danger
|
||||||
class="ml-2"
|
class="ml-2"
|
||||||
@click="onDelete(row as any)"
|
@click="onDelete(row as any)"
|
||||||
v-access:code="['infra:demo01-contact:delete']"
|
v-access:code="['infra:demo01-contact:delete']"
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
<RadioGroup v-model:value="formData.sex">
|
<RadioGroup v-model:value="formData.sex">
|
||||||
<Radio
|
<Radio
|
||||||
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
||||||
:key="dict.value"
|
:key="dict.value.toString()"
|
||||||
:value="dict.value"
|
:value="dict.value"
|
||||||
>
|
>
|
||||||
{{ dict.label }}
|
{{ dict.label }}
|
||||||
|
|
|
||||||
|
|
@ -88,14 +88,16 @@ function onAppend(row: Demo02CategoryApi.Demo02Category) {
|
||||||
async function onDelete(row: Demo02CategoryApi.Demo02Category) {
|
async function onDelete(row: Demo02CategoryApi.Demo02Category) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.id]),
|
content: $t('ui.actionMessage.deleting', [row.id]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo02Category(row.id as number);
|
await deleteDemo02Category(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
await getList();
|
await getList();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@ import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
||||||
import { h, onMounted, reactive, ref } from 'vue';
|
import { h, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import {
|
import {
|
||||||
cloneDeep,
|
cloneDeep,
|
||||||
downloadFileFromBlobPart,
|
downloadFileFromBlobPart,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
|
isEmpty,
|
||||||
} from '@vben/utils';
|
} from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DatePicker,
|
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
message,
|
message,
|
||||||
|
|
@ -26,6 +26,7 @@ import {
|
||||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Student,
|
deleteDemo03Student,
|
||||||
|
deleteDemo03StudentListByIds,
|
||||||
exportDemo03Student,
|
exportDemo03Student,
|
||||||
getDemo03StudentPage,
|
getDemo03StudentPage,
|
||||||
} from '#/api/infra/demo/demo03/erp';
|
} from '#/api/infra/demo/demo03/erp';
|
||||||
|
|
@ -56,7 +57,6 @@ const queryParams = reactive({
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
sex: undefined,
|
sex: undefined,
|
||||||
birthday: undefined,
|
|
||||||
description: undefined,
|
description: undefined,
|
||||||
createTime: undefined,
|
createTime: undefined,
|
||||||
});
|
});
|
||||||
|
|
@ -68,9 +68,6 @@ const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const params = cloneDeep(queryParams) as any;
|
const params = cloneDeep(queryParams) as any;
|
||||||
if (params.birthday && Array.isArray(params.birthday)) {
|
|
||||||
params.birthday = (params.birthday as string[]).join(',');
|
|
||||||
}
|
|
||||||
if (params.createTime && Array.isArray(params.createTime)) {
|
if (params.createTime && Array.isArray(params.createTime)) {
|
||||||
params.createTime = (params.createTime as string[]).join(',');
|
params.createTime = (params.createTime as string[]).join(',');
|
||||||
}
|
}
|
||||||
|
|
@ -118,13 +115,41 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo03Student(row.id as number);
|
await deleteDemo03Student(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
await getList();
|
await getList();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03StudentListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Student[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -178,15 +203,6 @@ onMounted(() => {
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="出生日期" name="birthday">
|
|
||||||
<DatePicker
|
|
||||||
v-model:value="queryParams.birthday"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
placeholder="选择出生日期"
|
|
||||||
allow-clear
|
|
||||||
class="w-full"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="创建时间" name="createTime">
|
<Form.Item label="创建时间" name="createTime">
|
||||||
<RangePicker
|
<RangePicker
|
||||||
v-model:value="queryParams.createTime"
|
v-model:value="queryParams.createTime"
|
||||||
|
|
@ -229,6 +245,17 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
</template>
|
</template>
|
||||||
<VxeTable
|
<VxeTable
|
||||||
|
|
@ -242,7 +269,10 @@ onMounted(() => {
|
||||||
}"
|
}"
|
||||||
show-overflow
|
show-overflow
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
|
@checkbox-all="setDeleteIds"
|
||||||
|
@checkbox-change="setDeleteIds"
|
||||||
>
|
>
|
||||||
|
<VxeColumn type="checkbox" width="40" />
|
||||||
<VxeColumn field="id" title="编号" align="center" />
|
<VxeColumn field="id" title="编号" align="center" />
|
||||||
<VxeColumn field="name" title="名字" align="center" />
|
<VxeColumn field="name" title="名字" align="center" />
|
||||||
<VxeColumn field="sex" title="性别" align="center">
|
<VxeColumn field="sex" title="性别" align="center">
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
||||||
import { h, nextTick, onMounted, reactive, ref, watch } from 'vue';
|
import { h, nextTick, onMounted, reactive, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
import { Plus, Trash2 } from '@vben/icons';
|
||||||
import { cloneDeep, formatDateTime } from '@vben/utils';
|
import { cloneDeep, formatDateTime, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
|
@ -19,6 +19,7 @@ import {
|
||||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Course,
|
deleteDemo03Course,
|
||||||
|
deleteDemo03CourseListByIds,
|
||||||
getDemo03CoursePage,
|
getDemo03CoursePage,
|
||||||
} from '#/api/infra/demo/demo03/erp';
|
} from '#/api/infra/demo/demo03/erp';
|
||||||
import { ContentWrap } from '#/components/content-wrap';
|
import { ContentWrap } from '#/components/content-wrap';
|
||||||
|
|
@ -61,13 +62,41 @@ async function onDelete(row: Demo03StudentApi.Demo03Course) {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo03Course(row.id as number);
|
await deleteDemo03Course(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
getList();
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
} catch {
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生课程 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03CourseListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生课程 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Course[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
const loading = ref(true); // 列表的加载中
|
const loading = ref(true); // 列表的加载中
|
||||||
const list = ref<Demo03StudentApi.Demo03Course[]>([]); // 列表的数据
|
const list = ref<Demo03StudentApi.Demo03Course[]>([]); // 列表的数据
|
||||||
const total = ref(0); // 列表的总页数
|
const total = ref(0); // 列表的总页数
|
||||||
|
|
@ -100,9 +129,6 @@ const getList = async () => {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const params = cloneDeep(queryParams) as any;
|
const params = cloneDeep(queryParams) as any;
|
||||||
if (params.birthday && Array.isArray(params.birthday)) {
|
|
||||||
params.birthday = (params.birthday as string[]).join(',');
|
|
||||||
}
|
|
||||||
if (params.createTime && Array.isArray(params.createTime)) {
|
if (params.createTime && Array.isArray(params.createTime)) {
|
||||||
params.createTime = (params.createTime as string[]).join(',');
|
params.createTime = (params.createTime as string[]).join(',');
|
||||||
}
|
}
|
||||||
|
|
@ -200,9 +226,28 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.create', ['学生']) }}
|
{{ $t('ui.actionTitle.create', ['学生']) }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
</template>
|
</template>
|
||||||
<VxeTable ref="tableRef" :data="list" show-overflow :loading="loading">
|
<VxeTable
|
||||||
|
ref="tableRef"
|
||||||
|
:data="list"
|
||||||
|
show-overflow
|
||||||
|
:loading="loading"
|
||||||
|
@checkbox-all="setDeleteIds"
|
||||||
|
@checkbox-change="setDeleteIds"
|
||||||
|
>
|
||||||
|
<VxeColumn type="checkbox" width="40" />
|
||||||
<VxeColumn field="id" title="编号" align="center" />
|
<VxeColumn field="id" title="编号" align="center" />
|
||||||
<VxeColumn field="studentId" title="学生编号" align="center" />
|
<VxeColumn field="studentId" title="学生编号" align="center" />
|
||||||
<VxeColumn field="name" title="名字" align="center" />
|
<VxeColumn field="name" title="名字" align="center" />
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import type { Demo03StudentApi } from '#/api/infra/demo/demo03/erp';
|
||||||
import { h, nextTick, onMounted, reactive, ref, watch } from 'vue';
|
import { h, nextTick, onMounted, reactive, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
import { Plus, Trash2 } from '@vben/icons';
|
||||||
import { cloneDeep, formatDateTime } from '@vben/utils';
|
import { cloneDeep, formatDateTime, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
|
@ -19,6 +19,7 @@ import {
|
||||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Grade,
|
deleteDemo03Grade,
|
||||||
|
deleteDemo03GradeListByIds,
|
||||||
getDemo03GradePage,
|
getDemo03GradePage,
|
||||||
} from '#/api/infra/demo/demo03/erp';
|
} from '#/api/infra/demo/demo03/erp';
|
||||||
import { ContentWrap } from '#/components/content-wrap';
|
import { ContentWrap } from '#/components/content-wrap';
|
||||||
|
|
@ -61,13 +62,41 @@ async function onDelete(row: Demo03StudentApi.Demo03Grade) {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo03Grade(row.id as number);
|
await deleteDemo03Grade(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
getList();
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
} catch {
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生班级 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03GradeListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生班级 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Grade[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
const loading = ref(true); // 列表的加载中
|
const loading = ref(true); // 列表的加载中
|
||||||
const list = ref<Demo03StudentApi.Demo03Grade[]>([]); // 列表的数据
|
const list = ref<Demo03StudentApi.Demo03Grade[]>([]); // 列表的数据
|
||||||
const total = ref(0); // 列表的总页数
|
const total = ref(0); // 列表的总页数
|
||||||
|
|
@ -100,9 +129,6 @@ const getList = async () => {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const params = cloneDeep(queryParams) as any;
|
const params = cloneDeep(queryParams) as any;
|
||||||
if (params.birthday && Array.isArray(params.birthday)) {
|
|
||||||
params.birthday = (params.birthday as string[]).join(',');
|
|
||||||
}
|
|
||||||
if (params.createTime && Array.isArray(params.createTime)) {
|
if (params.createTime && Array.isArray(params.createTime)) {
|
||||||
params.createTime = (params.createTime as string[]).join(',');
|
params.createTime = (params.createTime as string[]).join(',');
|
||||||
}
|
}
|
||||||
|
|
@ -200,9 +226,28 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.create', ['学生']) }}
|
{{ $t('ui.actionTitle.create', ['学生']) }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
</template>
|
</template>
|
||||||
<VxeTable ref="tableRef" :data="list" show-overflow :loading="loading">
|
<VxeTable
|
||||||
|
ref="tableRef"
|
||||||
|
:data="list"
|
||||||
|
show-overflow
|
||||||
|
:loading="loading"
|
||||||
|
@checkbox-all="setDeleteIds"
|
||||||
|
@checkbox-change="setDeleteIds"
|
||||||
|
>
|
||||||
|
<VxeColumn type="checkbox" width="40" />
|
||||||
<VxeColumn field="id" title="编号" align="center" />
|
<VxeColumn field="id" title="编号" align="center" />
|
||||||
<VxeColumn field="studentId" title="学生编号" align="center" />
|
<VxeColumn field="studentId" title="学生编号" align="center" />
|
||||||
<VxeColumn field="name" title="名字" align="center" />
|
<VxeColumn field="name" title="名字" align="center" />
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
<RadioGroup v-model:value="formData.sex">
|
<RadioGroup v-model:value="formData.sex">
|
||||||
<Radio
|
<Radio
|
||||||
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
||||||
:key="dict.value"
|
:key="dict.value.toString()"
|
||||||
:value="dict.value"
|
:value="dict.value"
|
||||||
>
|
>
|
||||||
{{ dict.label }}
|
{{ dict.label }}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@ import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
|
||||||
import { h, onMounted, reactive, ref } from 'vue';
|
import { h, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import {
|
import {
|
||||||
cloneDeep,
|
cloneDeep,
|
||||||
downloadFileFromBlobPart,
|
downloadFileFromBlobPart,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
|
isEmpty,
|
||||||
} from '@vben/utils';
|
} from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DatePicker,
|
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
message,
|
message,
|
||||||
|
|
@ -26,6 +26,7 @@ import {
|
||||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Student,
|
deleteDemo03Student,
|
||||||
|
deleteDemo03StudentListByIds,
|
||||||
exportDemo03Student,
|
exportDemo03Student,
|
||||||
getDemo03StudentPage,
|
getDemo03StudentPage,
|
||||||
} from '#/api/infra/demo/demo03/normal';
|
} from '#/api/infra/demo/demo03/normal';
|
||||||
|
|
@ -52,7 +53,6 @@ const queryParams = reactive({
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
sex: undefined,
|
sex: undefined,
|
||||||
birthday: undefined,
|
|
||||||
description: undefined,
|
description: undefined,
|
||||||
createTime: undefined,
|
createTime: undefined,
|
||||||
});
|
});
|
||||||
|
|
@ -64,9 +64,6 @@ const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const params = cloneDeep(queryParams) as any;
|
const params = cloneDeep(queryParams) as any;
|
||||||
if (params.birthday && Array.isArray(params.birthday)) {
|
|
||||||
params.birthday = (params.birthday as string[]).join(',');
|
|
||||||
}
|
|
||||||
if (params.createTime && Array.isArray(params.createTime)) {
|
if (params.createTime && Array.isArray(params.createTime)) {
|
||||||
params.createTime = (params.createTime as string[]).join(',');
|
params.createTime = (params.createTime as string[]).join(',');
|
||||||
}
|
}
|
||||||
|
|
@ -114,13 +111,41 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo03Student(row.id as number);
|
await deleteDemo03Student(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
await getList();
|
await getList();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03StudentListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Student[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -174,15 +199,6 @@ onMounted(() => {
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="出生日期" name="birthday">
|
|
||||||
<DatePicker
|
|
||||||
v-model:value="queryParams.birthday"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
placeholder="选择出生日期"
|
|
||||||
allow-clear
|
|
||||||
class="w-full"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="创建时间" name="createTime">
|
<Form.Item label="创建时间" name="createTime">
|
||||||
<RangePicker
|
<RangePicker
|
||||||
v-model:value="queryParams.createTime"
|
v-model:value="queryParams.createTime"
|
||||||
|
|
@ -225,9 +241,28 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
</template>
|
</template>
|
||||||
<VxeTable ref="tableRef" :data="list" show-overflow :loading="loading">
|
<VxeTable
|
||||||
|
ref="tableRef"
|
||||||
|
:data="list"
|
||||||
|
show-overflow
|
||||||
|
:loading="loading"
|
||||||
|
@checkbox-all="setDeleteIds"
|
||||||
|
@checkbox-change="setDeleteIds"
|
||||||
|
>
|
||||||
|
<VxeColumn type="checkbox" width="40" />
|
||||||
<!-- 子表的列表 -->
|
<!-- 子表的列表 -->
|
||||||
<VxeColumn type="expand" width="60">
|
<VxeColumn type="expand" width="60">
|
||||||
<template #content="{ row }">
|
<template #content="{ row }">
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
<RadioGroup v-model:value="formData.sex">
|
<RadioGroup v-model:value="formData.sex">
|
||||||
<Radio
|
<Radio
|
||||||
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
||||||
:key="dict.value"
|
:key="dict.value.toString()"
|
||||||
:value="dict.value"
|
:value="dict.value"
|
||||||
>
|
>
|
||||||
{{ dict.label }}
|
{{ dict.label }}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@ import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal';
|
||||||
import { h, onMounted, reactive, ref } from 'vue';
|
import { h, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
import { Download, Plus, Trash2 } from '@vben/icons';
|
||||||
import {
|
import {
|
||||||
cloneDeep,
|
cloneDeep,
|
||||||
downloadFileFromBlobPart,
|
downloadFileFromBlobPart,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
|
isEmpty,
|
||||||
} from '@vben/utils';
|
} from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DatePicker,
|
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
message,
|
message,
|
||||||
|
|
@ -25,6 +25,7 @@ import {
|
||||||
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
deleteDemo03Student,
|
deleteDemo03Student,
|
||||||
|
deleteDemo03StudentListByIds,
|
||||||
exportDemo03Student,
|
exportDemo03Student,
|
||||||
getDemo03StudentPage,
|
getDemo03StudentPage,
|
||||||
} from '#/api/infra/demo/demo03/normal';
|
} from '#/api/infra/demo/demo03/normal';
|
||||||
|
|
@ -46,7 +47,6 @@ const queryParams = reactive({
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
sex: undefined,
|
sex: undefined,
|
||||||
birthday: undefined,
|
|
||||||
description: undefined,
|
description: undefined,
|
||||||
createTime: undefined,
|
createTime: undefined,
|
||||||
});
|
});
|
||||||
|
|
@ -58,9 +58,6 @@ const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const params = cloneDeep(queryParams) as any;
|
const params = cloneDeep(queryParams) as any;
|
||||||
if (params.birthday && Array.isArray(params.birthday)) {
|
|
||||||
params.birthday = (params.birthday as string[]).join(',');
|
|
||||||
}
|
|
||||||
if (params.createTime && Array.isArray(params.createTime)) {
|
if (params.createTime && Array.isArray(params.createTime)) {
|
||||||
params.createTime = (params.createTime as string[]).join(',');
|
params.createTime = (params.createTime as string[]).join(',');
|
||||||
}
|
}
|
||||||
|
|
@ -108,13 +105,41 @@ async function onDelete(row: Demo03StudentApi.Demo03Student) {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDemo03Student(row.id as number);
|
await deleteDemo03Student(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
await getList();
|
await getList();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除学生 */
|
||||||
|
async function onDeleteBatch() {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: $t('ui.actionMessage.deleting'),
|
||||||
|
duration: 0,
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deleteDemo03StudentListByIds(deleteIds.value);
|
||||||
|
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
await getList();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteIds = ref<number[]>([]); // 待删除学生 ID
|
||||||
|
function setDeleteIds({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: Demo03StudentApi.Demo03Student[];
|
||||||
|
}) {
|
||||||
|
deleteIds.value = records.map((item) => item.id);
|
||||||
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -168,15 +193,6 @@ onMounted(() => {
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="出生日期" name="birthday">
|
|
||||||
<DatePicker
|
|
||||||
v-model:value="queryParams.birthday"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
placeholder="选择出生日期"
|
|
||||||
allow-clear
|
|
||||||
class="w-full"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="创建时间" name="createTime">
|
<Form.Item label="创建时间" name="createTime">
|
||||||
<RangePicker
|
<RangePicker
|
||||||
v-model:value="queryParams.createTime"
|
v-model:value="queryParams.createTime"
|
||||||
|
|
@ -219,9 +235,28 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
{{ $t('ui.actionTitle.export') }}
|
{{ $t('ui.actionTitle.export') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
:icon="h(Trash2)"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
class="ml-2"
|
||||||
|
:disabled="isEmpty(deleteIds)"
|
||||||
|
@click="onDeleteBatch"
|
||||||
|
v-access:code="['infra:demo03-student:delete']"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</Button>
|
||||||
</TableToolbar>
|
</TableToolbar>
|
||||||
</template>
|
</template>
|
||||||
<VxeTable ref="tableRef" :data="list" show-overflow :loading="loading">
|
<VxeTable
|
||||||
|
ref="tableRef"
|
||||||
|
:data="list"
|
||||||
|
show-overflow
|
||||||
|
:loading="loading"
|
||||||
|
@checkbox-all="setDeleteIds"
|
||||||
|
@checkbox-change="setDeleteIds"
|
||||||
|
>
|
||||||
|
<VxeColumn type="checkbox" width="40" />
|
||||||
<VxeColumn field="id" title="编号" align="center" />
|
<VxeColumn field="id" title="编号" align="center" />
|
||||||
<VxeColumn field="name" title="名字" align="center" />
|
<VxeColumn field="name" title="名字" align="center" />
|
||||||
<VxeColumn field="sex" title="性别" align="center">
|
<VxeColumn field="sex" title="性别" align="center">
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
const data = formData.value as Demo03StudentApi.Demo03Student;
|
const data = formData.value as Demo03StudentApi.Demo03Student;
|
||||||
// 拼接子表的数据
|
// 拼接子表的数据
|
||||||
data.demo03courses = demo03CourseFormRef.value?.getData();
|
data.demo03courses = demo03CourseFormRef.value?.getData();
|
||||||
data.demo03grade = demo03GradeFormRef.value?.getValues();
|
data.demo03grade = demo03GradeFormRef.value?.getValues() as any;
|
||||||
try {
|
try {
|
||||||
await (formData.value?.id
|
await (formData.value?.id
|
||||||
? updateDemo03Student(data)
|
? updateDemo03Student(data)
|
||||||
|
|
@ -135,7 +135,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
<RadioGroup v-model:value="formData.sex">
|
<RadioGroup v-model:value="formData.sex">
|
||||||
<Radio
|
<Radio
|
||||||
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')"
|
||||||
:key="dict.value"
|
:key="dict.value.toString()"
|
||||||
:value="dict.value"
|
:value="dict.value"
|
||||||
>
|
>
|
||||||
{{ dict.label }}
|
{{ dict.label }}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
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 { InfraFileApi } from '#/api/infra/file';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { getRangePickerDefaultProps } from '#/utils';
|
import { getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 表单的字段 */
|
/** 表单的字段 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -57,9 +52,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = InfraFileApi.File>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'name',
|
field: 'name',
|
||||||
|
|
@ -112,29 +105,10 @@ export function useGridColumns<T = InfraFileApi.File>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 160,
|
width: 160,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
slots: { default: 'actions' },
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '文件',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'copyUrl',
|
|
||||||
text: '复制链接',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['infra:file:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
<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 { InfraFileApi } from '#/api/infra/file';
|
import type { InfraFileApi } from '#/api/infra/file';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Upload } from '@vben/icons';
|
|
||||||
import { openWindow } from '@vben/utils';
|
import { openWindow } from '@vben/utils';
|
||||||
|
|
||||||
import { useClipboard } from '@vueuse/core';
|
import { useClipboard } from '@vueuse/core';
|
||||||
import { Button, Image, message } from 'ant-design-vue';
|
import { Button, Image, message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { deleteFile, getFilePage } from '#/api/infra/file';
|
import { deleteFile, getFilePage } from '#/api/infra/file';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
|
@ -30,13 +26,13 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 上传文件 */
|
/** 上传文件 */
|
||||||
function onUpload() {
|
function handleUpload() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 复制链接到剪贴板 */
|
/** 复制链接到剪贴板 */
|
||||||
const { copy } = useClipboard({ legacy: true });
|
const { copy } = useClipboard({ legacy: true });
|
||||||
async function onCopyUrl(row: InfraFileApi.File) {
|
async function handleCopyUrl(row: InfraFileApi.File) {
|
||||||
if (!row.url) {
|
if (!row.url) {
|
||||||
message.error('文件 URL 为空');
|
message.error('文件 URL 为空');
|
||||||
return;
|
return;
|
||||||
|
|
@ -50,15 +46,8 @@ async function onCopyUrl(row: InfraFileApi.File) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 打开 URL */
|
|
||||||
function openUrl(url?: string) {
|
|
||||||
if (url) {
|
|
||||||
openWindow(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除文件 */
|
/** 删除文件 */
|
||||||
async function onDelete(row: InfraFileApi.File) {
|
async function handleDelete(row: InfraFileApi.File) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name || row.path]),
|
content: $t('ui.actionMessage.deleting', [row.name || row.path]),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
|
|
@ -70,31 +59,17 @@ async function onDelete(row: InfraFileApi.File) {
|
||||||
$t('ui.actionMessage.deleteSuccess', [row.name || row.path]),
|
$t('ui.actionMessage.deleteSuccess', [row.name || row.path]),
|
||||||
);
|
);
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({ code, row }: OnActionClickParams<InfraFileApi.File>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'copyUrl': {
|
|
||||||
onCopyUrl(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -124,24 +99,47 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<FormModal @success="onRefresh" />
|
<FormModal @success="onRefresh" />
|
||||||
<Grid table-title="文件列表">
|
<Grid table-title="文件列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button type="primary" @click="onUpload">
|
<TableAction
|
||||||
<Upload class="size-5" />
|
:actions="[
|
||||||
上传图片
|
{
|
||||||
</Button>
|
label: '上传图片',
|
||||||
|
type: 'primary',
|
||||||
|
icon: ACTION_ICON.UPLOAD,
|
||||||
|
auth: ['infra:file:create'],
|
||||||
|
onClick: handleUpload,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #file-content="{ row }">
|
<template #file-content="{ row }">
|
||||||
<Image v-if="row.type && row.type.includes('image')" :src="row.url" />
|
<Image v-if="row.type && row.type.includes('image')" :src="row.url" />
|
||||||
<Button
|
<Button v-else type="link" @click="() => openWindow(row.url)">
|
||||||
v-else-if="row.type && row.type.includes('pdf')"
|
{{ row.type && row.type.includes('pdf') ? '预览' : '下载' }}
|
||||||
type="link"
|
|
||||||
@click="() => openUrl(row.url)"
|
|
||||||
>
|
|
||||||
预览
|
|
||||||
</Button>
|
|
||||||
<Button v-else type="link" @click="() => openUrl(row.url)">
|
|
||||||
下载
|
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '复制链接',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.COPY,
|
||||||
|
onClick: handleCopyUrl.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
auth: ['infra:file:delete'],
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
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 { InfraFileConfigApi } from '#/api/infra/file-config';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -265,9 +260,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = InfraFileConfigApi.FileConfig>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -309,39 +302,10 @@ export function useGridColumns<T = InfraFileConfigApi.FileConfig>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 280,
|
width: 240,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
slots: { default: 'actions' },
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '文件配置',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['infra:file-config:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['infra:file-config:delete']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'master',
|
|
||||||
text: '主配置',
|
|
||||||
disabled: (row: any) => row.master,
|
|
||||||
show: (_row: any) => hasAccessByCodes(['infra:file-config:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'test',
|
|
||||||
text: '测试',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +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 { InfraFileConfigApi } from '#/api/infra/file-config';
|
import type { InfraFileConfigApi } from '#/api/infra/file-config';
|
||||||
|
|
||||||
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Plus } from '@vben/icons';
|
|
||||||
import { openWindow } from '@vben/utils';
|
import { openWindow } from '@vben/utils';
|
||||||
|
|
||||||
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 {
|
import {
|
||||||
deleteFileConfig,
|
deleteFileConfig,
|
||||||
getFileConfigPage,
|
getFileConfigPage,
|
||||||
|
|
@ -34,17 +30,17 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建文件配置 */
|
/** 创建文件配置 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑文件配置 */
|
/** 编辑文件配置 */
|
||||||
function onEdit(row: InfraFileConfigApi.FileConfig) {
|
function handleEdit(row: InfraFileConfigApi.FileConfig) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 设为主配置 */
|
/** 设为主配置 */
|
||||||
async function onMaster(row: InfraFileConfigApi.FileConfig) {
|
async function handleMaster(row: InfraFileConfigApi.FileConfig) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.updating', [row.name]),
|
content: $t('ui.actionMessage.updating', [row.name]),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
|
|
@ -54,13 +50,13 @@ async function onMaster(row: InfraFileConfigApi.FileConfig) {
|
||||||
await updateFileConfigMaster(row.id as number);
|
await updateFileConfigMaster(row.id as number);
|
||||||
message.success($t('ui.actionMessage.operationSuccess'));
|
message.success($t('ui.actionMessage.operationSuccess'));
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 测试文件配置 */
|
/** 测试文件配置 */
|
||||||
async function onTest(row: InfraFileConfigApi.FileConfig) {
|
async function handleTest(row: InfraFileConfigApi.FileConfig) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: '测试上传中...',
|
content: '测试上传中...',
|
||||||
duration: 0,
|
duration: 0,
|
||||||
|
|
@ -78,58 +74,35 @@ async function onTest(row: InfraFileConfigApi.FileConfig) {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
openWindow(response);
|
openWindow(response);
|
||||||
});
|
});
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除文件配置 */
|
/** 删除文件配置 */
|
||||||
async function onDelete(row: InfraFileConfigApi.FileConfig) {
|
async function handleDelete(row: InfraFileConfigApi.FileConfig) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteFileConfig(row.id as number);
|
await deleteFileConfig(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<InfraFileConfigApi.FileConfig>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'master': {
|
|
||||||
onMaster(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'test': {
|
|
||||||
onTest(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -159,14 +132,58 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<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="['infra:file-config:create']"
|
label: $t('ui.actionTitle.create', ['角色']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['文件配置']) }}
|
auth: ['system:role:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['infra:file-config:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '测试',
|
||||||
|
type: 'link',
|
||||||
|
icon: 'lucide:test-tube-diagonal',
|
||||||
|
auth: ['infra:file-config:update'],
|
||||||
|
onClick: handleTest.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:drop-down-actions="[
|
||||||
|
{
|
||||||
|
label: '主配置',
|
||||||
|
type: 'link',
|
||||||
|
auth: ['infra:file-config:update'],
|
||||||
|
popConfirm: {
|
||||||
|
title: `是否要将${row.name}设为主配置?`,
|
||||||
|
confirm: handleMaster.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
auth: ['infra:file-config:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
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 { InfraJobApi } from '#/api/infra/job';
|
import type { DescriptionItemSchema } from '#/components/description';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { DICT_TYPE, getDictOptions, InfraJobStatusEnum } from '#/utils';
|
import { formatDateTime } from '@vben/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
import { Timeline } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
import { DICT_TYPE, getDictOptions } from '#/utils';
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
|
|
@ -124,9 +127,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格列配置 */
|
/** 表格列配置 */
|
||||||
export function useGridColumns<T = InfraJobApi.Job>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -163,58 +164,77 @@ export function useGridColumns<T = InfraJobApi.Job>(
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 280,
|
width: 240,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
slots: { default: 'actions' },
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '任务',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
},
|
||||||
name: 'CellOperation',
|
];
|
||||||
options: [
|
}
|
||||||
|
|
||||||
|
/** 详情的配置 */
|
||||||
|
export function useDetailSchema(): DescriptionItemSchema[] {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
code: 'edit',
|
field: 'id',
|
||||||
show: hasAccessByCodes(['infra:job:update']),
|
label: '任务编号',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: 'update-status',
|
field: 'name',
|
||||||
text: '开启',
|
label: '任务名称',
|
||||||
show: (row: any) =>
|
|
||||||
hasAccessByCodes(['infra:job:update']) &&
|
|
||||||
row.status === InfraJobStatusEnum.STOP,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: 'update-status',
|
field: 'status',
|
||||||
text: '暂停',
|
label: '任务状态',
|
||||||
show: (row: any) =>
|
content: (data) =>
|
||||||
hasAccessByCodes(['infra:job:update']) &&
|
h(DictTag, {
|
||||||
row.status === InfraJobStatusEnum.NORMAL,
|
type: DICT_TYPE.INFRA_JOB_STATUS,
|
||||||
|
value: data?.status,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: 'trigger',
|
field: 'handlerName',
|
||||||
text: '执行',
|
label: '处理器的名字',
|
||||||
show: hasAccessByCodes(['infra:job:trigger']),
|
|
||||||
},
|
|
||||||
// TODO @芋艿:增加一个“更多”选项
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: '详细',
|
|
||||||
show: hasAccessByCodes(['infra:job:query']),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: 'log',
|
field: 'handlerParam',
|
||||||
text: '日志',
|
label: '处理器的参数',
|
||||||
show: hasAccessByCodes(['infra:job:query']),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
code: 'delete',
|
field: 'cronExpression',
|
||||||
show: hasAccessByCodes(['infra:job:delete']),
|
label: 'CRON 表达式',
|
||||||
},
|
},
|
||||||
],
|
{
|
||||||
|
field: 'retryCount',
|
||||||
|
label: '重试次数',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'retryInterval',
|
||||||
|
label: '重试间隔',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'monitorTimeout',
|
||||||
|
label: '监控超时时间',
|
||||||
|
content: (data) =>
|
||||||
|
data?.monitorTimeout && data.monitorTimeout > 0
|
||||||
|
? `${data.monitorTimeout} 毫秒`
|
||||||
|
: '未开启',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'nextTimes',
|
||||||
|
label: '后续执行时间',
|
||||||
|
content: (data) => {
|
||||||
|
if (!data?.nextTimes) {
|
||||||
|
return '无后续执行时间';
|
||||||
|
}
|
||||||
|
if (data.nextTimes.length === 0) {
|
||||||
|
return '无后续执行时间';
|
||||||
|
}
|
||||||
|
return h(Timeline, {}, () =>
|
||||||
|
data.nextTimes.map((time: any) =>
|
||||||
|
h(Timeline.Item, {}, () => formatDateTime(time)?.toString()),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,15 @@
|
||||||
<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 { InfraJobApi } from '#/api/infra/job';
|
import type { InfraJobApi } from '#/api/infra/job';
|
||||||
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, History, Plus } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
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 {
|
import {
|
||||||
deleteJob,
|
deleteJob,
|
||||||
exportJob,
|
exportJob,
|
||||||
|
|
@ -47,28 +43,28 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportJob(await gridApi.formApi.getValues());
|
const data = await exportJob(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '定时任务.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '定时任务.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建任务 */
|
/** 创建任务 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑任务 */
|
/** 编辑任务 */
|
||||||
function onEdit(row: InfraJobApi.Job) {
|
function handleEdit(row: InfraJobApi.Job) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看任务详情 */
|
/** 查看任务详情 */
|
||||||
function onDetail(row: InfraJobApi.Job) {
|
function handleDetail(row: InfraJobApi.Job) {
|
||||||
detailModalApi.setData({ id: row.id }).open();
|
detailModalApi.setData({ id: row.id }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新任务状态 */
|
/** 更新任务状态 */
|
||||||
async function onUpdateStatus(row: InfraJobApi.Job) {
|
async function handleUpdateStatus(row: InfraJobApi.Job) {
|
||||||
const status =
|
const status =
|
||||||
row.status === InfraJobStatusEnum.STOP
|
row.status === InfraJobStatusEnum.STOP
|
||||||
? InfraJobStatusEnum.NORMAL
|
? InfraJobStatusEnum.NORMAL
|
||||||
|
|
@ -86,7 +82,7 @@ async function onUpdateStatus(row: InfraJobApi.Job) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 执行一次任务 */
|
/** 执行一次任务 */
|
||||||
async function onTrigger(row: InfraJobApi.Job) {
|
async function handleTrigger(row: InfraJobApi.Job) {
|
||||||
confirm({
|
confirm({
|
||||||
content: `确定执行一次 ${row.name} 吗?`,
|
content: `确定执行一次 ${row.name} 吗?`,
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
|
|
@ -96,7 +92,7 @@ async function onTrigger(row: InfraJobApi.Job) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 跳转到任务日志 */
|
/** 跳转到任务日志 */
|
||||||
function onLog(row?: InfraJobApi.Job) {
|
function handleLog(row?: InfraJobApi.Job) {
|
||||||
push({
|
push({
|
||||||
name: 'InfraJobLog',
|
name: 'InfraJobLog',
|
||||||
query: row?.id ? { id: row.id } : {},
|
query: row?.id ? { id: row.id } : {},
|
||||||
|
|
@ -104,7 +100,7 @@ function onLog(row?: InfraJobApi.Job) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除任务 */
|
/** 删除任务 */
|
||||||
async function onDelete(row: InfraJobApi.Job) {
|
async function handleDelete(row: InfraJobApi.Job) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
|
|
@ -119,42 +115,12 @@ async function onDelete(row: InfraJobApi.Job) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({ code, row }: OnActionClickParams<InfraJobApi.Job>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'log': {
|
|
||||||
onLog(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'trigger': {
|
|
||||||
onTrigger(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'update-status': {
|
|
||||||
onUpdateStatus(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -191,32 +157,91 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<DetailModal />
|
<DetailModal />
|
||||||
<Grid table-title="定时任务列表">
|
<Grid table-title="定时任务列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['infra:job:create']"
|
label: $t('ui.actionTitle.create', ['任务']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['任务']) }}
|
auth: ['infra:job:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
<Button
|
},
|
||||||
type="primary"
|
{
|
||||||
class="ml-2"
|
label: $t('ui.actionTitle.export'),
|
||||||
@click="onExport"
|
type: 'primary',
|
||||||
v-access:code="['infra:job:export']"
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
>
|
auth: ['infra:job:export'],
|
||||||
<Download class="size-5" />
|
onClick: handleExport,
|
||||||
{{ $t('ui.actionTitle.export') }}
|
},
|
||||||
</Button>
|
{
|
||||||
<Button
|
label: '执行日志',
|
||||||
type="primary"
|
type: 'primary',
|
||||||
class="ml-2"
|
icon: 'lucide:history',
|
||||||
@click="onLog(undefined)"
|
auth: ['infra:job:export'],
|
||||||
v-access:code="['infra:job:query']"
|
onClick: handleExport,
|
||||||
>
|
},
|
||||||
<History class="size-5" />
|
]"
|
||||||
执行日志
|
/>
|
||||||
</Button>
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['infra:job:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '开启',
|
||||||
|
type: 'link',
|
||||||
|
icon: 'lucide:circle-play',
|
||||||
|
auth: ['infra:job:update'],
|
||||||
|
ifShow: () => row.status === InfraJobStatusEnum.STOP,
|
||||||
|
onClick: handleUpdateStatus.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '暂停',
|
||||||
|
type: 'link',
|
||||||
|
icon: 'lucide:circle-pause',
|
||||||
|
auth: ['infra:job:update'],
|
||||||
|
ifShow: () => row.status === InfraJobStatusEnum.NORMAL,
|
||||||
|
onClick: handleUpdateStatus.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '执行',
|
||||||
|
type: 'link',
|
||||||
|
icon: 'lucide:clock-plus',
|
||||||
|
auth: ['infra:job:trigger'],
|
||||||
|
onClick: handleTrigger.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:drop-down-actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
auth: ['infra:job:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '日志',
|
||||||
|
type: 'link',
|
||||||
|
auth: ['infra:job:query'],
|
||||||
|
onClick: handleLog.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
auth: ['infra:job:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
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 { InfraJobLogApi } from '#/api/infra/job-log';
|
import type { DescriptionItemSchema } from '#/components/description';
|
||||||
|
|
||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
import { formatDateTime } from '@vben/utils';
|
import { formatDateTime } from '@vben/utils';
|
||||||
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import { DictTag } from '#/components/dict-tag';
|
||||||
import { DICT_TYPE, getDictOptions } from '#/utils';
|
import { DICT_TYPE, getDictOptions } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 列表的搜索表单 */
|
/** 列表的搜索表单 */
|
||||||
export function useGridFormSchema(): VbenFormSchema[] {
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -65,9 +65,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格列配置 */
|
/** 表格列配置 */
|
||||||
export function useGridColumns<T = InfraJobLogApi.JobLog>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -120,26 +118,61 @@ export function useGridColumns<T = InfraJobLogApi.JobLog>(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 80,
|
width: 80,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
slots: { default: 'actions' },
|
||||||
cellRender: {
|
},
|
||||||
attrs: {
|
];
|
||||||
nameField: 'id',
|
}
|
||||||
nameTitle: '日志',
|
|
||||||
onClick: onActionClick,
|
/** 详情的配置 */
|
||||||
},
|
export function useDetailSchema(): DescriptionItemSchema[] {
|
||||||
name: 'CellOperation',
|
return [
|
||||||
options: [
|
{
|
||||||
{
|
field: 'id',
|
||||||
code: 'detail',
|
label: '日志编号',
|
||||||
text: '详细',
|
},
|
||||||
show: hasAccessByCodes(['infra:job:query']),
|
{
|
||||||
},
|
field: 'jobId',
|
||||||
],
|
label: '任务编号',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'handlerName',
|
||||||
|
label: '处理器的名字',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'handlerParam',
|
||||||
|
label: '处理器的参数',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'executeIndex',
|
||||||
|
label: '第几次执行',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'beginTime',
|
||||||
|
label: '执行时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'endTime',
|
||||||
|
label: '结束时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'duration',
|
||||||
|
label: '执行时长',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
label: '任务状态',
|
||||||
|
content: (data) =>
|
||||||
|
h(DictTag, {
|
||||||
|
type: DICT_TYPE.INFRA_JOB_LOG_STATUS,
|
||||||
|
value: data?.status,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'result',
|
||||||
|
label: '执行结果',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +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 { InfraJobLogApi } from '#/api/infra/job-log';
|
import type { InfraJobLogApi } from '#/api/infra/job-log';
|
||||||
|
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
import { exportJobLog, getJobLogPage } from '#/api/infra/job-log';
|
import { exportJobLog, getJobLogPage } from '#/api/infra/job-log';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
import { DocAlert } from '#/components/doc-alert';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
@ -29,29 +23,16 @@ const [DetailModal, detailModalApi] = useVbenModal({
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportJobLog(await gridApi.formApi.getValues());
|
const data = await exportJobLog(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '任务日志.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '任务日志.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看日志详情 */
|
/** 查看日志详情 */
|
||||||
function onDetail(row: InfraJobLogApi.JobLog) {
|
function handleDetail(row: InfraJobLogApi.JobLog) {
|
||||||
detailModalApi.setData({ id: row.id }).open();
|
detailModalApi.setData({ id: row.id }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<InfraJobLogApi.JobLog>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取表单schema并设置默认jobId
|
// 获取表单schema并设置默认jobId
|
||||||
const formSchema = useGridFormSchema();
|
const formSchema = useGridFormSchema();
|
||||||
|
|
||||||
|
|
@ -60,7 +41,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
schema: formSchema,
|
schema: formSchema,
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick),
|
columns: useGridColumns(),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
|
|
@ -97,15 +78,30 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<DetailModal />
|
<DetailModal />
|
||||||
<Grid table-title="任务日志列表">
|
<Grid table-title="任务日志列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
class="ml-2"
|
{
|
||||||
@click="onExport"
|
label: $t('ui.actionTitle.export'),
|
||||||
v-access:code="['infra:job:export']"
|
type: 'primary',
|
||||||
>
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
<Download class="size-5" />
|
auth: ['infra:job:export'],
|
||||||
{{ $t('ui.actionTitle.export') }}
|
onClick: handleExport,
|
||||||
</Button>
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['infra:job:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,11 @@ import type { InfraJobLogApi } from '#/api/infra/job-log';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { formatDateTime } from '@vben/utils';
|
|
||||||
|
|
||||||
import { Descriptions } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { getJobLog } from '#/api/infra/job-log';
|
import { getJobLog } from '#/api/infra/job-log';
|
||||||
import { DictTag } from '#/components/dict-tag';
|
import { useDescription } from '#/components/description';
|
||||||
import { DICT_TYPE } from '#/utils';
|
|
||||||
|
import { useDetailSchema } from '../data';
|
||||||
|
|
||||||
const formData = ref<InfraJobLogApi.JobLog>();
|
const formData = ref<InfraJobLogApi.JobLog>();
|
||||||
|
|
||||||
|
|
@ -33,6 +31,15 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [Description] = useDescription({
|
||||||
|
componentProps: {
|
||||||
|
bordered: true,
|
||||||
|
column: 1,
|
||||||
|
class: 'mx-4',
|
||||||
|
},
|
||||||
|
schema: useDetailSchema(),
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -42,44 +49,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
:show-cancel-button="false"
|
:show-cancel-button="false"
|
||||||
:show-confirm-button="false"
|
:show-confirm-button="false"
|
||||||
>
|
>
|
||||||
<Descriptions
|
<Description :data="formData" />
|
||||||
:column="1"
|
|
||||||
bordered
|
|
||||||
size="middle"
|
|
||||||
class="mx-4"
|
|
||||||
:label-style="{ width: '140px' }"
|
|
||||||
>
|
|
||||||
<Descriptions.Item label="日志编号">
|
|
||||||
{{ formData?.id }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="任务编号">
|
|
||||||
{{ formData?.jobId }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="处理器的名字">
|
|
||||||
{{ formData?.handlerName }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="处理器的参数">
|
|
||||||
{{ formData?.handlerParam }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="第几次执行">
|
|
||||||
{{ formData?.executeIndex }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="执行时间">
|
|
||||||
{{ formData?.beginTime ? formatDateTime(formData.beginTime) : '' }} ~
|
|
||||||
{{ formData?.endTime ? formatDateTime(formData.endTime) : '' }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="执行时长">
|
|
||||||
{{ formData?.duration ? `${formData.duration} 毫秒` : '' }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="任务状态">
|
|
||||||
<DictTag
|
|
||||||
:type="DICT_TYPE.INFRA_JOB_LOG_STATUS"
|
|
||||||
:value="formData?.status"
|
|
||||||
/>
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="执行结果">
|
|
||||||
{{ formData?.result }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
</Descriptions>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,11 @@ import type { InfraJobApi } from '#/api/infra/job';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { formatDateTime } from '@vben/utils';
|
|
||||||
|
|
||||||
import { Descriptions, Timeline } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import { getJob, getJobNextTimes } from '#/api/infra/job';
|
import { getJob, getJobNextTimes } from '#/api/infra/job';
|
||||||
import { DictTag } from '#/components/dict-tag';
|
import { useDescription } from '#/components/description';
|
||||||
import { DICT_TYPE } from '#/utils';
|
|
||||||
|
import { useDetailSchema } from '../data';
|
||||||
|
|
||||||
const formData = ref<InfraJobApi.Job>(); // 任务详情
|
const formData = ref<InfraJobApi.Job>(); // 任务详情
|
||||||
const nextTimes = ref<Date[]>([]); // 下一次执行时间
|
const nextTimes = ref<Date[]>([]); // 下一次执行时间
|
||||||
|
|
@ -31,11 +29,21 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
formData.value = await getJob(data.id);
|
formData.value = await getJob(data.id);
|
||||||
// 获取下一次执行时间
|
// 获取下一次执行时间
|
||||||
nextTimes.value = await getJobNextTimes(data.id);
|
nextTimes.value = await getJobNextTimes(data.id);
|
||||||
|
formData.value.nextTimes = nextTimes.value;
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [Description] = useDescription({
|
||||||
|
componentProps: {
|
||||||
|
bordered: true,
|
||||||
|
column: 1,
|
||||||
|
class: 'mx-4',
|
||||||
|
},
|
||||||
|
schema: useDetailSchema(),
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -45,57 +53,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
:show-cancel-button="false"
|
:show-cancel-button="false"
|
||||||
:show-confirm-button="false"
|
:show-confirm-button="false"
|
||||||
>
|
>
|
||||||
<Descriptions
|
<Description :data="formData" />
|
||||||
:column="1"
|
|
||||||
bordered
|
|
||||||
size="middle"
|
|
||||||
class="mx-4"
|
|
||||||
:label-style="{ width: '140px' }"
|
|
||||||
>
|
|
||||||
<Descriptions.Item label="任务编号">
|
|
||||||
{{ formData?.id }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="任务名称">
|
|
||||||
{{ formData?.name }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="任务状态">
|
|
||||||
<DictTag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="formData?.status" />
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="处理器的名字">
|
|
||||||
{{ formData?.handlerName }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="处理器的参数">
|
|
||||||
{{ formData?.handlerParam }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="Cron 表达式">
|
|
||||||
{{ formData?.cronExpression }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="重试次数">
|
|
||||||
{{ formData?.retryCount }}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="重试间隔">
|
|
||||||
{{
|
|
||||||
formData?.retryInterval ? `${formData.retryInterval} 毫秒` : '无间隔'
|
|
||||||
}}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="监控超时时间">
|
|
||||||
{{
|
|
||||||
formData?.monitorTimeout && formData.monitorTimeout > 0
|
|
||||||
? `${formData.monitorTimeout} 毫秒`
|
|
||||||
: '未开启'
|
|
||||||
}}
|
|
||||||
</Descriptions.Item>
|
|
||||||
<Descriptions.Item label="后续执行时间">
|
|
||||||
<Timeline class="h-[180px]">
|
|
||||||
<Timeline.Item
|
|
||||||
v-for="(nextTime, index) in nextTimes"
|
|
||||||
:key="index"
|
|
||||||
color="blue"
|
|
||||||
>
|
|
||||||
第 {{ index + 1 }} 次:{{ formatDateTime(nextTime.toString()) }}
|
|
||||||
</Timeline.Item>
|
|
||||||
</Timeline>
|
|
||||||
</Descriptions.Item>
|
|
||||||
</Descriptions>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,16 @@ import Memory from './modules/memory.vue';
|
||||||
const redisData = ref<InfraRedisApi.RedisMonitorInfo>();
|
const redisData = ref<InfraRedisApi.RedisMonitorInfo>();
|
||||||
|
|
||||||
/** 统一加载 Redis 数据 */
|
/** 统一加载 Redis 数据 */
|
||||||
const loadRedisData = async () => {
|
async function loadRedisData() {
|
||||||
try {
|
try {
|
||||||
redisData.value = await getRedisMonitorInfo();
|
redisData.value = await getRedisMonitorInfo();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载 Redis 数据失败', error);
|
console.error('加载 Redis 数据失败', error);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
loadRedisData();
|
await loadRedisData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -37,9 +37,11 @@ onMounted(() => {
|
||||||
<DocAlert title="本地缓存" url="https://doc.iocoder.cn/local-cache/" />
|
<DocAlert title="本地缓存" url="https://doc.iocoder.cn/local-cache/" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<Card class="mt-5" title="Redis 概览">
|
<div class="class=" mt-5>
|
||||||
|
<Card title="Redis 概览">
|
||||||
<Info :redis-data="redisData" />
|
<Info :redis-data="redisData" />
|
||||||
</Card>
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-5 grid grid-cols-1 gap-4 md:grid-cols-2">
|
<div class="mt-5 grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
<Card title="内存使用">
|
<Card title="内存使用">
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
|
||||||
/** 渲染命令统计图表 */
|
/** 渲染命令统计图表 */
|
||||||
const renderCommandStats = () => {
|
function renderCommandStats() {
|
||||||
if (!props.redisData?.commandStats) {
|
if (!props.redisData?.commandStats) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ const renderCommandStats = () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 监听数据变化,重新渲染图表 */
|
/** 监听数据变化,重新渲染图表 */
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -97,7 +97,5 @@ onMounted(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<EchartsUI ref="chartRef" height="420px" />
|
<EchartsUI ref="chartRef" height="420px" />
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
|
||||||
/** 解析内存值,移除单位,转为数字 */
|
/** 解析内存值,移除单位,转为数字 */
|
||||||
const parseMemoryValue = (memStr: string | undefined): number => {
|
function parseMemoryValue(memStr: string | undefined): number {
|
||||||
if (!memStr) {
|
if (!memStr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -27,10 +27,10 @@ const parseMemoryValue = (memStr: string | undefined): number => {
|
||||||
} catch {
|
} catch {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 渲染内存使用图表 */
|
/** 渲染内存使用图表 */
|
||||||
const renderMemoryChart = () => {
|
function renderMemoryChart() {
|
||||||
if (!props.redisData?.info) {
|
if (!props.redisData?.info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,7 @@ const renderMemoryChart = () => {
|
||||||
detail: {
|
detail: {
|
||||||
show: true,
|
show: true,
|
||||||
offsetCenter: [0, '50%'],
|
offsetCenter: [0, '50%'],
|
||||||
color: 'auto',
|
color: 'inherit',
|
||||||
fontSize: 30,
|
fontSize: 30,
|
||||||
formatter: usedMemory,
|
formatter: usedMemory,
|
||||||
},
|
},
|
||||||
|
|
@ -110,7 +110,7 @@ const renderMemoryChart = () => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 监听数据变化,重新渲染图表 */
|
/** 监听数据变化,重新渲染图表 */
|
||||||
watch(
|
watch(
|
||||||
|
|
@ -131,7 +131,5 @@ onMounted(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<EchartsUI ref="chartRef" height="420px" />
|
<EchartsUI ref="chartRef" height="420px" />
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ watchEffect(() => {
|
||||||
/** 发送消息 */
|
/** 发送消息 */
|
||||||
const sendText = ref(''); // 发送内容
|
const sendText = ref(''); // 发送内容
|
||||||
const sendUserId = ref(''); // 发送人
|
const sendUserId = ref(''); // 发送人
|
||||||
const handlerSend = () => {
|
function handlerSend() {
|
||||||
if (!sendText.value.trim()) {
|
if (!sendText.value.trim()) {
|
||||||
message.warning('消息内容不能为空');
|
message.warning('消息内容不能为空');
|
||||||
return;
|
return;
|
||||||
|
|
@ -119,19 +119,19 @@ const handlerSend = () => {
|
||||||
// 2. 最后发送消息
|
// 2. 最后发送消息
|
||||||
send(jsonMessage);
|
send(jsonMessage);
|
||||||
sendText.value = '';
|
sendText.value = '';
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 切换 websocket 连接状态 */
|
/** 切换 websocket 连接状态 */
|
||||||
const toggleConnectStatus = () => {
|
function toggleConnectStatus() {
|
||||||
if (getIsOpen.value) {
|
if (getIsOpen.value) {
|
||||||
close();
|
close();
|
||||||
} else {
|
} else {
|
||||||
open();
|
open();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 获取消息类型的徽标颜色 */
|
/** 获取消息类型的徽标颜色 */
|
||||||
const getMessageBadgeColor = (type?: string) => {
|
function getMessageBadgeColor(type?: string) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'group': {
|
case 'group': {
|
||||||
return 'green';
|
return 'green';
|
||||||
|
|
@ -146,10 +146,10 @@ const getMessageBadgeColor = (type?: string) => {
|
||||||
return 'default';
|
return 'default';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 获取消息类型的文本 */
|
/** 获取消息类型的文本 */
|
||||||
const getMessageTypeText = (type?: string) => {
|
function getMessageTypeText(type?: string) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'group': {
|
case 'group': {
|
||||||
return '群发';
|
return '群发';
|
||||||
|
|
@ -164,7 +164,7 @@ const getMessageTypeText = (type?: string) => {
|
||||||
return '未知';
|
return '未知';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
const userList = ref<SystemUserApi.User[]>([]); // 用户列表
|
const userList = ref<SystemUserApi.User[]>([]); // 用户列表
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询 IP */
|
/** 查询 IP */
|
||||||
function onQueryIp() {
|
function handleQueryIp() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<FormModal @success="onRefresh" />
|
<FormModal @success="onRefresh" />
|
||||||
<Grid table-title="地区列表">
|
<Grid table-title="地区列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button type="primary" @click="onQueryIp">
|
<Button type="primary" @click="handleQueryIp">
|
||||||
<Search class="size-5" />
|
<Search class="size-5" />
|
||||||
IP 查询
|
IP 查询
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
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 { SystemDeptApi } from '#/api/system/dept';
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
import { handleTree } from '@vben/utils';
|
import { handleTree } from '@vben/utils';
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
|
|
@ -10,8 +9,6 @@ import { getDeptList } from '#/api/system/dept';
|
||||||
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 [
|
||||||
|
|
@ -113,7 +110,6 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns(
|
export function useGridColumns(
|
||||||
onActionClick?: OnActionClickFn<SystemDeptApi.Dept>,
|
|
||||||
getLeaderName?: (userId: number) => string | undefined,
|
getLeaderName?: (userId: number) => string | undefined,
|
||||||
): VxeTableGridOptions<SystemDeptApi.Dept>['columns'] {
|
): VxeTableGridOptions<SystemDeptApi.Dept>['columns'] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -154,39 +150,10 @@ export function useGridColumns(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 200,
|
width: 220,
|
||||||
align: 'right',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
headerAlign: 'center',
|
slots: { default: 'actions' },
|
||||||
showOverflow: false,
|
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '部门',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'append',
|
|
||||||
text: '新增下级',
|
|
||||||
show: hasAccessByCodes(['system:dept:create']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['system:dept:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['system:dept:delete']),
|
|
||||||
disabled: (row: SystemDeptApi.Dept) => {
|
|
||||||
return !!(row.children && row.children.length > 0);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,15 @@
|
||||||
<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 { SystemDeptApi } from '#/api/system/dept';
|
import type { SystemDeptApi } from '#/api/system/dept';
|
||||||
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 { 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 { deleteDept, getDeptList } from '#/api/system/dept';
|
import { deleteDept, getDeptList } from '#/api/system/dept';
|
||||||
import { getSimpleUserList } from '#/api/system/user';
|
import { getSimpleUserList } from '#/api/system/user';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
@ -29,9 +25,9 @@ const [FormModal, formModalApi] = useVbenModal({
|
||||||
const userList = ref<SystemUserApi.User[]>([]);
|
const userList = ref<SystemUserApi.User[]>([]);
|
||||||
|
|
||||||
/** 获取负责人名称 */
|
/** 获取负责人名称 */
|
||||||
const getLeaderName = (userId: number) => {
|
function getLeaderName(userId: number) {
|
||||||
return userList.value.find((user) => user.id === userId)?.nickname;
|
return userList.value.find((user) => user.id === userId)?.nickname;
|
||||||
};
|
}
|
||||||
|
|
||||||
/** 刷新表格 */
|
/** 刷新表格 */
|
||||||
function onRefresh() {
|
function onRefresh() {
|
||||||
|
|
@ -46,57 +42,41 @@ function toggleExpand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建部门 */
|
/** 创建部门 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 添加下级部门 */
|
/** 添加下级部门 */
|
||||||
function onAppend(row: SystemDeptApi.Dept) {
|
function handleAppend(row: SystemDeptApi.Dept) {
|
||||||
formModalApi.setData({ parentId: row.id }).open();
|
formModalApi.setData({ parentId: row.id }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑部门 */
|
/** 编辑部门 */
|
||||||
function onEdit(row: SystemDeptApi.Dept) {
|
function handleEdit(row: SystemDeptApi.Dept) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除部门 */
|
/** 删除部门 */
|
||||||
async function onDelete(row: SystemDeptApi.Dept) {
|
async function handleDelete(row: SystemDeptApi.Dept) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteDept(row.id as number);
|
await deleteDept(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({ code, row }: OnActionClickParams<SystemDeptApi.Dept>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'append': {
|
|
||||||
onAppend(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick, getLeaderName),
|
columns: useGridColumns(getLeaderName),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
pagerConfig: {
|
pagerConfig: {
|
||||||
|
|
@ -136,17 +116,54 @@ 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="['system:dept:create']"
|
label: $t('ui.actionTitle.create', ['菜单']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['部门']) }}
|
auth: ['system:dept:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
<Button class="ml-2" @click="toggleExpand">
|
},
|
||||||
{{ isExpanded ? '收缩' : '展开' }}
|
{
|
||||||
</Button>
|
label: isExpanded ? '收缩' : '展开',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: toggleExpand,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '新增下级',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['system:menu:create'],
|
||||||
|
onClick: handleAppend.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:menu:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['system:menu:delete'],
|
||||||
|
disabled: !!(row.children && row.children.length > 0),
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import TypeGrid from './modules/type-grid.vue';
|
||||||
|
|
||||||
const searchDictType = ref<string>(); // 搜索的字典类型
|
const searchDictType = ref<string>(); // 搜索的字典类型
|
||||||
|
|
||||||
function onDictTypeSelect(dictType: string) {
|
function handleDictTypeSelect(dictType: string) {
|
||||||
searchDictType.value = dictType;
|
searchDictType.value = dictType;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -24,7 +24,7 @@ function onDictTypeSelect(dictType: string) {
|
||||||
<div class="flex h-full">
|
<div class="flex h-full">
|
||||||
<!-- 左侧字典类型列表 -->
|
<!-- 左侧字典类型列表 -->
|
||||||
<div class="w-1/2 pr-3">
|
<div class="w-1/2 pr-3">
|
||||||
<TypeGrid @select="onDictTypeSelect" />
|
<TypeGrid @select="handleDictTypeSelect" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 右侧字典数据列表 -->
|
<!-- 右侧字典数据列表 -->
|
||||||
<div class="w-1/2">
|
<div class="w-1/2">
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,16 @@ import type { SystemDictDataApi } from '#/api/system/dict/data';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
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 {
|
import {
|
||||||
deleteDictData,
|
deleteDictData,
|
||||||
exportDictData,
|
exportDictData,
|
||||||
getDictDataPage,
|
getDictDataPage,
|
||||||
} from '#/api/system/dict/data';
|
} from '#/api/system/dict/data';
|
||||||
import { ACTION_KEY, TableAction } from '#/components/table-action';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useDataGridColumns, useDataGridFormSchema } from '../data';
|
import { useDataGridColumns, useDataGridFormSchema } from '../data';
|
||||||
|
|
@ -40,33 +38,37 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportDictData(await gridApi.formApi.getValues());
|
const data = await exportDictData(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '字典数据.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '字典数据.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建字典数据 */
|
/** 创建字典数据 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
dataFormModalApi.setData({ dictType: props.dictType }).open();
|
dataFormModalApi.setData({ dictType: props.dictType }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑字典数据 */
|
/** 编辑字典数据 */
|
||||||
function onEdit(row: SystemDictDataApi.DictData) {
|
function handleEdit(row: SystemDictDataApi.DictData) {
|
||||||
dataFormModalApi.setData(row).open();
|
dataFormModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除字典数据 */
|
/** 删除字典数据 */
|
||||||
async function onDelete(row: SystemDictDataApi.DictData) {
|
async function handleDelete(row: SystemDictDataApi.DictData) {
|
||||||
message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.label]),
|
content: $t('ui.actionMessage.deleting', [row.label]),
|
||||||
key: ACTION_KEY,
|
key: 'action_key_msg',
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
await deleteDictData(row.id as number);
|
await deleteDictData(row.id as number);
|
||||||
message.success({
|
message.success({
|
||||||
content: $t('ui.actionMessage.deleteSuccess', [row.label]),
|
content: $t('ui.actionMessage.deleteSuccess', [row.label]),
|
||||||
key: ACTION_KEY,
|
key: 'action_key_msg',
|
||||||
});
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
|
@ -116,23 +118,24 @@ watch(
|
||||||
|
|
||||||
<Grid table-title="字典数据列表">
|
<Grid table-title="字典数据列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['system:dict:create']"
|
label: $t('ui.actionTitle.create', ['字典数据']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['字典数据']) }}
|
auth: ['system:dict:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
<Button
|
},
|
||||||
type="primary"
|
{
|
||||||
class="ml-2"
|
label: $t('ui.actionTitle.export'),
|
||||||
@click="onExport"
|
type: 'primary',
|
||||||
v-access:code="['system:dict:export']"
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
>
|
auth: ['system:dict:export'],
|
||||||
<Download class="size-5" />
|
onClick: handleExport,
|
||||||
{{ $t('ui.actionTitle.export') }}
|
},
|
||||||
</Button>
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{ row }">
|
<template #actions="{ row }">
|
||||||
<TableAction
|
<TableAction
|
||||||
|
|
@ -140,19 +143,19 @@ watch(
|
||||||
{
|
{
|
||||||
label: $t('common.edit'),
|
label: $t('common.edit'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
icon: 'ant-design:edit-outlined',
|
icon: ACTION_ICON.EDIT,
|
||||||
auth: ['system:dict:update'],
|
auth: ['system:dict:update'],
|
||||||
onClick: onEdit.bind(null, row),
|
onClick: handleEdit.bind(null, row),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('common.delete'),
|
label: $t('common.delete'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
danger: true,
|
danger: true,
|
||||||
icon: 'ant-design:delete-outlined',
|
icon: ACTION_ICON.DELETE,
|
||||||
auth: ['system:dict:delete'],
|
auth: ['system:dict:delete'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: $t('ui.actionMessage.deleteConfirm', [row.label]),
|
title: $t('ui.actionMessage.deleteConfirm', [row.label]),
|
||||||
confirm: onDelete.bind(null, row),
|
confirm: handleDelete.bind(null, row),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,16 @@ import type {
|
||||||
import type { SystemDictTypeApi } from '#/api/system/dict/type';
|
import type { SystemDictTypeApi } from '#/api/system/dict/type';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
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 {
|
import {
|
||||||
deleteDictType,
|
deleteDictType,
|
||||||
exportDictType,
|
exportDictType,
|
||||||
getDictTypePage,
|
getDictTypePage,
|
||||||
} from '#/api/system/dict/type';
|
} from '#/api/system/dict/type';
|
||||||
import { ACTION_KEY, TableAction } from '#/components/table-action';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useTypeGridColumns, useTypeGridFormSchema } from '../data';
|
import { useTypeGridColumns, useTypeGridFormSchema } from '../data';
|
||||||
|
|
@ -36,33 +34,37 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportDictType(await gridApi.formApi.getValues());
|
const data = await exportDictType(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '字典类型.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '字典类型.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建字典类型 */
|
/** 创建字典类型 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
typeFormModalApi.setData(null).open();
|
typeFormModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑字典类型 */
|
/** 编辑字典类型 */
|
||||||
function onEdit(row: any) {
|
function handleEdit(row: any) {
|
||||||
typeFormModalApi.setData(row).open();
|
typeFormModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除字典类型 */
|
/** 删除字典类型 */
|
||||||
async function onDelete(row: SystemDictTypeApi.DictType) {
|
async function handleDelete(row: SystemDictTypeApi.DictType) {
|
||||||
message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
key: ACTION_KEY,
|
key: 'action_key_msg',
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
await deleteDictType(row.id as number);
|
await deleteDictType(row.id as number);
|
||||||
message.success({
|
message.success({
|
||||||
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
key: ACTION_KEY,
|
key: 'action_key_msg',
|
||||||
});
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格事件 */
|
/** 表格事件 */
|
||||||
|
|
@ -110,23 +112,24 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
|
||||||
<Grid table-title="字典类型列表">
|
<Grid table-title="字典类型列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['system:dict:create']"
|
label: $t('ui.actionTitle.create', ['字典类型']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['字典类型']) }}
|
auth: ['system:dict:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
<Button
|
},
|
||||||
type="primary"
|
{
|
||||||
class="ml-2"
|
label: $t('ui.actionTitle.export'),
|
||||||
@click="onExport"
|
type: 'primary',
|
||||||
v-access:code="['system:dict:export']"
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
>
|
auth: ['system:dict:export'],
|
||||||
<Download class="size-5" />
|
onClick: handleExport,
|
||||||
{{ $t('ui.actionTitle.export') }}
|
},
|
||||||
</Button>
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #actions="{ row }">
|
<template #actions="{ row }">
|
||||||
<TableAction
|
<TableAction
|
||||||
|
|
@ -134,19 +137,19 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
{
|
{
|
||||||
label: $t('common.edit'),
|
label: $t('common.edit'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
icon: 'ant-design:edit-outlined',
|
icon: ACTION_ICON.EDIT,
|
||||||
auth: ['system:dict:update'],
|
auth: ['system:dict:update'],
|
||||||
onClick: onEdit.bind(null, row),
|
onClick: handleEdit.bind(null, row),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('common.delete'),
|
label: $t('common.delete'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
danger: true,
|
danger: true,
|
||||||
icon: 'ant-design:delete-outlined',
|
icon: ACTION_ICON.DELETE,
|
||||||
auth: ['system:dict:delete'],
|
auth: ['system:dict:delete'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
confirm: onDelete.bind(null, row),
|
confirm: handleDelete.bind(null, row),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
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 { SystemLoginLogApi } from '#/api/system/login-log';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { DICT_TYPE, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 列表的搜索表单 */
|
/** 列表的搜索表单 */
|
||||||
export function useGridFormSchema(): VbenFormSchema[] {
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -42,9 +37,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemLoginLogApi.LoginLog>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -91,26 +84,10 @@ export function useGridColumns<T = SystemLoginLogApi.LoginLog>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 120,
|
width: 80,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'username',
|
|
||||||
nameTitle: '登录日志',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: '详情',
|
|
||||||
show: hasAccessByCodes(['system:login-log:query']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
<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 { SystemLoginLogApi } from '#/api/system/login-log';
|
import type { SystemLoginLogApi } from '#/api/system/login-log';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
import { Button } from 'ant-design-vue';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
|
||||||
import { exportLoginLog, getLoginLogPage } from '#/api/system/login-log';
|
import { exportLoginLog, getLoginLogPage } from '#/api/system/login-log';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
import { DocAlert } from '#/components/doc-alert';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
@ -30,35 +24,22 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportLoginLog(await gridApi.formApi.getValues());
|
const data = await exportLoginLog(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '登录日志.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '登录日志.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看登录日志详情 */
|
/** 查看登录日志详情 */
|
||||||
function onDetail(row: SystemLoginLogApi.LoginLog) {
|
function handleDetail(row: SystemLoginLogApi.LoginLog) {
|
||||||
detailModalApi.setData(row).open();
|
detailModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemLoginLogApi.LoginLog>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -92,15 +73,30 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<DetailModal @success="onRefresh" />
|
<DetailModal @success="onRefresh" />
|
||||||
<Grid table-title="登录日志列表">
|
<Grid table-title="登录日志列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
class="ml-2"
|
{
|
||||||
@click="onExport"
|
label: $t('ui.actionTitle.export'),
|
||||||
v-access:code="['system:login-log:export']"
|
type: 'primary',
|
||||||
>
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
<Download class="size-5" />
|
auth: ['system:login-log:export'],
|
||||||
{{ $t('ui.actionTitle.export') }}
|
onClick: handleExport,
|
||||||
</Button>
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['system:login-log:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +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 { SystemMailAccountApi } from '#/api/system/mail/account';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { DICT_TYPE, getDictOptions } from '#/utils';
|
import { DICT_TYPE, getDictOptions } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -125,9 +120,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemMailAccountApi.MailAccount>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -179,29 +172,10 @@ export function useGridColumns<T = SystemMailAccountApi.MailAccount>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 130,
|
width: 130,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'mail',
|
|
||||||
nameTitle: '邮箱账号',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['system:mail-account:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['system:mail-account:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
<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 { SystemMailAccountApi } from '#/api/system/mail/account';
|
import type { SystemMailAccountApi } from '#/api/system/mail/account';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { 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 {
|
import {
|
||||||
deleteMailAccount,
|
deleteMailAccount,
|
||||||
getMailAccountPage,
|
getMailAccountPage,
|
||||||
|
|
@ -32,54 +28,39 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建邮箱账号 */
|
/** 创建邮箱账号 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑邮箱账号 */
|
/** 编辑邮箱账号 */
|
||||||
function onEdit(row: SystemMailAccountApi.MailAccount) {
|
function handleEdit(row: SystemMailAccountApi.MailAccount) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除邮箱账号 */
|
/** 删除邮箱账号 */
|
||||||
async function onDelete(row: SystemMailAccountApi.MailAccount) {
|
async function handleDelete(row: SystemMailAccountApi.MailAccount) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.mail]),
|
content: $t('ui.actionMessage.deleting', [row.mail]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteMailAccount(row.id as number);
|
await deleteMailAccount(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.mail]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.mail]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemMailAccountApi.MailAccount>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -112,14 +93,41 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<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="['system:mail-account:create']"
|
label: $t('ui.actionTitle.create', ['邮箱账号']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['邮箱账号']) }}
|
auth: ['system:mail-account:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:mail-account:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['system:mail-account:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +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 { SystemMailLogApi } from '#/api/system/mail/log';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { getSimpleMailAccountList } from '#/api/system/mail/account';
|
import { getSimpleMailAccountList } from '#/api/system/mail/account';
|
||||||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 列表的搜索表单 */
|
/** 列表的搜索表单 */
|
||||||
export function useGridFormSchema(): VbenFormSchema[] {
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -75,9 +70,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemMailLogApi.MailLog>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -125,26 +118,10 @@ export function useGridColumns<T = SystemMailLogApi.MailLog>(
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 80,
|
width: 80,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'toMail',
|
|
||||||
nameTitle: '邮件日志',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: '查看',
|
|
||||||
show: hasAccessByCodes(['system:mail-log:query']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
<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 { SystemMailLogApi } from '#/api/system/mail/log';
|
import type { SystemMailLogApi } from '#/api/system/mail/log';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { getMailLogPage } from '#/api/system/mail/log';
|
import { getMailLogPage } from '#/api/system/mail/log';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
import { DocAlert } from '#/components/doc-alert';
|
||||||
|
|
||||||
|
|
@ -25,29 +22,16 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看邮件日志 */
|
/** 查看邮件日志 */
|
||||||
function onDetail(row: SystemMailLogApi.MailLog) {
|
function handleDetail(row: SystemMailLogApi.MailLog) {
|
||||||
detailModalApi.setData(row).open();
|
detailModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemMailLogApi.MailLog>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -79,7 +63,19 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
|
||||||
<DetailModal @success="onRefresh" />
|
<DetailModal @success="onRefresh" />
|
||||||
<Grid table-title="邮件日志列表">
|
<Grid table-title="邮件日志列表">
|
||||||
<template #toolbar-tools> </template>
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['system:mail-log:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
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 { SystemMailTemplateApi } from '#/api/system/mail/template';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { getSimpleMailAccountList } from '#/api/system/mail/account';
|
import { getSimpleMailAccountList } from '#/api/system/mail/account';
|
||||||
|
|
@ -13,8 +10,6 @@ import {
|
||||||
getRangePickerDefaultProps,
|
getRangePickerDefaultProps,
|
||||||
} from '#/utils';
|
} from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -193,8 +188,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemMailTemplateApi.MailTemplate>(
|
export function useGridColumns(
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
getAccountMail?: (accountId: number) => string | undefined,
|
getAccountMail?: (accountId: number) => string | undefined,
|
||||||
): VxeTableGridOptions['columns'] {
|
): VxeTableGridOptions['columns'] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -245,34 +239,10 @@ export function useGridColumns<T = SystemMailTemplateApi.MailTemplate>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 150,
|
width: 220,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '邮件模板',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['system:mail-template:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['system:mail-template:delete']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'send',
|
|
||||||
text: '测试',
|
|
||||||
show: hasAccessByCodes(['system:mail-template:send-mail']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,15 @@
|
||||||
<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 { SystemMailAccountApi } from '#/api/system/mail/account';
|
import type { SystemMailAccountApi } from '#/api/system/mail/account';
|
||||||
import type { SystemMailTemplateApi } from '#/api/system/mail/template';
|
import type { SystemMailTemplateApi } from '#/api/system/mail/template';
|
||||||
|
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { 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 { getSimpleMailAccountList } from '#/api/system/mail/account';
|
import { getSimpleMailAccountList } from '#/api/system/mail/account';
|
||||||
import {
|
import {
|
||||||
deleteMailTemplate,
|
deleteMailTemplate,
|
||||||
|
|
@ -28,11 +24,6 @@ import SendForm from './modules/send-form.vue';
|
||||||
|
|
||||||
const accountList = ref<SystemMailAccountApi.MailAccount[]>([]);
|
const accountList = ref<SystemMailAccountApi.MailAccount[]>([]);
|
||||||
|
|
||||||
/** 获取邮箱账号 */
|
|
||||||
const getAccountMail = (accountId: number) => {
|
|
||||||
return accountList.value.find((account) => account.id === accountId)?.mail;
|
|
||||||
};
|
|
||||||
|
|
||||||
const [FormModal, formModalApi] = useVbenModal({
|
const [FormModal, formModalApi] = useVbenModal({
|
||||||
connectedComponent: Form,
|
connectedComponent: Form,
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
|
|
@ -49,55 +40,38 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建邮件模板 */
|
/** 创建邮件模板 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑邮件模板 */
|
/** 编辑邮件模板 */
|
||||||
function onEdit(row: SystemMailTemplateApi.MailTemplate) {
|
function handleEdit(row: SystemMailTemplateApi.MailTemplate) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 发送测试邮件 */
|
/** 发送测试邮件 */
|
||||||
function onSend(row: SystemMailTemplateApi.MailTemplate) {
|
function handleSend(row: SystemMailTemplateApi.MailTemplate) {
|
||||||
sendModalApi.setData(row).open();
|
sendModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除邮件模板 */
|
/** 删除邮件模板 */
|
||||||
async function onDelete(row: SystemMailTemplateApi.MailTemplate) {
|
async function handleDelete(row: SystemMailTemplateApi.MailTemplate) {
|
||||||
const hideLoading = message.loading({
|
message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
duration: 0,
|
||||||
key: 'action_process_msg',
|
key: 'action_process_msg',
|
||||||
});
|
});
|
||||||
try {
|
|
||||||
await deleteMailTemplate(row.id as number);
|
await deleteMailTemplate(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} finally {
|
|
||||||
hideLoading();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
/** 获取邮箱账号 */
|
||||||
function onActionClick({
|
function getAccountMail(accountId: number) {
|
||||||
code,
|
return accountList.value.find((account) => account.id === accountId)?.mail;
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemMailTemplateApi.MailTemplate>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'send': {
|
|
||||||
onSend(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
|
@ -105,7 +79,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
schema: useGridFormSchema(),
|
schema: useGridFormSchema(),
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick, getAccountMail),
|
columns: useGridColumns(getAccountMail),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
|
|
@ -144,14 +118,48 @@ onMounted(async () => {
|
||||||
<SendModal />
|
<SendModal />
|
||||||
<Grid table-title="邮件模板列表">
|
<Grid table-title="邮件模板列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['system:mail-template:create']"
|
label: $t('ui.actionTitle.create', ['邮件模板']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['邮件模板']) }}
|
auth: ['system:mail-template:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:mail-template:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '测试',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:mail-template:send-mail'],
|
||||||
|
onClick: handleSend.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['system:mail-template:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 动态构建表单 schema */
|
/** 动态构建表单 schema */
|
||||||
const buildFormSchema = () => {
|
function buildFormSchema() {
|
||||||
const schema = useSendMailFormSchema();
|
const schema = useSendMailFormSchema();
|
||||||
if (formData.value?.params) {
|
if (formData.value?.params) {
|
||||||
formData.value.params?.forEach((param: string) => {
|
formData.value.params?.forEach((param: string) => {
|
||||||
|
|
@ -99,7 +99,7 @@ const buildFormSchema = () => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return schema;
|
return schema;
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
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 { SystemMenuApi } from '#/api/system/menu';
|
import type { SystemMenuApi } from '#/api/system/menu';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
import { handleTree, isHttpUrl } from '@vben/utils';
|
import { handleTree, isHttpUrl } from '@vben/utils';
|
||||||
|
|
||||||
|
|
@ -21,8 +20,6 @@ import {
|
||||||
SystemMenuTypeEnum,
|
SystemMenuTypeEnum,
|
||||||
} from '#/utils';
|
} from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -269,9 +266,7 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns(
|
export function useGridColumns(): VxeTableGridOptions<SystemMenuApi.Menu>['columns'] {
|
||||||
onActionClick: OnActionClickFn<SystemMenuApi.Menu>,
|
|
||||||
): VxeTableGridOptions<SystemMenuApi.Menu>['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'name',
|
field: 'name',
|
||||||
|
|
@ -321,34 +316,10 @@ export function useGridColumns(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 200,
|
width: 220,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
align: 'center',
|
slots: { default: 'actions' },
|
||||||
showOverflow: false,
|
|
||||||
cellRender: {
|
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'append',
|
|
||||||
text: '新增下级',
|
|
||||||
show: hasAccessByCodes(['system:menu:create']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['system:menu:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['system:menu:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,15 @@
|
||||||
<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 { SystemMenuApi } from '#/api/system/menu';
|
import type { SystemMenuApi } from '#/api/system/menu';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { IconifyIcon, Plus } from '@vben/icons';
|
import { IconifyIcon } 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 { deleteMenu, getMenuList } from '#/api/system/menu';
|
import { deleteMenu, getMenuList } from '#/api/system/menu';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
import { DocAlert } from '#/components/doc-alert';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
@ -32,54 +29,38 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建菜单 */
|
/** 创建菜单 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData({}).open();
|
formModalApi.setData({}).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 添加下级菜单 */
|
/** 添加下级菜单 */
|
||||||
function onAppend(row: SystemMenuApi.Menu) {
|
function handleAppend(row: SystemMenuApi.Menu) {
|
||||||
formModalApi.setData({ pid: row.id }).open();
|
formModalApi.setData({ pid: row.id }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑菜单 */
|
/** 编辑菜单 */
|
||||||
function onEdit(row: SystemMenuApi.Menu) {
|
function handleEdit(row: SystemMenuApi.Menu) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除菜单 */
|
/** 删除菜单 */
|
||||||
async function onDelete(row: SystemMenuApi.Menu) {
|
async function handleDelete(row: SystemMenuApi.Menu) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteMenu(row.id as number);
|
await deleteMenu(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({ code, row }: OnActionClickParams<SystemMenuApi.Menu>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'append': {
|
|
||||||
onAppend(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 切换树形展开/收缩状态 */
|
/** 切换树形展开/收缩状态 */
|
||||||
const isExpanded = ref(false);
|
const isExpanded = ref(false);
|
||||||
function toggleExpand() {
|
function toggleExpand() {
|
||||||
|
|
@ -89,7 +70,7 @@ function toggleExpand() {
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick),
|
columns: useGridColumns(),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
pagerConfig: {
|
pagerConfig: {
|
||||||
|
|
@ -131,17 +112,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<FormModal @success="onRefresh" />
|
<FormModal @success="onRefresh" />
|
||||||
<Grid>
|
<Grid>
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['system:menu:create']"
|
label: $t('ui.actionTitle.create', ['菜单']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['菜单']) }}
|
auth: ['system:menu:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
<Button class="ml-2" @click="toggleExpand">
|
},
|
||||||
{{ isExpanded ? '收缩' : '展开' }}
|
{
|
||||||
</Button>
|
label: isExpanded ? '收缩' : '展开',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: toggleExpand,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #name="{ row }">
|
<template #name="{ row }">
|
||||||
<div class="flex w-full items-center gap-1">
|
<div class="flex w-full items-center gap-1">
|
||||||
|
|
@ -161,6 +147,37 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<div class="items-center justify-end"></div>
|
<div class="items-center justify-end"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '新增下级',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['system:menu:create'],
|
||||||
|
onClick: handleAppend.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:menu:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['system:menu:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +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 { SystemNoticeApi } from '#/api/system/notice';
|
|
||||||
|
|
||||||
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 [
|
||||||
|
|
@ -91,9 +86,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemNoticeApi.Notice>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -130,34 +123,10 @@ export function useGridColumns<T = SystemNoticeApi.Notice>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 180,
|
width: 220,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'title',
|
|
||||||
nameTitle: '公告',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['system:notice:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'push',
|
|
||||||
text: '推送',
|
|
||||||
show: hasAccessByCodes(['system:notice:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['system:notice:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
<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 { SystemNoticeApi } from '#/api/system/notice';
|
import type { SystemNoticeApi } from '#/api/system/notice';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { 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 { deleteNotice, getNoticePage, pushNotice } from '#/api/system/notice';
|
import { deleteNotice, getNoticePage, pushNotice } from '#/api/system/notice';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
|
@ -28,73 +24,56 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建公告 */
|
/** 创建公告 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑公告 */
|
/** 编辑公告 */
|
||||||
function onEdit(row: SystemNoticeApi.Notice) {
|
function handleEdit(row: SystemNoticeApi.Notice) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除公告 */
|
/** 删除公告 */
|
||||||
async function onDelete(row: SystemNoticeApi.Notice) {
|
async function handleDelete(row: SystemNoticeApi.Notice) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.title]),
|
content: $t('ui.actionMessage.deleting', [row.title]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteNotice(row.id as number);
|
await deleteNotice(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.title]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.title]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} catch {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 推送公告 */
|
/** 推送公告 */
|
||||||
async function onPush(row: SystemNoticeApi.Notice) {
|
async function handlePush(row: SystemNoticeApi.Notice) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.processing', ['推送']),
|
content: $t('ui.actionMessage.processing', ['推送']),
|
||||||
duration: 0,
|
|
||||||
key: 'action_process_msg',
|
key: 'action_process_msg',
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await pushNotice(row.id as number);
|
await pushNotice(row.id as number);
|
||||||
message.success($t('ui.actionMessage.operationSuccess'));
|
message.success({
|
||||||
} catch {
|
content: $t('ui.actionMessage.operationSuccess'),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemNoticeApi.Notice>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'push': {
|
|
||||||
onPush(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -124,14 +103,48 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<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="['system:notice:create']"
|
label: $t('ui.actionTitle.create', ['公告']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['公告']) }}
|
auth: ['system:notice:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:notice:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '推送',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['system:notice:update'],
|
||||||
|
onClick: handlePush.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['system:notice:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
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 { SystemNotifyMessageApi } from '#/api/system/notify/message';
|
|
||||||
|
|
||||||
import { useAccess } from '@vben/access';
|
|
||||||
|
|
||||||
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 列表的搜索表单 */
|
/** 列表的搜索表单 */
|
||||||
export function useGridFormSchema(): VbenFormSchema[] {
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -65,9 +60,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -146,26 +139,10 @@ export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 180,
|
width: 80,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'id',
|
|
||||||
nameTitle: '站内信',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: '详情',
|
|
||||||
show: hasAccessByCodes(['system:notify-message:query']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
<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 { SystemNotifyMessageApi } from '#/api/system/notify/message';
|
import type { SystemNotifyMessageApi } from '#/api/system/notify/message';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { getNotifyMessagePage } from '#/api/system/notify/message';
|
import { getNotifyMessagePage } from '#/api/system/notify/message';
|
||||||
import { DocAlert } from '#/components/doc-alert';
|
import { DocAlert } from '#/components/doc-alert';
|
||||||
|
|
||||||
|
|
@ -25,29 +22,16 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看站内信详情 */
|
/** 查看站内信详情 */
|
||||||
function onDetail(row: SystemNotifyMessageApi.NotifyMessage) {
|
function handleDetail(row: SystemNotifyMessageApi.NotifyMessage) {
|
||||||
detailModalApi.setData(row).open();
|
detailModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemNotifyMessageApi.NotifyMessage>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -79,6 +63,20 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<DetailModal @success="onRefresh" />
|
<DetailModal @success="onRefresh" />
|
||||||
<Grid table-title="站内信列表" />
|
<Grid table-title="站内信列表">
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['system:notify-message:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
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 { SystemNotifyMessageApi } from '#/api/system/notify/message';
|
|
||||||
import type { DescriptionItemSchema } from '#/components/description';
|
import type { DescriptionItemSchema } from '#/components/description';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
@ -36,9 +35,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: '',
|
title: '',
|
||||||
|
|
@ -86,31 +83,10 @@ export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 180,
|
width: 130,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'id',
|
|
||||||
nameTitle: '站内信',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'detail',
|
|
||||||
text: '查看',
|
|
||||||
show: (row: any) => row.readStatus,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'read',
|
|
||||||
text: '已读',
|
|
||||||
show: (row: any) => !row.readStatus,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
<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 { SystemNotifyMessageApi } from '#/api/system/notify/message';
|
import type { SystemNotifyMessageApi } from '#/api/system/notify/message';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { MdiCheckboxMarkedCircleOutline } 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 {
|
import {
|
||||||
getMyNotifyMessagePage,
|
getMyNotifyMessagePage,
|
||||||
updateAllNotifyMessageRead,
|
updateAllNotifyMessageRead,
|
||||||
|
|
@ -32,12 +28,12 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查看站内信详情 */
|
/** 查看站内信详情 */
|
||||||
function onDetail(row: SystemNotifyMessageApi.NotifyMessage) {
|
function handleDetail(row: SystemNotifyMessageApi.NotifyMessage) {
|
||||||
detailModalApi.setData(row).open();
|
detailModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 标记一条站内信已读 */
|
/** 标记一条站内信已读 */
|
||||||
async function onRead(row: SystemNotifyMessageApi.NotifyMessage) {
|
async function handleRead(row: SystemNotifyMessageApi.NotifyMessage) {
|
||||||
message.loading({
|
message.loading({
|
||||||
content: '正在标记已读...',
|
content: '正在标记已读...',
|
||||||
duration: 0,
|
duration: 0,
|
||||||
|
|
@ -46,15 +42,18 @@ async function onRead(row: SystemNotifyMessageApi.NotifyMessage) {
|
||||||
// 执行标记已读操作
|
// 执行标记已读操作
|
||||||
await updateNotifyMessageRead([row.id]);
|
await updateNotifyMessageRead([row.id]);
|
||||||
// 提示成功
|
// 提示成功
|
||||||
message.success('标记已读成功');
|
message.success({
|
||||||
|
content: '标记已读成功',
|
||||||
|
key: 'action_process_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
|
|
||||||
// 打开详情
|
// 打开详情
|
||||||
onDetail(row);
|
handleDetail(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 标记选中的站内信为已读 */
|
/** 标记选中的站内信为已读 */
|
||||||
async function onMarkRead() {
|
async function handleMarkRead() {
|
||||||
const rows = gridApi.grid.getCheckboxRecords();
|
const rows = gridApi.grid.getCheckboxRecords();
|
||||||
if (!rows || rows.length === 0) {
|
if (!rows || rows.length === 0) {
|
||||||
message.warning('请选择需要标记的站内信');
|
message.warning('请选择需要标记的站内信');
|
||||||
|
|
@ -62,48 +61,43 @@ async function onMarkRead() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ids = rows.map((row: SystemNotifyMessageApi.NotifyMessage) => row.id);
|
const ids = rows.map((row: SystemNotifyMessageApi.NotifyMessage) => row.id);
|
||||||
message.loading({
|
const hideLoading = message.loading({
|
||||||
content: '正在标记已读...',
|
content: '正在标记已读...',
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
// 执行标记已读操作
|
// 执行标记已读操作
|
||||||
await updateNotifyMessageRead(ids);
|
await updateNotifyMessageRead(ids);
|
||||||
// 提示成功
|
// 提示成功
|
||||||
message.success('标记已读成功');
|
message.success({
|
||||||
|
content: '标记已读成功',
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
await gridApi.grid.setAllCheckboxRow(false);
|
await gridApi.grid.setAllCheckboxRow(false);
|
||||||
onRefresh();
|
onRefresh();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 标记所有站内信为已读 */
|
/** 标记所有站内信为已读 */
|
||||||
async function onMarkAllRead() {
|
async function handleMarkAllRead() {
|
||||||
message.loading({
|
const hideLoading = message.loading({
|
||||||
content: '正在标记全部已读...',
|
content: '正在标记全部已读...',
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
|
try {
|
||||||
// 执行标记已读操作
|
// 执行标记已读操作
|
||||||
await updateAllNotifyMessageRead();
|
await updateAllNotifyMessageRead();
|
||||||
// 提示成功
|
// 提示成功
|
||||||
message.success('全部标记已读成功');
|
message.success({
|
||||||
|
content: '全部标记已读成功',
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
await gridApi.grid.setAllCheckboxRow(false);
|
await gridApi.grid.setAllCheckboxRow(false);
|
||||||
onRefresh();
|
onRefresh();
|
||||||
}
|
} finally {
|
||||||
|
hideLoading();
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemNotifyMessageApi.NotifyMessage>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'detail': {
|
|
||||||
onDetail(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'read': {
|
|
||||||
onRead(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +106,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
schema: useGridFormSchema(),
|
schema: useGridFormSchema(),
|
||||||
},
|
},
|
||||||
gridOptions: {
|
gridOptions: {
|
||||||
columns: useGridColumns(onActionClick),
|
columns: useGridColumns(),
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
keepSource: true,
|
keepSource: true,
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
|
|
@ -150,14 +144,42 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<DetailModal @success="onRefresh" />
|
<DetailModal @success="onRefresh" />
|
||||||
<Grid table-title="我的站内信">
|
<Grid table-title="我的站内信">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button type="primary" @click="onMarkRead">
|
<TableAction
|
||||||
<MdiCheckboxMarkedCircleOutline />
|
:actions="[
|
||||||
标记已读
|
{
|
||||||
</Button>
|
label: '标记已读',
|
||||||
<Button type="primary" class="ml-2" @click="onMarkAllRead">
|
type: 'primary',
|
||||||
<MdiCheckboxMarkedCircleOutline />
|
icon: 'mdi:checkbox-marked-circle-outline',
|
||||||
全部已读
|
onClick: handleMarkRead,
|
||||||
</Button>
|
},
|
||||||
|
{
|
||||||
|
label: '全部已读',
|
||||||
|
type: 'primary',
|
||||||
|
icon: 'mdi:checkbox-marked-circle-outline',
|
||||||
|
onClick: handleMarkAllRead,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '查看',
|
||||||
|
type: 'link',
|
||||||
|
ifShow: row.readStatus,
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '已读',
|
||||||
|
type: 'link',
|
||||||
|
ifShow: !row.readStatus,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
onClick: handleRead.bind(null, row),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
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 { SystemNotifyTemplateApi } from '#/api/system/notify/template';
|
|
||||||
|
|
||||||
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';
|
||||||
|
|
@ -14,8 +11,6 @@ import {
|
||||||
UserTypeEnum,
|
UserTypeEnum,
|
||||||
} from '#/utils';
|
} from '#/utils';
|
||||||
|
|
||||||
const { hasAccessByCodes } = useAccess();
|
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|
@ -229,9 +224,7 @@ export function useSendNotifyFormSchema(): VbenFormSchema[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的字段 */
|
/** 列表的字段 */
|
||||||
export function useGridColumns<T = SystemNotifyTemplateApi.NotifyTemplate>(
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
onActionClick: OnActionClickFn<T>,
|
|
||||||
): VxeTableGridOptions['columns'] {
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
|
|
@ -288,34 +281,10 @@ export function useGridColumns<T = SystemNotifyTemplateApi.NotifyTemplate>(
|
||||||
formatter: 'formatDateTime',
|
formatter: 'formatDateTime',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'operation',
|
|
||||||
title: '操作',
|
title: '操作',
|
||||||
minWidth: 180,
|
width: 220,
|
||||||
align: 'center',
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
cellRender: {
|
slots: { default: 'actions' },
|
||||||
attrs: {
|
|
||||||
nameField: 'name',
|
|
||||||
nameTitle: '站内信模板',
|
|
||||||
onClick: onActionClick,
|
|
||||||
},
|
|
||||||
name: 'CellOperation',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
code: 'edit',
|
|
||||||
show: hasAccessByCodes(['system:notify-template:update']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'send',
|
|
||||||
text: '测试',
|
|
||||||
show: hasAccessByCodes(['system:notify-template:send-notify']),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'delete',
|
|
||||||
show: hasAccessByCodes(['system:notify-template:delete']),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +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 { SystemNotifyTemplateApi } from '#/api/system/notify/template';
|
import type { SystemNotifyTemplateApi } from '#/api/system/notify/template';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
import { Download, Plus } from '@vben/icons';
|
|
||||||
import { downloadFileFromBlobPart } from '@vben/utils';
|
import { downloadFileFromBlobPart } from '@vben/utils';
|
||||||
|
|
||||||
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 {
|
import {
|
||||||
deleteNotifyTemplate,
|
deleteNotifyTemplate,
|
||||||
exportNotifyTemplate,
|
exportNotifyTemplate,
|
||||||
|
|
@ -40,69 +36,50 @@ function onRefresh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出表格 */
|
/** 导出表格 */
|
||||||
async function onExport() {
|
async function handleExport() {
|
||||||
const data = await exportNotifyTemplate(await gridApi.formApi.getValues());
|
const data = await exportNotifyTemplate(await gridApi.formApi.getValues());
|
||||||
downloadFileFromBlobPart({ fileName: '站内信模板.xls', source: data });
|
downloadFileFromBlobPart({ fileName: '站内信模板.xls', source: data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建站内信模板 */
|
/** 创建站内信模板 */
|
||||||
function onCreate() {
|
function handleCreate() {
|
||||||
formModalApi.setData(null).open();
|
formModalApi.setData(null).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 编辑站内信模板 */
|
/** 编辑站内信模板 */
|
||||||
function onEdit(row: SystemNotifyTemplateApi.NotifyTemplate) {
|
function handleEdit(row: SystemNotifyTemplateApi.NotifyTemplate) {
|
||||||
formModalApi.setData(row).open();
|
formModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 发送测试站内信 */
|
/** 发送测试站内信 */
|
||||||
function onSend(row: SystemNotifyTemplateApi.NotifyTemplate) {
|
function handleSend(row: SystemNotifyTemplateApi.NotifyTemplate) {
|
||||||
sendModalApi.setData(row).open();
|
sendModalApi.setData(row).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 删除站内信模板 */
|
/** 删除站内信模板 */
|
||||||
async function onDelete(row: SystemNotifyTemplateApi.NotifyTemplate) {
|
async function handleDelete(row: SystemNotifyTemplateApi.NotifyTemplate) {
|
||||||
const hideLoading = message.loading({
|
const hideLoading = message.loading({
|
||||||
content: $t('ui.actionMessage.deleting', [row.name]),
|
content: $t('ui.actionMessage.deleting', [row.name]),
|
||||||
duration: 0,
|
key: 'action_key_msg',
|
||||||
key: 'action_process_msg',
|
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await deleteNotifyTemplate(row.id as number);
|
await deleteNotifyTemplate(row.id as number);
|
||||||
message.success($t('ui.actionMessage.deleteSuccess', [row.name]));
|
message.success({
|
||||||
|
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
|
||||||
|
key: 'action_key_msg',
|
||||||
|
});
|
||||||
onRefresh();
|
onRefresh();
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格操作按钮的回调函数 */
|
|
||||||
function onActionClick({
|
|
||||||
code,
|
|
||||||
row,
|
|
||||||
}: OnActionClickParams<SystemNotifyTemplateApi.NotifyTemplate>) {
|
|
||||||
switch (code) {
|
|
||||||
case 'delete': {
|
|
||||||
onDelete(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'edit': {
|
|
||||||
onEdit(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'send': {
|
|
||||||
onSend(row);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -137,23 +114,55 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
<SendModal />
|
<SendModal />
|
||||||
<Grid table-title="站内信模板列表">
|
<Grid table-title="站内信模板列表">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button
|
<TableAction
|
||||||
type="primary"
|
:actions="[
|
||||||
@click="onCreate"
|
{
|
||||||
v-access:code="['system:notify-template:create']"
|
label: $t('ui.actionTitle.create', ['短信渠道']),
|
||||||
>
|
type: 'primary',
|
||||||
<Plus class="size-5" />
|
icon: ACTION_ICON.ADD,
|
||||||
{{ $t('ui.actionTitle.create', ['站内信模板']) }}
|
auth: ['system:notify-template:create'],
|
||||||
</Button>
|
onClick: handleCreate,
|
||||||
<Button
|
},
|
||||||
type="primary"
|
{
|
||||||
class="ml-2"
|
label: $t('ui.actionTitle.export'),
|
||||||
@click="onExport"
|
type: 'primary',
|
||||||
v-access:code="['system:notify-template:export']"
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
>
|
auth: ['system:notify-template:export'],
|
||||||
<Download class="size-5" />
|
onClick: handleExport,
|
||||||
{{ $t('ui.actionTitle.export') }}
|
},
|
||||||
</Button>
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['system:notify-template:update'],
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '测试',
|
||||||
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['system:notify-template:send-notify'],
|
||||||
|
onClick: handleSend.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['system:notify-template:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue