Compare commits
2 Commits
96a9234239
...
7c508de85e
Author | SHA1 | Date | |
---|---|---|---|
7c508de85e | |||
d4c26d13ea |
@ -19,7 +19,7 @@ export interface Clean_orderVO {
|
||||
/**
|
||||
* 保洁id
|
||||
*/
|
||||
cleanId: string | number;
|
||||
cleanId: string | null;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
@ -54,7 +54,7 @@ export interface Clean_orderVO {
|
||||
/**
|
||||
* 单位id
|
||||
*/
|
||||
unitId: string | number;
|
||||
unitId: string | null;
|
||||
|
||||
/**
|
||||
* 申请单位
|
||||
|
@ -1,13 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
import { cloneDeep } from '@vben/utils';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { cleanAdd, cleanInfo, cleanUpdate } from '#/api/property/clean';
|
||||
import { cleanAdd, cleanInfo, cleanUpdate, cleanList } from '#/api/property/clean';
|
||||
import type { CleanVO } from '#/api/property/clean/model';
|
||||
import { clean_orderAdd, clean_orderInfo, clean_orderUpdate } from '#/api/property/clean_order';
|
||||
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
|
||||
import { resident_unitList } from '#/api/property/resident/unit';
|
||||
|
||||
import { modalSchema } from './data';
|
||||
|
||||
@ -18,17 +22,56 @@ const title = computed(() => {
|
||||
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
|
||||
});
|
||||
|
||||
// 用来缓存 cleanList 的完整数据
|
||||
let cleanListData: CleanVO[] = [];
|
||||
|
||||
// 在文件顶部加缓存
|
||||
let unitListData: { id: any; name: string }[] = [];
|
||||
|
||||
const editUnitId = ref('');
|
||||
const editCleanId = ref('');
|
||||
|
||||
const [BasicForm, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
// 默认占满两列
|
||||
formItemClass: 'col-span-2',
|
||||
formItemClass: 'col-span-1',
|
||||
// 默认label宽度 px
|
||||
labelWidth: 80,
|
||||
labelWidth: 120,
|
||||
// 通用配置项 会影响到所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
}
|
||||
},
|
||||
// 1. 使用正确的属性名 handleValuesChange
|
||||
handleValuesChange: async (values, fieldsChanged) => {
|
||||
// 2. fieldsChanged 是一个包含变化字段名的数组
|
||||
if (fieldsChanged.includes('name')) {
|
||||
// 如果缓存数据为空,先请求一次并缓存
|
||||
if (cleanListData.length === 0) {
|
||||
try {
|
||||
const res = await cleanList(); // 查询所有
|
||||
cleanListData = res.rows || [];
|
||||
} catch (e) {
|
||||
console.error('获取劳务列表失败:', e);
|
||||
cleanListData = []; // 出错时清空
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 从 values 中获取当前选中的 id
|
||||
const selectedId = values.name;
|
||||
const selectedItem = cleanListData.find(item => item.id === selectedId);
|
||||
|
||||
if (selectedItem) {
|
||||
// 4. 使用正确的 formApi.setValues 方法
|
||||
await formApi.setValues({
|
||||
prices: selectedItem.peices, // 服务单价
|
||||
frequency: selectedItem.frequency, // 保洁频率
|
||||
standard: selectedItem.standard, // 保洁内容
|
||||
peices: selectedItem.peices, // 保洁标准
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
schema: modalSchema(),
|
||||
showDefaultActions: false,
|
||||
wrapperClass: 'grid-cols-2',
|
||||
@ -43,7 +86,7 @@ const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
||||
|
||||
const [BasicModal, modalApi] = useVbenModal({
|
||||
// 在这里更改宽度
|
||||
class: 'w-[550px]',
|
||||
class: 'w-[70%]',
|
||||
fullscreenButton: false,
|
||||
onBeforeClose,
|
||||
onClosed: handleClosed,
|
||||
@ -56,13 +99,15 @@ const [BasicModal, modalApi] = useVbenModal({
|
||||
|
||||
const { id } = modalApi.getData() as { id?: number | string };
|
||||
isUpdate.value = !!id;
|
||||
|
||||
if (isUpdate.value && id) {
|
||||
const record = await cleanInfo(id);
|
||||
const record = await clean_orderInfo(id);
|
||||
if (record.starTime) record.starTime = dayjs(record.starTime);
|
||||
if (record.endTime) record.endTime = dayjs(record.endTime);
|
||||
editUnitId.value = record.unitId || '';
|
||||
editCleanId.value = record.cleanId || '';
|
||||
await formApi.setValues(record);
|
||||
}
|
||||
await markInitialized();
|
||||
|
||||
modalApi.modalLoading(false);
|
||||
},
|
||||
});
|
||||
@ -74,9 +119,30 @@ async function handleConfirm() {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
|
||||
const data = cloneDeep(await formApi.getValues());
|
||||
await (isUpdate.value ? cleanUpdate(data) : cleanAdd(data));
|
||||
console.log(data);
|
||||
|
||||
// 单位数据缓存
|
||||
if (unitListData.length === 0) {
|
||||
const res = await resident_unitList();
|
||||
unitListData = res.rows || [];
|
||||
}
|
||||
// 劳务数据缓存 cleanListData 已有
|
||||
|
||||
// 查找label
|
||||
const unitObj = unitListData.find(item => item.id === data.unit);
|
||||
const cleanObj = cleanListData.find(item => item.id === data.name);
|
||||
|
||||
data.unit = unitObj ? unitObj.name : data.unit || '' ;
|
||||
data.name = cleanObj ? cleanObj.name :data.name || '';
|
||||
data.unitId = unitObj ? unitObj.id : (isUpdate.value ? editUnitId.value : '');
|
||||
data.cleanId = cleanObj ? cleanObj.id : (isUpdate.value ? editCleanId.value : '');
|
||||
|
||||
// 如不需要原字段可删除
|
||||
// delete data.unit;
|
||||
// delete data.name;
|
||||
|
||||
await (isUpdate.value ? clean_orderUpdate(data) : clean_orderAdd(data));
|
||||
resetInitialized();
|
||||
emit('reload');
|
||||
modalApi.close();
|
||||
|
@ -1,42 +1,38 @@
|
||||
import type { FormSchemaGetter } from '#/adapter/form';
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { cleanList } from '#/api/property/clean';
|
||||
import type { PageResult } from '#/api/common';
|
||||
import type { CleanVO } from '#/api/property/clean/model';
|
||||
import { resident_unitList } from '#/api/property/resident/unit';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export const querySchema: FormSchemaGetter = () => [
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'name',
|
||||
label: '劳务名称',
|
||||
},
|
||||
{
|
||||
component: 'Textarea',
|
||||
fieldName: 'measure',
|
||||
label: '计量单位',
|
||||
fieldName: 'location',
|
||||
label: '服务地址',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'method',
|
||||
label: '计算方式',
|
||||
fieldName: 'persion',
|
||||
label: '申请人',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'peices',
|
||||
label: '单价',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'frequency',
|
||||
label: '保洁频率',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'standard',
|
||||
label: '保洁标准',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'stater',
|
||||
label: '状态',
|
||||
component: 'Select',
|
||||
fieldName: 'payState',
|
||||
label: '支付状态',
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '待支付',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '已支付',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@ -45,41 +41,65 @@ export const querySchema: FormSchemaGetter = () => [
|
||||
export const columns: VxeGridProps['columns'] = [
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{
|
||||
title: '主键id',
|
||||
title: '序号',
|
||||
field: 'id',
|
||||
slots: {
|
||||
default: ({ rowIndex }) => {
|
||||
return (rowIndex + 1).toString();
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '服务地址',
|
||||
field: 'location',
|
||||
},
|
||||
{
|
||||
title: '服务面积(㎡)',
|
||||
field: 'area',
|
||||
},
|
||||
{
|
||||
title: '劳务名称',
|
||||
field: 'name',
|
||||
},
|
||||
{
|
||||
title: '计量单位',
|
||||
field: 'measure',
|
||||
title: '申报单价含税(元)',
|
||||
field: 'prices',
|
||||
},
|
||||
{
|
||||
title: '计算方式',
|
||||
field: 'method',
|
||||
title: '合计费用',
|
||||
field: 'sumPeices',
|
||||
},
|
||||
{
|
||||
title: '单价',
|
||||
field: 'peices',
|
||||
title: '支付状态',
|
||||
field: 'payState',
|
||||
slots: {
|
||||
default: ({ row }) => row.stater === 1 ? '已支付' : '待支付',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '保洁频率',
|
||||
field: 'frequency',
|
||||
title: '服务开始时间',
|
||||
field: 'starTime',
|
||||
},
|
||||
{
|
||||
title: '保洁标准',
|
||||
field: 'standard',
|
||||
title: '服务结束时间',
|
||||
field: 'endTime',
|
||||
},
|
||||
{
|
||||
title: '申请单位',
|
||||
field: 'unit',
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
field: 'remark',
|
||||
title: '申请人',
|
||||
field: 'persion',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
field: 'stater',
|
||||
title: '联系电话',
|
||||
field: 'phone',
|
||||
},
|
||||
// {
|
||||
// title: '提交时间',
|
||||
// field: 'stater',
|
||||
// },
|
||||
{
|
||||
field: 'action',
|
||||
fixed: 'right',
|
||||
@ -99,52 +119,133 @@ export const modalSchema: FormSchemaGetter = () => [
|
||||
triggerFields: [''],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '服务地址(房间号)',
|
||||
fieldName: 'location',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '服务面积(㎡)',
|
||||
fieldName: 'area',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '劳务名称',
|
||||
fieldName: 'name',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: cleanList,
|
||||
resultField: 'rows',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '服务单价',
|
||||
fieldName: 'prices',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
componentProps: {
|
||||
placeholder: '',
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
// {
|
||||
// label: '保洁频率',
|
||||
// fieldName: 'frequency',
|
||||
// component: 'Input',
|
||||
// rules: 'required',
|
||||
// componentProps: {
|
||||
// placeholder: '',
|
||||
// disabled: true,
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// label: '保洁内容',
|
||||
// fieldName: 'standard',
|
||||
// component: 'Input',
|
||||
// rules: 'required',
|
||||
// componentProps: {
|
||||
// placeholder: '',
|
||||
// disabled: true,
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// label: '保洁标准',
|
||||
// fieldName: 'peices',
|
||||
// component: 'Input',
|
||||
// rules: 'required',
|
||||
// componentProps: {
|
||||
// placeholder: '',
|
||||
// disabled: true,
|
||||
// },
|
||||
// },
|
||||
{
|
||||
label: '开始时间',
|
||||
fieldName: 'starTime',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
showTime: true,
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
placeholder: '请选择开始时间'
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '结束时间',
|
||||
fieldName: 'endTime',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
showTime: true,
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
placeholder: '请选择结束时间'
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '申请人',
|
||||
fieldName: 'persion',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '计量单位',
|
||||
fieldName: 'measure',
|
||||
component: 'Textarea',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '计算方式',
|
||||
fieldName: 'method',
|
||||
label: '联系电话',
|
||||
fieldName: 'phone',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '单价',
|
||||
fieldName: 'peices',
|
||||
component: 'Input',
|
||||
label: '申请单位',
|
||||
fieldName: 'unit',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: resident_unitList,
|
||||
resultField: 'rows',
|
||||
labelField: 'name',
|
||||
valueField: 'id',
|
||||
placeholder: '请选择单位',
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '保洁频率',
|
||||
fieldName: 'frequency',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '保洁标准',
|
||||
fieldName: 'standard',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
fieldName: 'remark',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
fieldName: 'stater',
|
||||
component: 'Input',
|
||||
{
|
||||
label: '支付状态',
|
||||
fieldName: 'payState',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '待支付',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '已支付',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
];
|
||||
|
@ -20,6 +20,11 @@ import {
|
||||
cleanList,
|
||||
cleanRemove,
|
||||
} from '#/api/property/clean';
|
||||
import {
|
||||
clean_orderExport,
|
||||
clean_orderList,
|
||||
clean_orderRemove,
|
||||
} from '#/api/property/clean_order';
|
||||
import type { CleanForm } from '#/api/property/clean/model';
|
||||
import { commonDownloadExcel } from '#/utils/file/download';
|
||||
|
||||
@ -28,7 +33,7 @@ import { columns, querySchema } from './data';
|
||||
|
||||
const formOptions: VbenFormProps = {
|
||||
commonConfig: {
|
||||
labelWidth: 80,
|
||||
labelWidth: 120,
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
@ -64,7 +69,7 @@ const gridOptions: VxeGridProps = {
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues = {}) => {
|
||||
return await cleanList({
|
||||
return await clean_orderList({
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
@ -99,7 +104,7 @@ async function handleEdit(row: Required<CleanForm>) {
|
||||
}
|
||||
|
||||
async function handleDelete(row: Required<CleanForm>) {
|
||||
await cleanRemove(row.id);
|
||||
await clean_orderRemove(row.id);
|
||||
await tableApi.query();
|
||||
}
|
||||
|
||||
@ -111,14 +116,14 @@ function handleMultiDelete() {
|
||||
okType: 'danger',
|
||||
content: `确认删除选中的${ids.length}条记录吗?`,
|
||||
onOk: async () => {
|
||||
await cleanRemove(ids);
|
||||
await clean_orderRemove(ids);
|
||||
await tableApi.query();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleDownloadExcel() {
|
||||
commonDownloadExcel(cleanExport, '保洁管理数据', tableApi.formApi.form.values, {
|
||||
commonDownloadExcel(clean_orderExport, '保洁订单数据', tableApi.formApi.form.values, {
|
||||
fieldMappingTime: formOptions.fieldMappingTime,
|
||||
});
|
||||
}
|
||||
@ -126,7 +131,7 @@ function handleDownloadExcel() {
|
||||
|
||||
<template>
|
||||
<Page :auto-content-height="true">
|
||||
<BasicTable table-title="保洁管理列表">
|
||||
<BasicTable table-title="保洁订单列表">
|
||||
<template #toolbar-tools>
|
||||
<Space>
|
||||
<a-button
|
||||
|
@ -0,0 +1,101 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
import { cloneDeep } from '@vben/utils';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { cleanAdd, cleanInfo, cleanUpdate } from '#/api/property/clean';
|
||||
import { defaultFormValueGetter, useBeforeCloseDiff } from '#/utils/popup';
|
||||
|
||||
import { modalSchema } from './data';
|
||||
|
||||
const emit = defineEmits<{ reload: [] }>();
|
||||
|
||||
const isUpdate = ref(false);
|
||||
const title = computed(() => {
|
||||
return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
|
||||
});
|
||||
|
||||
const [BasicForm, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
// 默认占满两列
|
||||
formItemClass: 'col-span-1',
|
||||
// 默认label宽度 px
|
||||
labelWidth: 120,
|
||||
// 通用配置项 会影响到所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
}
|
||||
},
|
||||
schema: modalSchema(),
|
||||
showDefaultActions: false,
|
||||
wrapperClass: 'grid-cols-2',
|
||||
});
|
||||
|
||||
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
|
||||
{
|
||||
initializedGetter: defaultFormValueGetter(formApi),
|
||||
currentGetter: defaultFormValueGetter(formApi),
|
||||
},
|
||||
);
|
||||
|
||||
const [BasicModal, modalApi] = useVbenModal({
|
||||
// 在这里更改宽度
|
||||
class: 'w-[70%]',
|
||||
fullscreenButton: false,
|
||||
onBeforeClose,
|
||||
onClosed: handleClosed,
|
||||
onConfirm: handleConfirm,
|
||||
onOpenChange: async (isOpen) => {
|
||||
if (!isOpen) {
|
||||
return null;
|
||||
}
|
||||
modalApi.modalLoading(true);
|
||||
|
||||
const { id } = modalApi.getData() as { id?: number | string };
|
||||
isUpdate.value = !!id;
|
||||
|
||||
if (isUpdate.value && id) {
|
||||
const record = await cleanInfo(id);
|
||||
await formApi.setValues(record);
|
||||
}
|
||||
await markInitialized();
|
||||
|
||||
modalApi.modalLoading(false);
|
||||
},
|
||||
});
|
||||
|
||||
async function handleConfirm() {
|
||||
try {
|
||||
modalApi.lock(true);
|
||||
const { valid } = await formApi.validate();
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// getValues获取为一个readonly的对象 需要修改必须先深拷贝一次
|
||||
const data = cloneDeep(await formApi.getValues());
|
||||
await (isUpdate.value ? cleanUpdate(data) : cleanAdd(data));
|
||||
resetInitialized();
|
||||
emit('reload');
|
||||
modalApi.close();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
modalApi.lock(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleClosed() {
|
||||
await formApi.resetForm();
|
||||
resetInitialized();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicModal :title="title">
|
||||
<BasicForm />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
189
apps/web-antd/src/views/property/clean/cleanSettings/data.ts
Normal file
189
apps/web-antd/src/views/property/clean/cleanSettings/data.ts
Normal file
@ -0,0 +1,189 @@
|
||||
import type { FormSchemaGetter } from '#/adapter/form';
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
|
||||
export const querySchema: FormSchemaGetter = () => [
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'name',
|
||||
label: '劳务名称',
|
||||
},
|
||||
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'method',
|
||||
label: '计算方式',
|
||||
},
|
||||
{
|
||||
component: 'Select',
|
||||
fieldName: 'stater',
|
||||
label: '状态',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '下架', value: 0 },
|
||||
{ label: '上架', value: 1 },
|
||||
],
|
||||
placeholder: '请选择类型',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||
// export const columns: () => VxeGridProps['columns'] = () => [
|
||||
export const columns: VxeGridProps['columns'] = [
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{
|
||||
title: '序号',
|
||||
field: 'id',
|
||||
width: 60,
|
||||
slots: {
|
||||
default: ({ rowIndex }) => {
|
||||
return (rowIndex + 1).toString();
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '劳务名称',
|
||||
field: 'name',
|
||||
},
|
||||
{
|
||||
title: '计量单位',
|
||||
field: 'measure',
|
||||
},
|
||||
{
|
||||
title: '计算方式',
|
||||
field: 'method',
|
||||
},
|
||||
{
|
||||
title: '申报单价含税(元)',
|
||||
field: 'peices',
|
||||
},
|
||||
{
|
||||
title: '保洁频率',
|
||||
field: 'frequency',
|
||||
},
|
||||
// {
|
||||
// title: '保洁内容',
|
||||
// field: 'standard',
|
||||
// },
|
||||
{
|
||||
title: '保洁标准',
|
||||
field: 'standard',
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
field: 'remark',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
field: 'stater',
|
||||
slots: {
|
||||
default: ({ row }) => row.stater === 1 ? '上架' : '下架',
|
||||
},
|
||||
},
|
||||
// {
|
||||
// title: '创建时间',
|
||||
// field: 'stater',
|
||||
// },
|
||||
{
|
||||
field: 'action',
|
||||
fixed: 'right',
|
||||
slots: { default: 'action' },
|
||||
title: '操作',
|
||||
width: 180,
|
||||
},
|
||||
];
|
||||
|
||||
export const modalSchema: FormSchemaGetter = () => [
|
||||
{
|
||||
label: '主键id',
|
||||
fieldName: 'id',
|
||||
component: 'Input',
|
||||
dependencies: {
|
||||
show: () => false,
|
||||
triggerFields: [''],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '劳务名称',
|
||||
fieldName: 'name',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '计量单位',
|
||||
fieldName: 'measure',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '计算方式',
|
||||
fieldName: 'method',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '申报单价含税(元)',
|
||||
fieldName: 'peices',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '保洁频率',
|
||||
fieldName: 'frequency',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
// {
|
||||
// label: '保洁内容',
|
||||
// fieldName: 'standard',
|
||||
// component: 'Input',
|
||||
// rules: 'required',
|
||||
// },
|
||||
{
|
||||
label: '保洁标准',
|
||||
fieldName: 'standard',
|
||||
component: 'Input',
|
||||
rules: 'required',
|
||||
},
|
||||
// {
|
||||
// label: '开始时间',
|
||||
// fieldName: 'starTime',
|
||||
// component: 'DatePicker',
|
||||
// componentProps: {
|
||||
// showTime: true,
|
||||
// format: 'YYYY-MM-DD HH:mm:ss',
|
||||
// placeholder: '请选择开始时间'
|
||||
// },
|
||||
// rules: 'required',
|
||||
// },
|
||||
// {
|
||||
// label: '结束时间',
|
||||
// fieldName: 'endTime',
|
||||
// component: 'DatePicker',
|
||||
// componentProps: {
|
||||
// showTime: true,
|
||||
// format: 'YYYY-MM-DD HH:mm:ss',
|
||||
// placeholder: '请选择结束时间'
|
||||
// },
|
||||
// rules: 'required',
|
||||
// },
|
||||
{
|
||||
label: '状态',
|
||||
fieldName: 'stater',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '下架', value: 0 },
|
||||
{ label: '上架', value: 1 },
|
||||
],
|
||||
placeholder: '请选择类型',
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
fieldName: 'remark',
|
||||
component: 'Input',
|
||||
},
|
||||
];
|
@ -1,4 +1,181 @@
|
||||
<script setup lang="ts">
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
|
||||
import { getVxePopupContainer } from '@vben/utils';
|
||||
|
||||
import { Modal, Popconfirm, Space } from 'ant-design-vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import {
|
||||
useVbenVxeGrid,
|
||||
vxeCheckboxChecked,
|
||||
type VxeGridProps
|
||||
} from '#/adapter/vxe-table';
|
||||
|
||||
import {
|
||||
cleanExport,
|
||||
cleanList,
|
||||
cleanRemove,
|
||||
} from '#/api/property/clean';
|
||||
import type { CleanForm } from '#/api/property/clean/model';
|
||||
import { commonDownloadExcel } from '#/utils/file/download';
|
||||
|
||||
import cleanModal from './clean-modal.vue';
|
||||
import { columns, querySchema } from './data';
|
||||
|
||||
const formOptions: VbenFormProps = {
|
||||
commonConfig: {
|
||||
labelWidth: 120, componentProps: {
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
schema: querySchema(),
|
||||
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
|
||||
// 处理区间选择器RangePicker时间格式 将一个字段映射为两个字段 搜索/导出会用到
|
||||
// 不需要直接删除
|
||||
// fieldMappingTime: [
|
||||
// [
|
||||
// 'createTime',
|
||||
// ['params[beginTime]', 'params[endTime]'],
|
||||
// ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'],
|
||||
// ],
|
||||
// ],
|
||||
};
|
||||
|
||||
const gridOptions: VxeGridProps = {
|
||||
checkboxConfig: {
|
||||
// 高亮
|
||||
highlight: true,
|
||||
// 翻页时保留选中状态
|
||||
reserve: true,
|
||||
// 点击行选中
|
||||
// trigger: 'row',
|
||||
},
|
||||
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
||||
// columns: columns(),
|
||||
columns,
|
||||
height: 'auto',
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues = {}) => {
|
||||
return await cleanList({
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
rowConfig: {
|
||||
keyField: 'id',
|
||||
},
|
||||
// 表格全局唯一表示 保存列配置需要用到
|
||||
id: 'property-clean-index'
|
||||
};
|
||||
|
||||
const [BasicTable, tableApi] = useVbenVxeGrid({
|
||||
formOptions,
|
||||
gridOptions,
|
||||
});
|
||||
|
||||
const [CleanModal, modalApi] = useVbenModal({
|
||||
connectedComponent: cleanModal,
|
||||
});
|
||||
|
||||
function handleAdd() {
|
||||
modalApi.setData({});
|
||||
modalApi.open();
|
||||
}
|
||||
|
||||
async function handleEdit(row: Required<CleanForm>) {
|
||||
modalApi.setData({ id: row.id });
|
||||
modalApi.open();
|
||||
}
|
||||
|
||||
async function handleDelete(row: Required<CleanForm>) {
|
||||
await cleanRemove(row.id);
|
||||
await tableApi.query();
|
||||
}
|
||||
|
||||
function handleMultiDelete() {
|
||||
const rows = tableApi.grid.getCheckboxRecords();
|
||||
const ids = rows.map((row: Required<CleanForm>) => row.id);
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
okType: 'danger',
|
||||
content: `确认删除选中的${ids.length}条记录吗?`,
|
||||
onOk: async () => {
|
||||
await cleanRemove(ids);
|
||||
await tableApi.query();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleDownloadExcel() {
|
||||
commonDownloadExcel(cleanExport, '保洁管理数据', tableApi.formApi.form.values, {
|
||||
fieldMappingTime: formOptions.fieldMappingTime,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>保洁设置</div>
|
||||
<Page :auto-content-height="true">
|
||||
<BasicTable table-title="保洁设置列表">
|
||||
<template #toolbar-tools>
|
||||
<Space>
|
||||
<a-button
|
||||
v-access:code="['property:clean:export']"
|
||||
@click="handleDownloadExcel"
|
||||
>
|
||||
{{ $t('pages.common.export') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
:disabled="!vxeCheckboxChecked(tableApi)"
|
||||
danger
|
||||
type="primary"
|
||||
v-access:code="['property:clean:remove']"
|
||||
@click="handleMultiDelete">
|
||||
{{ $t('pages.common.delete') }}
|
||||
</a-button>
|
||||
<a-button
|
||||
type="primary"
|
||||
v-access:code="['property:clean:add']"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('pages.common.add') }}
|
||||
</a-button>
|
||||
</Space>
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<Space>
|
||||
<ghost-button
|
||||
v-access:code="['property:clean:edit']"
|
||||
@click.stop="handleEdit(row)"
|
||||
>
|
||||
{{ $t('pages.common.edit') }}
|
||||
</ghost-button>
|
||||
<Popconfirm
|
||||
:get-popup-container="getVxePopupContainer"
|
||||
placement="left"
|
||||
title="确认删除?"
|
||||
@confirm="handleDelete(row)"
|
||||
>
|
||||
<ghost-button
|
||||
danger
|
||||
v-access:code="['property:clean:remove']"
|
||||
@click.stop=""
|
||||
>
|
||||
{{ $t('pages.common.delete') }}
|
||||
</ghost-button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<CleanModal @reload="tableApi.query()" />
|
||||
</Page>
|
||||
</template>
|
||||
<script></script>
|
@ -1,134 +1,5 @@
|
||||
<template>
|
||||
<div class="conference-list">
|
||||
<a-list
|
||||
:grid="{ gutter: 16, xs: 1, sm: 2, md: 2, lg: 3, xl: 4, xxl: 4 }"
|
||||
:data-source="conferenceList"
|
||||
:loading="loading"
|
||||
class="conference-list-content"
|
||||
v-infinite-scroll="loadMore"
|
||||
:infinite-scroll-disabled="disabled"
|
||||
:infinite-scroll-distance="10"
|
||||
>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
<a-card :title="item.name" :bordered="false" class="conference-card">
|
||||
<template #cover>
|
||||
<img
|
||||
alt="会议室图片"
|
||||
:src="item.image || '/placeholder-image.jpg'"
|
||||
style="height: 200px; object-fit: cover;"
|
||||
/>
|
||||
</template>
|
||||
<a-card-meta :title="item.name">
|
||||
<template #description>
|
||||
<div class="conference-info">
|
||||
<p>容纳人数:{{ item.capacity }}人</p>
|
||||
<p>位置:{{ item.location }}</p>
|
||||
<p>设备:{{ item.facilities }}</p>
|
||||
</div>
|
||||
</template>
|
||||
</a-card-meta>
|
||||
<div class="card-actions">
|
||||
<a-button type="primary" @click="handleReservation(item)">
|
||||
去预约
|
||||
</a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</div>
|
||||
<div>会议室预约</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { requestClient } from '../../../../api/request';
|
||||
|
||||
interface ConferenceRoom {
|
||||
id: string;
|
||||
name: string;
|
||||
capacity: number;
|
||||
location: string;
|
||||
facilities: string;
|
||||
image?: string;
|
||||
}
|
||||
|
||||
const pageSize = 20;
|
||||
const currentPage = ref(1);
|
||||
const loading = ref(false);
|
||||
const conferenceList = ref<ConferenceRoom[]>([]);
|
||||
const noMore = ref(false);
|
||||
|
||||
const disabled = computed(() => loading.value || noMore.value);
|
||||
|
||||
const fetchConferenceList = async (page: number) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await requestClient.get<{
|
||||
list: ConferenceRoom[];
|
||||
total: number;
|
||||
}>('/property/conference/list', {
|
||||
params: {
|
||||
pageSize,
|
||||
pageNum: page,
|
||||
},
|
||||
});
|
||||
|
||||
if (page === 1) {
|
||||
conferenceList.value = res.list;
|
||||
} else {
|
||||
conferenceList.value = [...conferenceList.value, ...res.list];
|
||||
}
|
||||
|
||||
noMore.value = conferenceList.value.length >= res.total;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const loadMore = async () => {
|
||||
if (disabled.value) return;
|
||||
currentPage.value++;
|
||||
await fetchConferenceList(currentPage.value);
|
||||
};
|
||||
|
||||
const handleReservation = (room: ConferenceRoom) => {
|
||||
// TODO: 实现预约逻辑
|
||||
console.log('预约会议室:', room);
|
||||
};
|
||||
|
||||
// 初始加载
|
||||
fetchConferenceList(1);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.conference-list {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.conference-list-content {
|
||||
height: calc(100vh - 120px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.conference-card {
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.conference-info {
|
||||
p {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
margin-top: 16px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script></script>
|
||||
<style lang="scss"></style>
|
Loading…
Reference in New Issue
Block a user