fix: 若干上传文件,表单bug

This commit is contained in:
louis 2024-03-08 10:38:53 +08:00
parent b2db3f82f1
commit fdc30067de
12 changed files with 369 additions and 183 deletions

View File

@ -1661,9 +1661,9 @@ declare namespace API {
/** 年度 */ /** 年度 */
year: number; year: number;
/** 外出使用的车辆Id */ /** 外出使用的车辆Id */
vechicleId: number; vehicleId: number;
/** 外出使用的车辆名称(字典) */ /** 外出使用的车辆名称(字典) */
vechicle: DictItemEntity; vehicle: DictItemEntity;
/** 申请人 */ /** 申请人 */
applicant: string; applicant: string;
/** 出行司机 */ /** 出行司机 */
@ -1696,11 +1696,13 @@ declare namespace API {
/** 年度 */ /** 年度 */
year: number; year: number;
/** 外出使用的车辆名称(字典) */ /** 外出使用的车辆名称(字典) */
vechicleId: number; vehicleId: number;
/** 申请人 */ /** 申请人 */
applicant: string; applicant: string;
/** 出行司机 */ /** 出行司机 */
driver: string; driver: string;
/** 随行人员 */
partner: string;
/** 当前车辆里程数(KM) */ /** 当前车辆里程数(KM) */
currentMileage: number; currentMileage: number;
/** 预计出行开始时间 */ /** 预计出行开始时间 */
@ -1723,7 +1725,6 @@ declare namespace API {
}; };
type VehicleUsageUpdateParams = { type VehicleUsageUpdateParams = {
id: number; id: number;
}; };
type VehicleUsageParams = { type VehicleUsageParams = {
page?: number; page?: number;
@ -1739,7 +1740,7 @@ declare namespace API {
/** 年度 */ /** 年度 */
year?: number; year?: number;
/** 外出使用的车辆名称(字典) */ /** 外出使用的车辆名称(字典) */
vechicleId?: number; vehicleId?: number;
/** 申请人 */ /** 申请人 */
applicant?: string; applicant?: string;
/** 出行司机 */ /** 出行司机 */

View File

@ -81,7 +81,7 @@ type ComponentSchema<T extends object = Recordable> =
/** 表单项 */ /** 表单项 */
export type FormSchema<T extends object = Recordable> = ComponentSchema<T> & { export type FormSchema<T extends object = Recordable> = ComponentSchema<T> & {
/** 字段名 */ /** 字段名 */
field: GetFieldKeys<T>; field?: GetFieldKeys<T>;
// Event name triggered by internal value change, default change // Event name triggered by internal value change, default change
changeEvent?: string; changeEvent?: string;
// Variable name bound to v-model Default value // Variable name bound to v-model Default value

View File

@ -1,4 +1,5 @@
export enum DictEnum { export enum DictEnum {
ContractType = 'contract_type', // 合同类型 ContractType = 'contract_type', // 合同类型
Unit = 'unit', // 单位 Unit = 'unit', // 单位,
Vehicle = 'vehicle', // 车辆
} }

5
src/enums/vehicleEnum.ts Normal file
View File

@ -0,0 +1,5 @@
export enum VehicleUsageStatusEnum {
Pending = 0, // 待审核
Approved = 1, // 已通过
Rejected = 2, // 已拒绝
}

View File

@ -35,7 +35,7 @@
<LockOutlined @click="lockscreenStore.setLock(true)" /> <LockOutlined @click="lockscreenStore.setLock(true)" />
</Tooltip> </Tooltip>
<FullScreen /> <FullScreen />
<LocalePicker /> <!-- <LocalePicker /> -->
<Dropdown placement="bottomRight"> <Dropdown placement="bottomRight">
<Avatar :src="userInfo.avatar" :alt="userInfo.username">{{ userInfo.username }}</Avatar> <Avatar :src="userInfo.avatar" :alt="userInfo.username">{{ userInfo.username }}</Avatar>
<template #overlay> <template #overlay>

View File

@ -5,7 +5,8 @@ import { store } from '@/store';
import { DictEnum } from '@/enums/dictEnum'; import { DictEnum } from '@/enums/dictEnum';
const needCachedKey = [ const needCachedKey = [
DictEnum.ContractType, DictEnum.ContractType,
DictEnum.Unit DictEnum.Unit,
DictEnum.Vehicle
]; ];
export const useDictStore = defineStore('dict', () => { export const useDictStore = defineStore('dict', () => {

View File

@ -11,7 +11,7 @@ export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FOR
} }
export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string { export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string {
return dayjs(date).format(format); return date ? dayjs(date).format(format) : '';
} }
export const dateUtil = dayjs; export const dateUtil = dayjs;

View File

@ -1,10 +1,10 @@
import type { FormSchema } from '@/components/core/schema-form/'; import type { FormSchema } from '@/components/core/schema-form/';
import { ContractStatusEnum } from '@/enums/contractEnum'; import { ContractStatusEnum } from '@/enums/contractEnum';
import { formatStatus } from './columns'; import { formatStatus } from './columns';
import { useDictStore } from '@/store/modules/dict';
export const contractSchemas = ( import { DictEnum } from '@/enums/dictEnum';
contractTypes: API.DictItemEntity[], const { getDictItemsByCode } = useDictStore();
): FormSchema<API.ContractEntity>[] => [ export const formSchemas = (isEdit = false): FormSchema<API.ContractEntity>[] => [
{ {
field: 'contractNumber', field: 'contractNumber',
component: 'Input', component: 'Input',
@ -47,7 +47,6 @@ export const contractSchemas = (
field: 'signingDate', field: 'signingDate',
label: '签订时间', label: '签订时间',
component: 'DatePicker', component: 'DatePicker',
// defaultValue: new Date(),
colProps: { span: 12 }, colProps: { span: 12 },
componentProps: {}, componentProps: {},
}, },
@ -55,7 +54,6 @@ export const contractSchemas = (
field: 'deliveryDeadline', field: 'deliveryDeadline',
label: '交付期限', label: '交付期限',
component: 'DatePicker', component: 'DatePicker',
// defaultValue: new Date(),
colProps: { span: 12 }, colProps: { span: 12 },
}, },
{ {
@ -67,14 +65,18 @@ export const contractSchemas = (
span: 12, span: 12,
}, },
componentProps: { componentProps: {
options: contractTypes.map(({ label, id }) => ({ value: id, label })), options: getDictItemsByCode(DictEnum.ContractType).map(({ label, id }) => ({
value: id,
label,
})),
}, },
}, },
{ {
field: 'status', field: 'status',
label: '审核结果', label: '审核结果',
component: 'Select', component: 'Select',
required:true, required: true,
vIf:isEdit,
defaultValue: 0, defaultValue: 0,
colProps: { colProps: {
span: 12, span: 12,

View File

@ -28,7 +28,7 @@
import { baseColumns, type TableColumnItem, type TableListItem } from './columns'; import { baseColumns, type TableColumnItem, type TableListItem } from './columns';
import Api from '@/api/'; import Api from '@/api/';
import { useFormModal, useModal } from '@/hooks/useModal'; import { useFormModal, useModal } from '@/hooks/useModal';
import { contractSchemas } from './formSchemas'; import { formSchemas } from './formSchemas';
import { formatToDate } from '@/utils/dateUtil'; import { formatToDate } from '@/utils/dateUtil';
import { Button } from 'ant-design-vue'; import { Button } from 'ant-design-vue';
import AttachmentManage from '@/components/business/attachment-manage/index.vue'; import AttachmentManage from '@/components/business/attachment-manage/index.vue';
@ -40,10 +40,7 @@
const [DynamicTable, dynamicTableInstance] = useTable(); const [DynamicTable, dynamicTableInstance] = useTable();
const [showModal] = useFormModal(); const [showModal] = useFormModal();
const [fnModal] = useModal(); const [fnModal] = useModal();
const contractTypes = ref<API.DictItemEntity[]>([]);
const isUploadPopupVisiable = ref(false); const isUploadPopupVisiable = ref(false);
// contractList;
let columns = ref<TableColumnItem[]>(); let columns = ref<TableColumnItem[]>();
onMounted(() => { onMounted(() => {
columns.value = [ columns.value = [
@ -139,20 +136,20 @@
onFinish: async (values) => { onFinish: async (values) => {
const params = { const params = {
...values, ...values,
signingDate: formatToDate(values.signingDate), signingDate: formatToDate(values.signingDate) || undefined,
deliveryDeadline: formatToDate(values.deliveryDeadline), deliveryDeadline: formatToDate(values.deliveryDeadline) || undefined,
}; };
if (record.id) { if (record.id) {
await Api.contract.contractUpdate({ id: record.id }, params); await Api.contract.contractUpdate({ id: record.id }, params);
} else { } else {
await Api.contract.contractCreate(params); await Api.contract.contractCreate(params as API.ContractDto);
} }
dynamicTableInstance?.reload(); dynamicTableInstance?.reload();
}, },
}, },
formProps: { formProps: {
labelWidth: 100, labelWidth: 100,
schemas: contractSchemas(contractTypes.value), schemas: formSchemas(!!record.id),
}, },
}); });

View File

@ -1,62 +1,172 @@
import Api from '@/api';
import type { TableColumn } from '@/components/core/dynamic-table'; import type { TableColumn } from '@/components/core/dynamic-table';
import { VehicleUsageStatusEnum } from '@/enums/vehicleEnum';
import { formatToDate } from '@/utils/dateUtil';
import { Tag } from 'ant-design-vue';
import dayjs from 'dayjs';
export type TableListItem = API.VehicleUsageEntity; export type TableListItem = API.VehicleUsageEntity;
export type TableColumnItem = TableColumn<TableListItem>; export type TableColumnItem = TableColumn<TableListItem>;
export const baseColumns: TableColumnItem[] = [ export const baseColumns: TableColumnItem[] = [
{ {
title: '外出使用的车辆名称及车牌号', title: '年度',
dataIndex: 'vechicle', width: 80,
fixed: 'left',
dataIndex: 'year',
formItemProps: {
label: '年度',
component: 'Select',
componentProps: {
fieldNames: {
label: 'label',
value: 'value',
},
options: Array.from({ length: dayjs().year() - 2010 }).map((_, index) => ({
label: `${dayjs().year() - index}`,
value: dayjs().year() - index,
})),
},
colProps: {
span: 4,
},
},
},
{
title: '车辆名称及车牌号',
width: 150,
dataIndex: 'vehicle',
fixed: 'left',
formItemProps: {
labelWidth: 150,
label: '车辆名称及车牌号',
span: 12,
},
customRender: ({ record }) => { customRender: ({ record }) => {
return record?.vechicle?.label || ''; return record?.vehicle?.label || '';
}, },
}, },
{ {
title: '申请人', title: '申请人',
dataIndex: 'applicant', dataIndex: 'applicant',
formItemProps: {
span: 10,
},
}, },
{ {
title: '出行司机', title: '出行司机',
hideInSearch: true,
dataIndex: 'driver', dataIndex: 'driver',
}, },
// /** 外出使用的车辆Id */ {
// vechicleId: number; title: '随行人员',
// /** 外出使用的车辆名称(字典) */ hideInSearch: true,
// vechicle: DictItemEntity; dataIndex: 'partner',
// /** 申请人 */ },
// applicant: string; {
// /** 出行司机 */ title: '当前车辆里程数(KM)',
// driver: string; hideInSearch: true,
// /** 当前车辆里程数(KM) */ dataIndex: 'currentMileage',
// currentMileage: number; },
// /** 预计出行开始时间 */ {
// expectedStartDate: Date; title: '预计出行开始时间',
// /** 预计出行结束时间 */ width: 130,
// expectedEndDate: Date; hideInSearch: true,
// /** 使用事由 */ align: 'center',
// purpose: string; dataIndex: 'expectedStartDate',
// /** 实际回司时间 */ customRender: ({ record }) => {
// actualReturnTime: Date; return formatToDate(record.expectedStartDate);
// /** 回城车辆里程数(KM) */ },
// returnMileage: number; },
// /** 审核人 */ {
// reviewer: string; title: '预计出行结束时间',
// /** 审核状态0待审核1同意2.不同意(字典) */ width: 130,
// status: number; hideInSearch: true,
// /** 备注 */ align: 'center',
// remark: string; dataIndex: 'expectedEndDate',
// { customRender: ({ record }) => {
// title: '所属公司', return formatToDate(record.expectedEndDate);
// dataIndex: 'company', },
// customRender: ({ record }) => { },
// return record?.company?.name || ''; {
// }, title: '使用事由',
// }, dataIndex: 'purpose',
// { hideInSearch: true,
// title: '单位', },
// dataIndex: 'unit', {
// customRender: ({ record }) => { title: '实际回司时间',
// return record?.unit?.label || ''; hideInSearch: true,
// }, width: 130,
// }, align: 'center',
dataIndex: 'actualReturnTime',
customRender: ({ record }) => {
return formatToDate(record.actualReturnTime);
},
},
{
title: '回城车辆里程数(KM)',
hideInSearch: true,
dataIndex: 'returnMileage',
},
{
title: '审核人',
hideInSearch: true,
dataIndex: 'reviewer',
},
{
title: '备注',
hideInSearch: true,
dataIndex: 'remark',
},
{
title: '审核状态',
width: 100,
align:'center',
fixed: 'right',
dataIndex: 'status',
formItemProps: {
component: 'Select',
componentProps: {
options: Object.values(VehicleUsageStatusEnum)
.filter((value) => typeof value === 'number')
.map((item) => formatStatus(item as VehicleUsageStatusEnum)),
},
},
customRender: ({ record }) => {
const { color, label } = formatStatus(record.status);
return <Tag color={color}>{label}</Tag>;
},
},
]; ];
export function formatStatus(status: VehicleUsageStatusEnum): {
color: string;
label: string;
value: number;
} {
switch (status) {
case VehicleUsageStatusEnum.Pending:
return {
color: '#ccc',
label: '待审核',
value: VehicleUsageStatusEnum.Pending,
};
case VehicleUsageStatusEnum.Approved:
return {
color: 'green',
label: '已通过',
value: VehicleUsageStatusEnum.Approved,
};
case VehicleUsageStatusEnum.Rejected:
return {
color: 'red',
label: '已拒绝',
value: VehicleUsageStatusEnum.Rejected,
};
default:
return {
color: '#ccc',
label: '待审核',
value: VehicleUsageStatusEnum.Pending,
};
}
}

View File

@ -1,99 +1,182 @@
import Api from '@/api'; import Api from '@/api';
import type { FormSchema } from '@/components/core/schema-form/'; import type { FormSchema } from '@/components/core/schema-form/';
import { DictEnum } from '@/enums/dictEnum'; import { DictEnum } from '@/enums/dictEnum';
import { VehicleUsageStatusEnum } from '@/enums/vehicleEnum';
import { useDictStore } from '@/store/modules/dict'; import { useDictStore } from '@/store/modules/dict';
import { debounce } from 'lodash-es'; import dayjs from 'dayjs';
import { formatStatus } from './columns';
const { getDictItemsByCode } = useDictStore(); const { getDictItemsByCode } = useDictStore();
export const formSchemas: FormSchema<API.VehicleUsageDto>[] = [ export const formSchemas = (isEdit?: boolean): FormSchema<API.VehicleUsageDto>[] => [
// { {
// field: 'name', label: '年度',
// component: 'Input', component: 'Select',
// label: '车辆使用名称', field: 'year',
// rules: [{ required: true, type: 'string' }], colProps: {
// colProps: { span: 6,
// span: 12, },
// }, defaultValue: dayjs().year(),
// }, rules: [{ required: true, type: 'number' }],
// { componentProps: () => ({
// label: '单位', fieldNames: {
// component: 'Select', label: 'label',
// field: 'unitId', value: 'value',
// colProps: { },
// span: 12, defaultValue: dayjs().year(),
// }, options: Array.from({ length: dayjs().year() - 2010 }).map((_, index) => ({
// componentProps: ({ formInstance, schema, formModel }) => ({ label: `${dayjs().year() - index}`,
// showSearch: true, value: dayjs().year() - index,
// filterOption: (input: string, option: any) => { })),
// return option.label.indexOf(input) >= 0; }),
// }, },
// fieldNames: {
// label: 'label',
// value: 'value',
// },
// options: getDictItemsByCode(DictEnum.Unit).map((item) => ({
// value: item.id,
// label: item.label,
// })),
// getPopupContainer: () => document.body,
// defaultActiveFirstOption: true,
// }),
// },
// {
// field: 'companyId',
// component: 'Select',
// label: '所属公司',
// helpMessage: '如未找到对应公司,请先去公司管理添加公司。',
// componentProps: ({ formInstance, schema }) => ({
// showSearch: true,
// filterOption: false,
// fieldNames: {
// label: 'label',
// value: 'value',
// },
// options: [],
// getPopupContainer: () => document.body,
// defaultActiveFirstOption: true,
// onChange: async (value) => {
// if (!value) {
// formInstance?.setFieldsValue({ companyId: undefined });
// const options = await getCompanyOptions();
// const newSchema = {
// field: schema.field,
// componentProps: {
// options,
// },
// };
// formInstance?.updateSchema([newSchema]);
// }
// },
// request: () => { {
// return getCompanyOptions(); field: 'vehicleId',
// }, component: 'Select',
// onSearch: debounce(async (keyword) => { label: '车辆名称及车牌号',
// schema.loading = true; rules: [{ required: true, type: 'number' }],
// const newSchema = { labelWidth: 150,
// field: schema.field, helpMessage: '如未找到对应车辆,请先去字典管理添加车辆。',
// componentProps: { colProps: {
// options: [] as LabelValueOptions, span: 16,
// }, offset: 1,
// }; },
// formInstance?.updateSchema([newSchema]); componentProps: ({ formInstance, schema }) => ({
// const options = await getCompanyOptions(keyword).finally(() => (schema.loading = false)); showSearch: true,
// newSchema.componentProps.options = options; filterOption: (input: string, option: any) => {
// formInstance?.updateSchema([newSchema]); return option.label.toLocaleLowerCase().indexOf(input.toLocaleLowerCase()) >= 0;
// }, 500), },
// }), fieldNames: {
// }, label: 'label',
value: 'value',
},
options: getDictItemsByCode(DictEnum.Vehicle).map((item) => ({
value: item.id,
label: item.label,
})),
getPopupContainer: () => document.body,
defaultActiveFirstOption: true,
}),
},
{
field: 'applicant',
component: 'Input',
label: '申请人',
rules: [{ required: true, type: 'string' }],
colProps: {
span: 8,
},
},
{
field: 'driver',
component: 'Input',
label: '出行司机',
rules: [{ type: 'string' }],
colProps: {
span: 8,
},
},
{
field: 'partner',
component: 'Input',
label: '随行人员',
rules: [{ type: 'string' }],
colProps: {
span: 8,
},
},
{
label: '预计出行开始时间',
field: 'expectedStartDate',
component: 'DatePicker',
labelWidth: 150,
rules: [{ type: 'date', required: true }],
colProps: {
span: 12,
},
},
{
label: '预计出行结束时间',
field: 'expectedEndDate',
labelWidth: 150,
rules: [{ type: 'date', required: true }],
component: 'DatePicker',
colProps: {
span: 12,
},
},
{
field: 'currentMileage',
component: 'InputNumber',
label: '当前车辆里程数(KM)',
rules: [{ type: 'number' }],
labelWidth: 150,
colProps: {
span: 24,
},
},
{
label: '回城车辆里程数(KM)',
labelWidth: 150,
vIf: isEdit,
field: 'returnMileage',
rules: [{ type: 'number' }],
component: 'InputNumber',
colProps: {
span: 24,
},
},
{
label: '实际回司时间',
field: 'actualReturnTime',
labelWidth: 150,
vIf: isEdit,
rules: [{ type: 'date' }],
component: 'DatePicker',
colProps: {
span: 12,
},
},
{
field: 'purpose',
component: 'InputTextArea',
label: '使用事由',
rules: [{ type: 'string' }],
},
{
field: 'reviewer',
component: 'Input',
label: '审核人',
rules: [{ type: 'string' }],
colProps: {
span: 8,
},
},
{
field: 'status',
label: '审核结果',
component: 'Select',
required: true,
vIf: isEdit,
defaultValue: 0,
colProps: {
span: 8,
},
componentProps: {
allowClear: false,
options: Object.values(VehicleUsageStatusEnum)
.filter((value) => typeof value === 'number')
.map((item) => formatStatus(item as VehicleUsageStatusEnum)),
},
},
{
label: '备注',
field: 'remark',
component: 'Input',
colProps: {
span: 8,
},
},
]; ];
const getCompanyOptions = async (keyword?: string): Promise<LabelValueOptions> => {
const { items: result } = await Api.company.companyList({ pageSize: 100, name: keyword });
return (
result?.map((item) => ({
label: item.name,
value: item.id,
})) || []
);
};

View File

@ -8,12 +8,13 @@
:columns="columns" :columns="columns"
:exportFileName="'车辆使用'" :exportFileName="'车辆使用'"
bordered bordered
:scroll="{ x: 1920 }"
size="small" size="small"
> >
<template #toolbar> <template #toolbar>
<a-button <a-button
type="primary" type="primary"
:disabled="!$auth('system:role:create')" :disabled="!$auth('app:vehicle_usage:create')"
@click="openEditModal({})" @click="openEditModal({})"
> >
新增 新增
@ -41,23 +42,7 @@
const [showModal] = useFormModal(); const [showModal] = useFormModal();
const [fnModal] = useModal(); const [fnModal] = useModal();
const isUploadPopupVisiable = ref(false); const isUploadPopupVisiable = ref(false);
const dictStore = useDictStore();
let columns = ref<TableColumnItem[]>(); let columns = ref<TableColumnItem[]>();
// const loadData = async (params): Promise<API.VehicleUsageEntity> => {
// console.log('params', params);
// return Api.vehicleUsage.vehicleUsageList(params);
// };
// const loadTableData = async (params: any) => {
// const { company, ...res } = params;
// const data = await Api.vehicleUsage.vehicleUsageList({
// ...res,
// company,
// });
// return data;
// };
const exportFormatter = (columns: TableColumn[], tableData: any[]) => {
return { header: columns.map((item) => item.title), data: [] };
};
onMounted(() => { onMounted(() => {
columns.value = [ columns.value = [
...baseColumns, ...baseColumns,
@ -65,6 +50,7 @@
title: '附件', title: '附件',
width: 50, width: 50,
maxWidth: 50, maxWidth: 50,
fixed: 'right',
hideInSearch: true, hideInSearch: true,
hideInExport: true, hideInExport: true,
dataIndex: 'files', dataIndex: 'files',
@ -83,7 +69,7 @@
icon: 'ant-design:edit-outlined', icon: 'ant-design:edit-outlined',
tooltip: '编辑', tooltip: '编辑',
auth: { auth: {
perm: 'app:vehicleUsage:update', perm: 'app:vehicle_usage:update',
effect: 'disable', effect: 'disable',
}, },
onClick: () => openEditModal(record), onClick: () => openEditModal(record),
@ -92,7 +78,7 @@
icon: 'ant-design:delete-outlined', icon: 'ant-design:delete-outlined',
color: 'red', color: 'red',
tooltip: '删除此车辆使用', tooltip: '删除此车辆使用',
auth: 'app:vehicleUsage:delete', auth: 'app:vehicle_usage:delete',
popConfirm: { popConfirm: {
title: '你确定要删除吗?', title: '你确定要删除吗?',
placement: 'left', placement: 'left',
@ -113,7 +99,7 @@
isUploadPopupVisiable.value = true; isUploadPopupVisiable.value = true;
fnModal.show({ fnModal.show({
width: 800, width: 800,
title: `车辆使用: ${record.vechicleId}`, title: `车辆使用: ${record.vehicleId}`,
content: () => { content: () => {
return ( return (
<AttachmentUpload <AttachmentUpload
@ -163,7 +149,7 @@
}, },
formProps: { formProps: {
labelWidth: 100, labelWidth: 100,
schemas: formSchemas, schemas: formSchemas(!!record.id),
}, },
}); });