1. 管理员管理模块拆分

2. 图片上传自动压缩(大于850kb)
3. 省市区选择组件重构,支持搜索
This commit is contained in:
李琦
2026-05-30 13:52:59 +08:00
parent 402da17e3d
commit 75d1b4db42
20 changed files with 475 additions and 620 deletions

View File

@@ -28,8 +28,8 @@ export const gridOptions: VxeGridProps<RowType> = {
columns: [
{ type: 'checkbox', width: 60 },
{ field: 'id', align: 'left', title: 'ID', width: 100 },
{ field: 'drug_name', align: 'left', title: '药品名称' },
{ field: 'pinyin_simple', title: '拼音' },
{ field: 'drug_name', align: 'left', title: '药品名称', width: 120 },
{ field: 'pinyin_simple', title: '拼音', width: 120 },
{
field: 'zone_name',
title: '分区',
@@ -42,7 +42,7 @@ export const gridOptions: VxeGridProps<RowType> = {
width: 120,
slots: { default: 'category' },
},
{ field: 'supplier.name', title: '供应商', slots: { default: 'supplier' } },
{ field: 'supplier.name', title: '供应商', slots: { default: 'supplier' },width: 130 },
{
field: 'image',
align: 'left',
@@ -57,8 +57,8 @@ export const gridOptions: VxeGridProps<RowType> = {
slots: { default: 'instruction' },
width: 130,
},
{ field: 'function', title: '主要功能' },
{ field: 'specification', title: '规格' },
{ field: 'function', title: '主要功能', width: 240 },
{ field: 'specification', title: '规格', width: 130 },
{
field: 'is_otc',
title: '处方药',
@@ -66,14 +66,14 @@ export const gridOptions: VxeGridProps<RowType> = {
slots: { default: 'is_otc' },
},
{ field: 'status', title: '状态', slots: { default: 'status' } },
{ field: 'created_at', title: '发布时间' },
{ field: 'created_at', title: '发布时间', width: 240 },
{
field: 'min_adjust_price',
title: '最低调整金额',
width: 130,
slots: { default: 'min_adjust_price' },
},
{ type: 'html', title: '操作', width: 280, slots: { default: 'action' } },
{ type: 'html', title: '操作', fixed: 'right', width: 280, slots: { default: 'action' } },
],
keepSource: true,
pagerConfig: {},

View File

@@ -46,8 +46,8 @@ export async function getWarehouseDrugManagementInfo(id: number) {
/**
* 导出仓库药品药品
*/
export async function exportWarehouseDrugManagementApi() {
return requestClient.download(`${prefix}export`);
export async function exportWarehouseDrugManagementApi(params?: { type?: number }) {
return requestClient.download(`${prefix}export`, { params });
}
/**
* 导出仓库药品药品 - 模板

View File

@@ -1,11 +1,6 @@
import type { VbenFormProps } from '#/adapter/form';
import { getWarehouseProductTypeOptions } from '../api';
// import dayjs from 'dayjs';
export const formOptions: VbenFormProps = {
// 默认展开
collapsed: false,
schema: [
{
@@ -17,41 +12,11 @@ export const formOptions: VbenFormProps = {
fieldName: 'name',
label: '药名称',
},
{
component: 'ApiSelect',
componentProps: {
allowClear: true,
api: getWarehouseProductTypeOptions,
placeholder: '请选择类型',
afterFetch: (data: { label: string; value: number }[]) => {
if (!Array.isArray(data)) return [];
return data.map((item) => ({
label: item.label,
value: item.value,
}));
},
},
defaultValue: 1,
fieldName: 'type',
label: '类型',
},
// {
// component: 'RangePicker',
// componentProps: {
// format: 'YYYY-MM-DD', // 确保格式与你需要的一致
// },
// // defaultValue: [dayjs().startOf('month'), dayjs()],
// fieldName: 'search_time',
// label: '时间范围',
// },
],
// 控制表单是否显示折叠按钮
showCollapseButton: true,
submitButtonOptions: {
content: '查询',
},
// 是否在字段值改变时提交表单
submitOnChange: true,
// 按下回车时是否提交表单
submitOnEnter: false,
};

View File

@@ -1,6 +1,6 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import {getWarehouseDrugManagementList} from '../api';
import { getWarehouseDrugManagementList } from '../api';
interface RowType {
id: string;
@@ -10,70 +10,65 @@ interface RowType {
created_at: string;
}
export const gridOptions: VxeGridProps<RowType> = {
checkboxConfig: {
highlight: true,
labelField: '',
},
columnConfig: {
useKey: true,
},
rowConfig: {
useKey: true,
},
columns: [
{ type: 'checkbox', width: 60 },
{ field: 'id', align: 'left', title: 'ID', width: 100 },
{ field: 'drug.drug_name', align: 'left', title: '药品名称' },
{ field: 'drug.pinyin_simple', title: '拼音' },
{
field: 'image',
align: 'left',
title: '产品图片',
slots: { default: 'image' },
width: 130,
export function createGridOptions(productType: number): VxeGridProps<RowType> {
return {
checkboxConfig: {
highlight: true,
labelField: '',
},
{ field: 'market_price', title: '供货价' },
{ field: 'price', title: '建议售价' },
{ field: 'status', title: '状态', slots: { default: 'status' } },
{ field: 'created_at', title: '创建时间' },
{ type: 'html', title: '操作', slots: { default: 'action' } },
],
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
// 请求后端接口方法
query: async ({ page }, formValues) => {
return await getWarehouseDrugManagementList({
page: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
columnConfig: {
useKey: true,
},
rowConfig: {
useKey: true,
},
columns: [
{ type: 'checkbox', width: 60 },
{ field: 'id', align: 'left', title: 'ID', width: 100 },
{ field: 'drug.drug_name', align: 'left', title: '药品名称' },
{ field: 'drug.pinyin_simple', title: '拼音' },
{
field: 'image',
align: 'left',
title: '产品图片',
slots: { default: 'image' },
width: 130,
},
{ field: 'market_price', title: '供货价' },
{ field: 'price', title: '建议售价' },
{ field: 'status', title: '状态', slots: { default: 'status' } },
{ field: 'created_at', title: '创建时间' },
{ type: 'html', title: '操作', slots: { default: 'action' } },
],
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await getWarehouseDrugManagementList({
page: page.currentPage,
pageSize: page.pageSize,
type: productType,
...formValues,
});
},
},
},
},
// exportConfig: {
// api: passApplicationApi,
// },
height: 'auto',
border: false,
toolbarConfig: {
// 是否显示搜索表单控制按钮
// @ts-ignore 正式环境时有完整的类型声明
search: true,
refresh: true, // 刷新
print: false, // 打印
export: false, // 导出
// custom: true, // 自定义列
zoom: true, // 最大化最小化
slots: {
buttons: 'toolbar-buttons',
height: 'auto',
border: false,
toolbarConfig: {
search: true,
refresh: true,
print: false,
export: false,
zoom: true,
slots: {
buttons: 'toolbar-buttons',
},
custom: {
icon: 'vxe-icon-menu',
},
},
custom: {
// 自定义列-图标
icon: 'vxe-icon-menu',
},
},
showOverflow: false,
};
showOverflow: false,
};
}

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { VxeGridListeners } from '#/adapter/vxe-table';
import { ref } from 'vue';
import { computed, ref } from 'vue';
import { Page, useVbenModal } from '@vben/common-ui';
@@ -11,6 +11,7 @@ import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction } from '#/components/table-action';
import { downloadByData } from '#/util/tool';
import { useWarehouseDrugTypeRoute } from '../shared/useWarehouseDrugTypeRoute';
import {
deleteWarehouseDrugManagement,
exportWarehouseDrugManagementApi,
@@ -19,7 +20,11 @@ import {
import FormModalDemo from './components/modal.vue';
import ExcelUpload from './components/ExcelUpload.vue';
import { formOptions } from './config/search';
import { gridOptions } from './config/table';
import { createGridOptions } from './config/table';
const { productType, typeLabel } = useWarehouseDrugTypeRoute(
'/warehouse-drug-management/type/1',
);
const hasTopTableDropDownActions = ref(false);
@@ -36,6 +41,8 @@ const gridEvents: VxeGridListeners<any> = {
},
};
const gridOptions = computed(() => createGridOptions(productType.value));
const [Grid, gridApi] = useVbenVxeGrid({
formOptions,
gridOptions,
@@ -67,7 +74,7 @@ const showModal = (data = {}, isUpdate = false) => {
values: data,
update: isUpdate,
gridApi,
listDrugType: gridApi.formApi.latestSubmissionValues?.type,
listDrugType: productType.value,
});
formModalApi.open();
};
@@ -88,21 +95,17 @@ const deleteApi = (row: any) => {
* 导出
*/
const passApplication = () => {
// 新标签跳转到 exportWarehouseDrugManagementApi
exportWarehouseDrugManagementApi().then((res) => {
// 创建新的URL表示指定的File对象或者Blob对象。
exportWarehouseDrugManagementApi({ type: productType.value }).then((res) => {
downloadByData(res.data, '萧康云医-仓库商品导出.xlsx');
message.success('导出成功!');
});
};
const openExcelUploadModal = (type = 1) => {
const uploadType = gridApi.formApi.latestSubmissionValues.type;
ExcelUploadModalApi.setData({
gridApi,
type,
uploadType,
uploadType: productType.value,
passApplication,
});
ExcelUploadModalApi.open();
@@ -117,10 +120,10 @@ const updateStatus = (id: number) => {
</script>
<template>
<Page auto-content-height title="西(中成)药管理">
<Page auto-content-height :title="typeLabel || '总仓库管理'">
<ExcelUploadModal />
<FormModal />
<Grid>
<Grid v-if="productType">
<template #toolbar-buttons>
<TableAction
:actions="[

View File

@@ -0,0 +1,61 @@
import { computed, onMounted, ref, watch } from 'vue';
import type { RouteLocationNormalizedLoaded } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
import { getWarehouseProductTypeOptions } from '../admin/api';
const VALID_TYPES = [1, 2, 3, 5, 6, 7];
function resolveProductType(route: RouteLocationNormalizedLoaded): number {
const rawParam = route.params.type;
const fromParam = Number(Array.isArray(rawParam) ? rawParam[0] : rawParam);
if (VALID_TYPES.includes(fromParam)) {
return fromParam;
}
const match = route.path.match(/\/type\/(\d+)(?:\/|$)/);
const fromPath = Number(match?.[1]);
return VALID_TYPES.includes(fromPath) ? fromPath : 0;
}
async function loadTypeLabel(productType: number, typeLabel: { value: string }) {
try {
const options = await getWarehouseProductTypeOptions();
const matched = options?.find((item) => item.value === productType);
typeLabel.value = matched?.label ?? `类型${productType}`;
} catch {
typeLabel.value = `类型${productType}`;
}
}
/**
* 从路由 /.../type/:type 或静态 path /.../type/1 锁定仓库商品类型
*/
export function useWarehouseDrugTypeRoute(fallbackRedirect: string) {
const route = useRoute();
const router = useRouter();
const typeLabel = ref('');
const productType = computed(() => resolveProductType(route));
onMounted(async () => {
if (!productType.value) {
await router.replace(fallbackRedirect);
return;
}
await loadTypeLabel(productType.value, typeLabel);
});
watch(productType, async (value) => {
if (value) {
await loadTypeLabel(value, typeLabel);
}
});
return {
productType,
typeLabel,
};
}
export { VALID_TYPES };

View File

@@ -52,8 +52,8 @@ export async function updateWarehouseDrugManagementShopUpdateStatusApi(id: numbe
/**
* 导出仓库药品药品
*/
export async function exportWarehouseDrugManagementStoreApi() {
return requestClient.download(`${prefix}export`);
export async function exportWarehouseDrugManagementStoreApi(params?: { type?: number }) {
return requestClient.download(`${prefix}export`, { params });
}
/**
* 导出仓库药品药品 - 模板
@@ -106,16 +106,16 @@ export async function importUpdatePriceApi(data: Record<string, any>) {
* 同步总仓库api
* @param data
*/
export async function syncDrugApi(data: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug`, data);
export async function syncDrugApi(params?: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug`, { params });
}
/**
* 同步总仓库价格api
* @param data
* @param params
*/
export async function syncDrugPriceApi(data: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug-price`, data);
export async function syncDrugPriceApi(params?: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug-price`, { params });
}
/**

View File

@@ -1,11 +1,6 @@
import type { VbenFormProps } from '#/adapter/form';
import { getWarehouseProductTypeOptions } from '../api';
// import dayjs from 'dayjs';
export const formOptions: VbenFormProps = {
// 默认展开
collapsed: false,
schema: [
{
@@ -17,43 +12,11 @@ export const formOptions: VbenFormProps = {
fieldName: 'name',
label: '药名称',
},
{
component: 'ApiSelect',
componentProps: {
allowClear: true,
api: getWarehouseProductTypeOptions,
placeholder: '请选择类型',
afterFetch: (data: { label: string; value: number }[]) => {
if (!Array.isArray(data)) return [];
return data.map((item) => ({
label: item.label,
value: item.value,
}));
},
show: () => false,
},
disabled: true,
defaultValue: 2,
fieldName: 'type',
label: '类型',
},
// {
// component: 'RangePicker',
// componentProps: {
// format: 'YYYY-MM-DD', // 确保格式与你需要的一致
// },
// // defaultValue: [dayjs().startOf('month'), dayjs()],
// fieldName: 'search_time',
// label: '时间范围',
// },
],
// 控制表单是否显示折叠按钮
showCollapseButton: true,
submitButtonOptions: {
content: '查询',
},
// 是否在字段值改变时提交表单
submitOnChange: true,
// 按下回车时是否提交表单
submitOnEnter: false,
};

View File

@@ -1,6 +1,6 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import {getWarehouseDrugManagementStoreList} from '../api';
import { getWarehouseDrugManagementStoreList } from '../api';
interface RowType {
id: string;
@@ -10,75 +10,66 @@ interface RowType {
created_at: string;
}
export const gridOptions: VxeGridProps<RowType> = {
checkboxConfig: {
highlight: true,
labelField: '',
},
columnConfig: {
useKey: true,
},
rowConfig: {
useKey: true,
},
columns: [
{ type: 'checkbox', width: 60 },
{ field: 'id', align: 'left', title: 'ID', width: 100 },
{ field: 'drug.drug_name', align: 'left', title: '药品名称' },
{ field: 'drug.pinyin_simple', title: '拼音' },
{
field: 'image',
align: 'left',
title: '产品图片',
slots: { default: 'image' },
width: 130,
export function createGridOptions(productType: number): VxeGridProps<RowType> {
return {
checkboxConfig: {
highlight: true,
labelField: '',
},
// { field: 'drug.drug_store_drug.market_price', title: '供货价' },
{ field: 'buy_price', title: '供货价' },
{
field: 'drug.drug_store_drug.price',
title: '售价(不可修改)',
columnConfig: {
useKey: true,
},
// { field: 'price', title: '售价' },
// { field: 'status', title: '状态', slots: { default: 'status' } },
{ field: 'is_shop', title: '是否上架商城', slots: { default: 'is_shop' } },
// { type: 'html', align: 'right', title: '操作', slots: { default: 'action' }, width: 300, },
],
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
// 请求后端接口方法
query: async ({ page }, formValues) => {
return await getWarehouseDrugManagementStoreList({
page: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
rowConfig: {
useKey: true,
},
columns: [
{ type: 'checkbox', width: 60 },
{ field: 'id', align: 'left', title: 'ID', width: 100 },
{ field: 'drug.drug_name', align: 'left', title: '药品名称' },
{ field: 'drug.pinyin_simple', title: '拼音' },
{
field: 'image',
align: 'left',
title: '产品图片',
slots: { default: 'image' },
width: 130,
},
{ field: 'buy_price', title: '供货价' },
{
field: 'drug.drug_store_drug.price',
title: '售价(不可修改)',
},
{ field: 'is_shop', title: '是否上架商城', slots: { default: 'is_shop' } },
],
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await getWarehouseDrugManagementStoreList({
page: page.currentPage,
pageSize: page.pageSize,
type: productType,
...formValues,
});
},
},
},
},
// exportConfig: {
// api: passApplicationApi,
// },
height: 'auto',
border: false,
toolbarConfig: {
// 是否显示搜索表单控制按钮
// @ts-ignore 正式环境时有完整的类型声明
search: true,
refresh: true, // 刷新
print: false, // 打印
export: false, // 导出
// custom: true, // 自定义列
zoom: true, // 最大化最小化
slots: {
buttons: 'toolbar-buttons',
height: 'auto',
border: false,
toolbarConfig: {
search: true,
refresh: true,
print: false,
export: false,
zoom: true,
slots: {
buttons: 'toolbar-buttons',
},
custom: {
icon: 'vxe-icon-menu',
},
},
custom: {
// 自定义列-图标
icon: 'vxe-icon-menu',
},
},
showOverflow: false,
};
showOverflow: false,
};
}

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { VxeGridListeners } from '#/adapter/vxe-table';
import { ref } from 'vue';
import { computed, ref } from 'vue';
import { Page, useVbenModal } from '@vben/common-ui';
@@ -11,6 +11,7 @@ import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction } from '#/components/table-action';
import { downloadByData } from '#/util/tool';
import { useWarehouseDrugTypeRoute } from '../shared/useWarehouseDrugTypeRoute';
import {
checkSubscribeApi,
deleteWarehouseDrugManagementStore,
@@ -24,7 +25,11 @@ import {
import ExcelUpload from './components/ExcelUpload.vue';
import FormModalDemo from './components/modal.vue';
import { formOptions } from './config/search';
import { gridOptions } from './config/table';
import { createGridOptions } from './config/table';
const { productType, typeLabel } = useWarehouseDrugTypeRoute(
'/warehouse-drug-management-shop/type/2',
);
const hasTopTableDropDownActions = ref(false);
@@ -41,6 +46,8 @@ const gridEvents: VxeGridListeners<any> = {
},
};
const gridOptions = computed(() => createGridOptions(productType.value));
const [Grid, gridApi] = useVbenVxeGrid({
formOptions,
gridOptions,
@@ -99,7 +106,7 @@ const openExcelUploadModal = (type = 1) => {
};
const syncDrugs = () => {
syncDrugApi().then((res) => {
syncDrugApi({ type: productType.value }).then(() => {
message.success('同步成功!');
gridApi.query();
});
@@ -121,8 +128,7 @@ const updateWarehouseDrugManagementShopUpdateStatus = (id) => {
const syncDrugPrice = () => {
gridApi.setLoading(true);
syncDrugPriceApi().then((res) => {
console.log(res, '同步结果');
syncDrugPriceApi({ type: productType.value }).then(() => {
message.success('同步成功!');
gridApi.setLoading(false);
gridApi.query();
@@ -147,10 +153,10 @@ checkSubscribe();
</script>
<template>
<Page auto-content-height title="西(中成)药管理">
<Page auto-content-height :title="typeLabel || '商城仓库管理'">
<ExcelUploadModal />
<FormModal />
<Grid>
<Grid v-if="productType">
<template #toolbar-buttons>
<TableAction
:actions="[

View File

@@ -52,8 +52,8 @@ export async function updateWarehouseDrugManagementShopUpdateStatusApi(id: numbe
/**
* 导出仓库药品药品
*/
export async function exportWarehouseDrugManagementStoreApi() {
return requestClient.download(`${prefix}export`);
export async function exportWarehouseDrugManagementStoreApi(params?: { type?: number }) {
return requestClient.download(`${prefix}export`, { params });
}
/**
* 导出仓库药品药品 - 模板
@@ -106,16 +106,16 @@ export async function importUpdatePriceApi(data: Record<string, any>) {
* 同步总仓库api
* @param data
*/
export async function syncDrugApi(data: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug`, data);
export async function syncDrugApi(params?: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug`, { params });
}
/**
* 同步总仓库价格api
* @param data
* @param params
*/
export async function syncDrugPriceApi(data: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug-price`, data);
export async function syncDrugPriceApi(params?: Record<string, any>) {
return requestClient.get(`${prefix}sync-drug-price`, { params });
}
/**

View File

@@ -22,6 +22,7 @@ import {
const gridApi = ref();
const passApplication = ref();
const importType = ref(1);
const uploadProductType = ref(1);
const fileList = ref<UploadFile[]>([]);
const selectedFile = ref<File | null>(null); // 新增:存储选中的文件
const isFileSelected = ref(false); // 新增:标记是否有文件被选中
@@ -53,6 +54,7 @@ const [Modal, modalApi] = useVbenModal({
await submitApi({
file: selectedFile.value,
type: uploadProductType.value,
});
message.success('上传成功');
@@ -74,6 +76,7 @@ const [Modal, modalApi] = useVbenModal({
gridApi.value = isOpen ? modalApi.getData()?.gridApi : null;
passApplication.value = isOpen ? modalApi.getData()?.passApplication : null;
importType.value = isOpen ? modalApi.getData()?.type : 1;
uploadProductType.value = isOpen ? modalApi.getData()?.uploadType ?? 1 : 1;
fileList.value = [];
selectedFile.value = null; // 重置选中的文件
isFileSelected.value = false; // 重置文件选择状态

View File

@@ -1,11 +1,6 @@
import type { VbenFormProps } from '#/adapter/form';
import { getWarehouseProductTypeOptions } from '../api';
// import dayjs from 'dayjs';
export const formOptions: VbenFormProps = {
// 默认展开
collapsed: false,
schema: [
{
@@ -17,41 +12,11 @@ export const formOptions: VbenFormProps = {
fieldName: 'name',
label: '药名称',
},
{
component: 'ApiSelect',
componentProps: {
allowClear: true,
api: getWarehouseProductTypeOptions,
placeholder: '请选择类型',
afterFetch: (data: { label: string; value: number }[]) => {
if (!Array.isArray(data)) return [];
return data.map((item) => ({
label: item.label,
value: item.value,
}));
},
},
defaultValue: 1,
fieldName: 'type',
label: '类型',
},
// {
// component: 'RangePicker',
// componentProps: {
// format: 'YYYY-MM-DD', // 确保格式与你需要的一致
// },
// // defaultValue: [dayjs().startOf('month'), dayjs()],
// fieldName: 'search_time',
// label: '时间范围',
// },
],
// 控制表单是否显示折叠按钮
showCollapseButton: true,
submitButtonOptions: {
content: '查询',
},
// 是否在字段值改变时提交表单
submitOnChange: true,
// 按下回车时是否提交表单
submitOnEnter: false,
};

View File

@@ -1,6 +1,6 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import {getWarehouseDrugManagementStoreList} from '../api';
import { getWarehouseDrugManagementStoreList } from '../api';
interface RowType {
id: string;
@@ -10,72 +10,71 @@ interface RowType {
created_at: string;
}
export const gridOptions: VxeGridProps<RowType> = {
checkboxConfig: {
highlight: true,
labelField: '',
},
columnConfig: {
useKey: true,
},
rowConfig: {
useKey: true,
},
columns: [
{ type: 'checkbox', width: 60 },
{ field: 'id', align: 'left', title: 'ID', width: 100 },
{ field: 'drug.drug_name', align: 'left', title: '药品名称' },
{ field: 'drug.pinyin_simple', title: '拼音' },
{
field: 'image',
align: 'left',
title: '产品图片',
slots: { default: 'image' },
width: 130,
export function createGridOptions(productType: number): VxeGridProps<RowType> {
return {
checkboxConfig: {
highlight: true,
labelField: '',
},
// { field: 'drug.drug_store_drug.market_price', title: '供货价' },
{ field: 'buy_price', title: '供货价' },
{ field: 'drug.drug_store_drug.price', title: '建议售价' },
{ field: 'price', title: '售价' },
{ field: 'status', title: '状态', slots: { default: 'status' } },
// { field: 'is_shop', title: '是否上架商城', slots: { default: 'is_shop' } },
{ type: 'html', align: 'right', title: '操作', slots: { default: 'action' }, width: 300, },
],
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
// 请求后端接口方法
query: async ({ page }, formValues) => {
return await getWarehouseDrugManagementStoreList({
page: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
columnConfig: {
useKey: true,
},
rowConfig: {
useKey: true,
},
columns: [
{ type: 'checkbox', width: 60 },
{ field: 'id', align: 'left', title: 'ID', width: 100 },
{ field: 'drug.drug_name', align: 'left', title: '药品名称' },
{ field: 'drug.pinyin_simple', title: '拼音' },
{
field: 'image',
align: 'left',
title: '产品图片',
slots: { default: 'image' },
width: 130,
},
{ field: 'buy_price', title: '供货价' },
{ field: 'drug.drug_store_drug.price', title: '建议售价' },
{ field: 'price', title: '售价' },
{ field: 'status', title: '状态', slots: { default: 'status' } },
{
type: 'html',
align: 'right',
title: '操作',
slots: { default: 'action' },
width: 300,
},
],
keepSource: true,
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await getWarehouseDrugManagementStoreList({
page: page.currentPage,
pageSize: page.pageSize,
type: productType,
...formValues,
});
},
},
},
},
// exportConfig: {
// api: passApplicationApi,
// },
height: 'auto',
border: false,
toolbarConfig: {
// 是否显示搜索表单控制按钮
// @ts-ignore 正式环境时有完整的类型声明
search: true,
refresh: true, // 刷新
print: false, // 打印
export: false, // 导出
// custom: true, // 自定义列
zoom: true, // 最大化最小化
slots: {
buttons: 'toolbar-buttons',
height: 'auto',
border: false,
toolbarConfig: {
search: true,
refresh: true,
print: false,
export: false,
zoom: true,
slots: {
buttons: 'toolbar-buttons',
},
custom: {
icon: 'vxe-icon-menu',
},
},
custom: {
// 自定义列-图标
icon: 'vxe-icon-menu',
},
},
showOverflow: false,
};
showOverflow: false,
};
}

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { VxeGridListeners } from '#/adapter/vxe-table';
import { ref } from 'vue';
import { computed, ref } from 'vue';
import { Page, useVbenModal } from '@vben/common-ui';
@@ -11,6 +11,7 @@ import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { TableAction } from '#/components/table-action';
import { downloadByData } from '#/util/tool';
import { useWarehouseDrugTypeRoute } from '../shared/useWarehouseDrugTypeRoute';
import {
checkSubscribeApi,
deleteWarehouseDrugManagementStore,
@@ -24,7 +25,11 @@ import {
import ExcelUpload from './components/ExcelUpload.vue';
import FormModalDemo from './components/modal.vue';
import { formOptions } from './config/search';
import { gridOptions } from './config/table';
import { createGridOptions } from './config/table';
const { productType, typeLabel } = useWarehouseDrugTypeRoute(
'/warehouse-drug-management-store/type/1',
);
const hasTopTableDropDownActions = ref(false);
@@ -41,6 +46,8 @@ const gridEvents: VxeGridListeners<any> = {
},
};
const gridOptions = computed(() => createGridOptions(productType.value));
const [Grid, gridApi] = useVbenVxeGrid({
formOptions,
gridOptions,
@@ -81,9 +88,7 @@ const deleteApi = (row: any) => {
* 导出
*/
const passApplication = () => {
// 新标签跳转到 exportWarehouseDrugManagementStoreApi
exportWarehouseDrugManagementStoreApi().then((res) => {
// 创建新的URL表示指定的File对象或者Blob对象。
exportWarehouseDrugManagementStoreApi({ type: productType.value }).then((res) => {
downloadByData(res.data, '萧康云医-仓库商品导出.xlsx');
message.success('导出成功!');
});
@@ -93,13 +98,14 @@ const openExcelUploadModal = (type = 1) => {
ExcelUploadModalApi.setData({
gridApi,
type,
uploadType: productType.value,
passApplication,
});
ExcelUploadModalApi.open();
};
const syncDrugs = () => {
syncDrugApi().then((res) => {
syncDrugApi({ type: productType.value }).then(() => {
message.success('同步成功!');
gridApi.query();
});
@@ -121,8 +127,7 @@ const updateWarehouseDrugManagementShopUpdateStatus = (id) => {
const syncDrugPrice = () => {
gridApi.setLoading(true);
syncDrugPriceApi().then((res) => {
console.log(res, '同步结果');
syncDrugPriceApi({ type: productType.value }).then(() => {
message.success('同步成功!');
gridApi.setLoading(false);
gridApi.query();
@@ -147,10 +152,10 @@ checkSubscribe();
</script>
<template>
<Page auto-content-height title="西(中成)药管理">
<Page auto-content-height :title="typeLabel || '门店仓库管理'">
<ExcelUploadModal />
<FormModal />
<Grid>
<Grid v-if="productType">
<template #toolbar-buttons>
<TableAction
:actions="[
@@ -158,14 +163,12 @@ checkSubscribe();
label: '批量修改价格',
type: 'primary',
icon: 'ix:export-check',
// auth: ['超级西(中成)药', 'sys:user:save'],
onClick: openExcelUploadModal.bind(null, 2),
},
{
label: '更新总仓库商品(只更新未同步的商品)',
type: 'primary',
icon: 'material-symbols:sync-alt',
// auth: ['超级西(中成)药', 'sys:user:save'],
onClick: syncDrugs,
},
{

View File

@@ -28,6 +28,7 @@ import {
import FormModalDemo from './components/modal.vue';
// 导入绑定在线复诊配置弹窗使用store的组件
import BindConsultationModal from '#/views/system/store/components/BindConsultationModal.vue';
import DrugPriceModal from '#/views/system/store/components/DrugPriceModal.vue';
import StoreExternalFieldModal from '#/views/system/store/components/StoreExternalFieldModal.vue';
// 导入搜索表单配置
import { formOptions } from './config/search';
@@ -104,6 +105,17 @@ const [StoreExternalFieldModalComponent, storeExternalFieldModalApi] = useVbenMo
connectedComponent: StoreExternalFieldModal,
});
const [DrugPriceModalComponent, drugPriceModalApi] = useVbenModal({
connectedComponent: DrugPriceModal,
});
const showDrugPriceModal = (row: any) => {
drugPriceModalApi.setData({
store_id: row.id,
});
drugPriceModalApi.open();
};
const showStoreExternalFieldModal = (
row: any,
field: 'erp_id' | 'mes_id',
@@ -236,6 +248,7 @@ const batchSyncDrugPrice = () => {
<Page auto-content-height title="药店管理">
<FormModal />
<QrCodePreviewModal />
<DrugPriceModalComponent />
<BindConsultationModalComponent />
<StoreExternalFieldModalComponent />
<Grid>
@@ -427,6 +440,14 @@ const batchSyncDrugPrice = () => {
confirm: openQrCode.bind(null, row.id),
},
},
{
label: '修改药品价格',
type: 'link',
icon: 'ant-design:edit-outlined',
size: 'small',
ifShow: isPlatformAdmin,
onClick: showDrugPriceModal.bind(null, row),
},
]"
/>
</template>

View File

@@ -117,7 +117,7 @@ export async function updateStoreSubscribeStatus(data: { id: number }) {
/**
* 获取诊所药品列表(按类型)
* @param storeId 诊所ID
* @param type 品类型1=中药2=西药
* @param type 品类型1中药 2西药 3保健食品 5产品服务包 6非药品 7医疗器械
*/
export async function getStoreDrugsByTypeApi(storeId: number, type: number) {
return requestClient.get<any>(`${prefix}get-store-drugs-by-type`, {

View File

@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { computed, ref, watch } from 'vue';
import { computed, nextTick, ref, watch } from 'vue';
import { useVbenModal } from '@vben/common-ui';
@@ -9,18 +9,18 @@ import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
type DrugItem,
getChinaMedicineGridOptions,
getWesternMedicineGridOptions,
handleSaveRow,
type ProductTypeOption,
fetchProductTypeOptions,
getDrugPriceGridOptions,
handleBatchSave,
handleSaveRow,
TCM_PLACEHOLDER_IMAGE,
} from '../config/drug-price-table';
import { drugPriceFormOptions } from '../config/search';
const activeTab = ref<string>('1'); // 1=中药, 2=西药
const activeTab = ref<string>('');
const storeId = ref<number>(0);
const loading = ref(false);
const chinaGridApi = ref<any>(null);
const westernGridApi = ref<any>(null);
const productTypeOptions = ref<ProductTypeOption[]>([]);
const [Modal, modalApi] = useVbenModal({
fullscreenButton: false,
@@ -30,136 +30,89 @@ const [Modal, modalApi] = useVbenModal({
modalApi.close();
},
onConfirm: async () => {
// 批量保存保存当前激活tab的表格中所有修改的数据
if (activeTab.value === '1') {
await handleBatchSave(chinaGridApi.value, storeId.value);
} else {
await handleBatchSave(westernGridApi.value, storeId.value);
}
await handleBatchSave(drugGridApi, storeId.value);
},
onOpenChange(isOpen: boolean) {
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
const data = modalApi.getData<{ store_id: number }>();
if (data?.store_id) {
storeId.value = data.store_id;
// 使用proxyConfig自动加载数据不需要手动调用
}
productTypeOptions.value = await fetchProductTypeOptions();
activeTab.value = String(productTypeOptions.value[0]?.value ?? '1');
await nextTick();
drugGridApi?.reload?.();
} else {
// 重置数据
activeTab.value = '1';
activeTab.value = '';
storeId.value = 0;
productTypeOptions.value = [];
}
},
});
// 单行保存回调函数
const handleSaveChinaRow = async (row: DrugItem) => {
await handleSaveRow(row, storeId.value, chinaGridApi.value);
const handleSaveCurrentRow = async (row: DrugItem) => {
await handleSaveRow(row, storeId.value, drugGridApi);
};
const handleSaveWesternRow = async (row: DrugItem) => {
await handleSaveRow(row, storeId.value, westernGridApi.value);
};
const activeProductType = computed(() => Number(activeTab.value) || 1);
// 中药表格配置 - 使用computed包装响应式数据传入storeId
const chinaMedicineGridOptions = computed(() =>
getChinaMedicineGridOptions(storeId.value, handleSaveChinaRow),
const drugPriceGridOptions = computed(() =>
getDrugPriceGridOptions(
() => storeId.value,
() => activeProductType.value,
handleSaveCurrentRow,
),
);
// 西药表格配置 - 使用computed包装响应式数据传入storeId
const westernMedicineGridOptions = computed(() =>
getWesternMedicineGridOptions(storeId.value, handleSaveWesternRow),
);
const [ChinaGrid, chinaGridApiInstance] = useVbenVxeGrid({
const [DrugGrid, drugGridApi] = useVbenVxeGrid({
formOptions: drugPriceFormOptions,
gridOptions: chinaMedicineGridOptions,
gridOptions: drugPriceGridOptions,
});
const [WesternGrid, westernGridApiInstance] = useVbenVxeGrid({
formOptions: drugPriceFormOptions,
gridOptions: westernMedicineGridOptions,
watch(activeTab, async (tab, prev) => {
if (!storeId.value || !tab || !prev) {
return;
}
await nextTick();
drugGridApi?.reload?.();
});
chinaGridApi.value = chinaGridApiInstance;
westernGridApi.value = westernGridApiInstance;
// 批量保存保存当前tab的所有修改
const handleBatchSaveCurrent = async () => {
if (activeTab.value === '1') {
await handleBatchSave(chinaGridApi.value, storeId.value);
} else {
await handleBatchSave(westernGridApi.value, storeId.value);
}
await handleBatchSave(drugGridApi, storeId.value);
};
// 监听Tab切换刷新对应表格数据
watch(activeTab, () => {
// Tab切换时刷新对应表格的数据
if (activeTab.value === '1') {
chinaGridApi.value?.reload?.();
} else {
westernGridApi.value?.reload?.();
}
});
const rowImageSrc = (row: DrugItem) => {
return row.image || TCM_PLACEHOLDER_IMAGE;
};
</script>
<template>
<Modal
title="修改药品价格"
class="w-[80%]"
>
<Modal title="修改药品价格" class="w-[80%]">
<div>
<Tabs v-model:activeKey="activeTab">
<TabPane key="1" tab="中药">
<ChinaGrid>
<template #toolbar-buttons>
<Button type="primary" @click="handleBatchSaveCurrent">
批量保存
</Button>
</template>
<template #china-action="{ row }">
<Button
type="link"
size="small"
@click="handleSaveChinaRow(row)"
>
保存
</Button>
</template>
</ChinaGrid>
</TabPane>
<TabPane key="2" tab="西药">
<WesternGrid>
<template #toolbar-buttons>
<Button type="primary" @click="handleBatchSaveCurrent">
批量保存
</Button>
</template>
<template #western-image="{ row }">
<div class="div" style="width: 120px; height: 120px; overflow: scroll">
<Image
:src="
row.image ||
'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250510/cd470ebf97e31c4048ba502ba71b66a3.jpg'
"
height="30"
width="30"
/>
</div>
</template>
<template #western-action="{ row }">
<Button
type="link"
size="small"
@click="handleSaveWesternRow(row)"
>
保存
</Button>
</template>
</WesternGrid>
</TabPane>
<TabPane
v-for="option in productTypeOptions"
:key="String(option.value)"
:tab="option.label"
/>
</Tabs>
<DrugGrid v-if="activeTab">
<template #toolbar-buttons>
<Button type="primary" @click="handleBatchSaveCurrent">
批量保存
</Button>
</template>
<template #drug-image="{ row }">
<div class="div" style="width: 120px; height: 120px; overflow: scroll">
<Image :src="rowImageSrc(row)" height="30" width="30" />
</div>
</template>
<template #row-action="{ row }">
<Button type="link" size="small" @click="handleSaveCurrentRow(row)">
保存
</Button>
</template>
</DrugGrid>
</div>
</Modal>
</template>

View File

@@ -2,6 +2,8 @@ import type { VxeGridProps } from '#/adapter/vxe-table';
import { message } from 'ant-design-vue';
import { getWarehouseProductTypeOptions } from '#/views/business/warehouse-drug-management/admin/api';
import {
getStoreDrugsByTypeApi,
updateStoreDrugPricesApi,
@@ -16,11 +18,21 @@ export interface DrugItem {
buy_price: number;
}
export interface ProductTypeOption {
label: string;
value: number;
}
const TCM_PLACEHOLDER_IMAGE =
'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250510/cd470ebf97e31c4048ba502ba71b66a3.jpg';
export async function fetchProductTypeOptions(): Promise<ProductTypeOption[]> {
const data = await getWarehouseProductTypeOptions();
return Array.isArray(data) ? data : [];
}
/**
* 单行保存函数
* @param row 当前行数据
* @param storeId 诊所ID
* @param gridApi 表格API实例
*/
export const handleSaveRow = async (
row: DrugItem,
@@ -28,12 +40,11 @@ export const handleSaveRow = async (
gridApi: any,
) => {
if (!storeId) {
message.error('诊所ID不能为空');
message.error('门店ID不能为空');
return;
}
try {
// 获取当前行的最新数据(从表格中获取,包含编辑后的值)
const tableData = gridApi?.grid?.getTableData?.();
const fullData = tableData?.fullData || [];
const currentRow = fullData.find((item: DrugItem) => item.id === row.id);
@@ -43,7 +54,6 @@ export const handleSaveRow = async (
return;
}
// 构建提交数据(只提交当前行)
const drugs = [
{
id: currentRow.id,
@@ -52,7 +62,6 @@ export const handleSaveRow = async (
},
];
// 验证数据
for (const drug of drugs) {
if (drug.price < 0 || drug.buy_price < 0) {
message.error('价格不能为负数');
@@ -70,7 +79,6 @@ export const handleSaveRow = async (
});
message.success('保存成功');
// 刷新表格数据
gridApi?.reload?.();
} catch (error: any) {
message.error(error?.message || '保存失败');
@@ -79,24 +87,17 @@ export const handleSaveRow = async (
/**
* 批量保存函数(只保存修改的数据)
* @param gridApi 表格API实例
* @param storeId 诊所ID
*/
export const handleBatchSave = async (
gridApi: any,
storeId: number,
) => {
export const handleBatchSave = async (gridApi: any, storeId: number) => {
if (!storeId) {
message.error('诊所ID不能为空');
message.error('门店ID不能为空');
return;
}
try {
// 使用getRecordset获取修改的记录
const recordset = gridApi?.grid?.getRecordset?.();
const updateRecords = recordset?.updateRecords || [];
// 如果getRecordset没有返回修改记录尝试获取所有数据
if (updateRecords.length === 0) {
const tableData = gridApi?.grid?.getTableData?.();
const fullData = tableData?.fullData || [];
@@ -106,14 +107,12 @@ export const handleBatchSave = async (
return;
}
// 如果没有修改记录,提交所有数据
const drugs = fullData.map((row: DrugItem) => ({
id: row.id,
price: parseFloat(String(row.price)) || 0,
buy_price: parseFloat(String(row.buy_price)) || 0,
}));
// 验证数据
for (const drug of drugs) {
if (drug.price < 0 || drug.buy_price < 0) {
message.error('价格不能为负数');
@@ -135,17 +134,12 @@ export const handleBatchSave = async (
return;
}
// 构建提交数据(只提交修改过的数据)
const dataToSave = updateRecords;
// 构建提交数据
const drugs = dataToSave.map((row: DrugItem) => ({
const drugs = updateRecords.map((row: DrugItem) => ({
id: row.id,
price: parseFloat(String(row.price)) || 0,
buy_price: parseFloat(String(row.buy_price)) || 0,
}));
// 验证数据
for (const drug of drugs) {
if (drug.price < 0 || drug.buy_price < 0) {
message.error('价格不能为负数');
@@ -163,7 +157,6 @@ export const handleBatchSave = async (
});
message.success('保存成功');
// 刷新表格数据
gridApi?.reload?.();
} catch (error: any) {
message.error(error?.message || '保存失败');
@@ -171,103 +164,29 @@ export const handleBatchSave = async (
};
/**
* 获取中药表格配置
* @param storeId 诊所ID
* @param onSaveRow 单行保存回调函数
* @returns 表格配置对象
* 按 ProductTypeEnum 获取改价表格配置
*/
export const getChinaMedicineGridOptions = (
storeId: number,
export const getDrugPriceGridOptions = (
getStoreId: () => number,
getProductType: () => number,
onSaveRow: (row: DrugItem) => Promise<void>,
): VxeGridProps<DrugItem> => ({
columns: [
): VxeGridProps<DrugItem> => {
const showImage = getProductType() !== 1;
const columns: VxeGridProps<DrugItem>['columns'] = [
{ type: 'seq', width: 60, title: '序号' },
{ field: 'drug_name', title: '药品名称' },
{
field: 'price',
title: '零售价',
editRender: { name: 'input', props: { type: 'number', step: 0.01, min: 0 } },
formatter: ({ cellValue }) => {
if (cellValue === null || cellValue === undefined || cellValue === '') {
return '0.00';
}
const num = parseFloat(String(cellValue));
return isNaN(num) ? '0.00' : num.toFixed(2);
},
},
{
field: 'buy_price',
title: '供货价',
editRender: { name: 'input', props: { type: 'number', step: 0.01, min: 0 } },
formatter: ({ cellValue }) => {
if (cellValue === null || cellValue === undefined || cellValue === '') {
return '0.00';
}
const num = parseFloat(String(cellValue));
return isNaN(num) ? '0.00' : num.toFixed(2);
},
},
{
title: '操作',
slots: { default: 'china-action' },
},
],
editConfig: {
mode: 'cell',
trigger: 'click',
showStatus: true,
},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
if (!storeId) {
return { items: [], total: 0 };
}
const res = await getStoreDrugsByTypeApi(storeId, 1);
let items = res || [];
];
// 如果有关键词搜索,进行过滤
if (formValues?.drug_name) {
const keyword = String(formValues.drug_name).toLowerCase();
items = items.filter((item: DrugItem) =>
item.drug_name?.toLowerCase().includes(keyword),
);
}
return { items, total: items.length };
},
},
},
toolbarConfig: {
search: true,
refresh: true,
zoom: true,
slots: {
buttons: 'toolbar-buttons',
},
},
height: 500,
showOverflow: true,
});
/**
* 获取西药表格配置
* @param storeId 诊所ID
* @param onSaveRow 单行保存回调函数
* @returns 表格配置对象
*/
export const getWesternMedicineGridOptions = (
storeId: number,
onSaveRow: (row: DrugItem) => Promise<void>,
): VxeGridProps<DrugItem> => ({
columns: [
{ type: 'seq', width: 60, title: '序号' },
{ field: 'drug_name', title: '药品名称' },
{
if (showImage) {
columns.push({
field: 'image',
title: '图片',
slots: { default: 'western-image' },
},
slots: { default: 'drug-image' },
});
}
columns.push(
{
field: 'price',
title: '零售价',
@@ -294,43 +213,50 @@ export const getWesternMedicineGridOptions = (
},
{
title: '操作',
slots: { default: 'western-action' },
slots: { default: 'row-action' },
},
],
editConfig: {
mode: 'cell',
trigger: 'click',
showStatus: true,
},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
if (!storeId) {
return { items: [], total: 0 };
}
const res = await getStoreDrugsByTypeApi(storeId, 2);
let items = res || [];
);
// 如果有关键词搜索,进行过滤
if (formValues?.drug_name) {
const keyword = String(formValues.drug_name).toLowerCase();
items = items.filter((item: DrugItem) =>
item.drug_name?.toLowerCase().includes(keyword),
);
}
return {
columns,
editConfig: {
mode: 'cell',
trigger: 'click',
showStatus: true,
},
proxyConfig: {
ajax: {
query: async (_ctx, formValues) => {
const storeId = getStoreId();
const productType = getProductType();
if (!storeId) {
return { items: [], total: 0 };
}
const res = await getStoreDrugsByTypeApi(storeId, productType);
let items = res || [];
return { items, total: items.length };
if (formValues?.drug_name) {
const keyword = String(formValues.drug_name).toLowerCase();
items = items.filter((item: DrugItem) =>
item.drug_name?.toLowerCase().includes(keyword),
);
}
return { items, total: items.length };
},
},
},
},
toolbarConfig: {
search: true,
refresh: true,
zoom: true,
slots: {
buttons: 'toolbar-buttons',
toolbarConfig: {
search: true,
refresh: true,
zoom: true,
slots: {
buttons: 'toolbar-buttons',
},
},
},
height: 500,
showOverflow: true,
});
height: 500,
showOverflow: true,
};
};
export { TCM_PLACEHOLDER_IMAGE };

View File

@@ -41,7 +41,8 @@ export const modalFormProps: VbenFormProps = {
component: 'Avatar',
fieldName: 'logo',
label: 'LOGO',
rules: 'required',
defaultValue: 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250108/1bb87d41d15fe27b500a4bfcde01bb0e.png',
// rules: 'required',
},
{
component: 'VbenInput',
@@ -65,14 +66,14 @@ export const modalFormProps: VbenFormProps = {
component: 'Avatar',
fieldName: 'open_business_license',
label: '营业执照',
rules: 'required',
// rules: 'required',
formItemClass: 'col-span-6',
},
{
component: 'Avatar',
fieldName: 'business_license',
label: '生产许可证',
rules: 'required',
// rules: 'required',
formItemClass: 'col-span-6',
},
{
@@ -80,7 +81,7 @@ export const modalFormProps: VbenFormProps = {
fieldName: 'product_registration_certificate',
label: '产品注册证',
formItemClass: 'col-span-6',
rules: 'required',
// rules: 'required',
},
],
showDefaultActions: false,