在vue中element-ui使用表格并创建多组件弹窗并实现数据增删改查

表格数据的增删改查代码

实现组件化开发;分为根组件、子组件(查询组件、表格组件、新增编辑组件、详情组件)

index.vue 
<template>
	<!-- etDeviceLease/et-equipmentLeaseReturn/index  租赁归还 -->
	<div class="layout-padding">
		<div class="layout-padding-auto layout-padding-view">
			<equipment-return-seach
			    ref="queryRef" 
				:isLoading="isLoading" 
				:showSearch="showSearch" 
				:selectObjs="selectObjs"  
				:multiple="multiple" 
				@resetQuery="resetQuery"
				@checkUp="getData" 
			></equipment-return-seach>

			<equipment-return-page
				@handleDelete="handleDelete"
				:formDialogRef="formDialogRef"
				:detailDialogRef="detailDialogRef"
				@selectionChangHandle="selectionChangHandle"
				@handleShow="handleShow" 
				:dataList="state.dataList"
			>
			
			    <template v-slot:pagination> 
					<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
				</template>
		    </equipment-return-page>
		</div>

		<!-- 编辑、新增  -->
		<equipment-return-card ref="formDialogRef" @refresh="getDataList(false)" />
		<el-dialog v-model="dialogVisible" :title="'租赁单查看'" :close-on-click-modal="false" draggable> 
			<detail-card ref="formDetailRef" :dialogVisibleType="dialogVisible" :data-id="dataId" />
			<!-- <template #footer>
					<span class="dialog-footer">
						<el-button type="primary">发起流程</el-button>
					</span>
				</template> -->
		</el-dialog>
	</div>
</template>

<script setup lang="ts" name="systemEtFaultExperience"> 
import * as archives from '/@/api/archives/et-archives';  
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList, delObjs } from "/@/api/equipment/etDeviceLeaseReturn";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useDict } from '/@/hooks/dict';
// 引入组件
const equipmentReturnPage = defineAsyncComponent(() => import('./equipmentReturnPage.vue')); 
const DetailCard = defineAsyncComponent(() => import('./detailCard.vue'));
const equipmentReturnSeach = defineAsyncComponent(() => import('./equipmentReturnSeach.vue'));
const equipmentReturnCard = defineAsyncComponent(() => import('./equipmentReturnCard.vue'));  
 
// 定义查询字典

// 定义变量内容
const formDialogRef = ref(null);
const detailDialogRef = ref(null);
// 搜索变量
const queryRef = ref(null);
const showSearch = ref(true);
// 多选变量
const selectObjs = ref([]) as any;
const multiple = ref(true);
// 定义懒加载
const options = ref([]);
const isLoading = ref(false);
const hasMore = ref(true); // 判断是否还有更多数据 
const pageSize = ref(20); // 每次加载的数量
const currentPage = ref(1); // 当前页数

const state: BasicTableProps = reactive<BasicTableProps>({
	queryForm: {},
	pageList: fetchList,
}); 
//  table hook
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state);

// 清空搜索条件
const resetQuery = (e) => {
	state.queryForm = e;
	//  清空多选
	selectObjs.value = [];
	options.value = []; // 重置选项
	isLoading.value = false;
	hasMore.value = true;
	currentPage.value = 1; // 如果有分页逻辑,重置当前页 
	queryRef.value?.resetFields();
	getDataList();
};
 

// 点击查询
const getData = (e) => {
	state.queryForm = e; 
	getDataList();
};
// 导出excel
const exportExcel = () => {
	downBlobFile('/equipment/etFaultExperience/export', Object.assign(state.queryForm, { ids: selectObjs }), 'etFaultExperience.xlsx');
};

// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
	selectObjs.value = objs.map(({ id }) => id);
	multiple.value = !objs.length;
};
 
const dataId = ref();
const billStatus = ref();
const nodeStatus = ref();
const createBy = ref();
const dialogVisible = ref();

// 查看
function handleShow(row) {
	dataId.value = row.id;
	billStatus.value = row.billStatus;
	nodeStatus.value = row.status;
	createBy.value = row.createBy;
	dialogVisible.value = true;
}
 

// 删除操作
const handleDelete = async (ids: string[]) => {
	try {
		await useMessageBox().confirm('此操作将永久删除');
	} catch {
		return;
	}

	try {
		await delObjs(ids); 
		useMessage().success('删除成功');
		getDataList();
	} catch (err: any) {
		useMessage().error(err.msg);
	}
};
</script>
equipmentReturnSeach.vue

实现表格查询,重置表格选项

<template>
	<el-row  >
		<el-form :model="state.queryForm" label-width="90px" ref="queryRef" :inline="true" @keyup.enter="getDataList">
			<el-col :span="24">
				<el-form-item label="归还编号:" prop="leaseReturnNum">
					<el-input placeholder="请输入归还编号" v-model="state.queryForm.leaseReturnNum" />
				</el-form-item>
				<el-form-item label="归还名称:" prop="leaseReturnName">
					<el-input placeholder="请输入归还名称" v-model="state.queryForm.leaseReturnName" />
				</el-form-item>
				<el-form-item label="归还方" prop="tenantry">
					<el-input v-model="state.queryForm.tenantry" placeholder="请输入归还方" />
				</el-form-item>
				<el-form-item label="联系方式" prop="tenantryPhone">
					<el-input v-model="state.queryForm.tenantryPhone" placeholder="请输入联系方式" />
				</el-form-item>
				<el-form-item label="设备名称:" prop="archives">
					<el-input placeholder="请输入设备名称" v-model="state.queryForm.archives" />
				</el-form-item> 
				
				<el-form-item label="归还时间:" prop="startTime">
					<el-date-picker
						format="YYYY-MM-DD"
						value-format="YYYY-MM-DD HH:mm:ss"
						placeholder="租赁时间"
						style="width: 220px !important; text-align: left !important"
						v-model="value1"
						editable
						type="daterange"
						range-separator="-"
						start-placeholder="开始日期"
						end-placeholder="结束日期"
						
					/> 
				</el-form-item> 
				<el-form-item label="审批状态:" prop="billStatus">
					<el-select v-model="state.queryForm.billStatus" filterable clearable placeholder="请选择审批状态">
						<el-option v-for="item in DIC_PROP.ORDER_STATUS" :key="item.value" :label="item.label" :value="item.value"></el-option>
					</el-select>
				</el-form-item>
				<el-form-item label="">
					<el-button style="margin-left: 2rem" icon="Search" type="primary" v-auth="'equipment_etDeviceLease_view'" @click="checkUp">{{
						$t('common.queryBtn')
					}}</el-button>
					<el-button icon="Refresh" v-auth="'equipment_etDeviceLease_view'" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
				</el-form-item>
			</el-col>
		</el-form>
	</el-row>
</template>

<script setup lang="ts">
import { reactive, ref, defineProps, defineEmits, onMounted } from 'vue'; 
import { DIC_PROP } from '/@/flow/support/dict-prop'; 
const state = reactive({
	queryForm: {
		// equipmentName: '',
		// planNum: '',
		// planName: '',
		// planTypeCode: '',
		// billStatus: '',
		// planStart: '',
		// planEnd: '',
		// items: [],
	},
});
const emit = defineEmits(['getDataList', 'checkUp']);
const value1 = ref([]);
const getDataList = async (value: any) => {
	emit('getDataList');
};
const checkUp = async (value: any) => { 
	if (Array.isArray(value1.value) && value1.value.length !== 0) { 
		//  修改时间
		state.queryForm.leaseReturnStartTime = value1.value[0] ; //租赁归还开始时间
		state.queryForm.leaseReturnEndTime = value1.value[1]; //租赁归还结束时间
	}  else {
		state.queryForm.leaseReturnStartTime  = ''; //租赁归还开始时间
		state.queryForm.leaseReturnEndTime = ''; //租赁归还结束时间
	}
	emit('checkUp', state.queryForm);
};
 
// 搜索变量
const queryRef = ref();
// 多选变量
const selectObjs = ref([]) as any;
// 清空搜索条件
const resetQuery = () => {
	// 清空搜索条件
	queryRef.value?.resetFields();
	state.queryForm = {};
	// 清空多选
	selectObjs.value = [];
	value1.value=[]
	emit('checkUp', {});
}; 
 
</script>
<style scoped></style>

equipmentReturnPage.vue

实现点击编辑弹窗出现,点击删除判断删除权限 进行删除,使用sort具名插槽放置分页组件,点击查看显示弹窗数据回显展示,点击新增和编辑使用同一弹窗组件

<template>
	<div class="mb8" style="width: 100%">
		<el-button icon="folder-add" type="primary" class="ml10" @click="props.formDialogRef.openDialog()" v-auth="'equipment_etDeviceLeaseReturn_add'">
			新 增
		</el-button>
		<el-button plain :disabled="multiple" icon="Delete" type="primary" v-auth="'equipment_etDeviceLeaseReturn_del'" @click="handleDelete(selectObjs)">
			删除
		</el-button>
	</div>
	<el-table
		:data="dataList"
		v-loading="vLoading"
		:cell-style="cellStyle"
		:header-cell-style="headerCellStyle"
		@selection-change="selectionChangHandle"
		@sort-change="sortChangeHandle"
	>
		<el-table-column type="selection" width="40" align="center" />
		<!-- <el-table-column type="index" label="#" width="40" /> -->
		<el-table-column prop="leaseReturnNum" label="归还编号" show-overflow-tooltip />
		<el-table-column prop="leaseReturnName" label="归还名称" show-overflow-tooltip />
		<el-table-column prop="archives" label="设备名称" show-overflow-tooltip />

		<el-table-column prop="tenantry" label="归还方" show-overflow-tooltip />
		<el-table-column prop="tenantryPhone" label="归还方联系方式" show-overflow-tooltip /> 
		<el-table-column prop="leaseReturnTime" label="归还时间" show-overflow-tooltip />
		<el-table-column prop="remarks" label="归还说明" show-overflow-tooltip />
		<el-table-column prop="billStatus" label="业务审批状态" show-overflow-tooltip>
			<template #default="scope">
				<dict-tag
					:options="DIC_PROP.ORDER_STATUS"
					:value="scope.row.billStatus"
					:elTagStyle="{
						color: orderStatusItem(scope.row) ? orderStatusItem(scope.row).color : '',
						'border-color': orderStatusItem(scope.row) ? orderStatusItem(scope.row).color : '',
						'background-color': '#fff',
					}"
				></dict-tag>
			</template>
		</el-table-column> 
		<el-table-column label="操作" width="200">
			<template #default="scope"> 
				<el-button
					icon="edit-pen"
					text
					type="primary"
					@click="formDialogRef.openDialog(scope.row.id)"
					v-if="editShow(scope)"
					v-auth="'equipment_etDeviceLeaseReturn_edit'"
					>编辑</el-button
				>
				<el-button icon="el-icon-search" text type="primary" v-auth="'equipment_etDeviceLeaseReturn_view'" @click="handleShow(scope.row)">查看</el-button>
				<el-button
					icon="delete"
					v-auth="'equipment_etDeviceLeaseReturn_del'"
					v-if="delShow(scope)" 
					text
					type="primary"
					@click="handleDelete([scope.row.id])"
					>删除</el-button
				> 
			</template>
		</el-table-column>
	</el-table>
	<slot name="pagination"></slot>
</template>

<script setup lang="ts">
import { reactive, ref, defineProps, defineEmits, onMounted } from 'vue';   
import { useMessage, useMessageBox } from '/@/hooks/message';
import { DIC_PROP } from '/@/flow/support/dict-prop';

const props = defineProps({
	dataList: {
		type: Array,
		default: [
			{
				id: '',
				leaseReturnName: '',
				leaseReturnNum: '',
				flowKey: '',
				flowInstId: '',
				leaseReturnTime: '2024-12-12',
				leaseId: '',
				remarks: '',
				billStatus: '',
				chargeDeptId: '',
				userId: '',
				deptId: '',
				revision: '',
				createBy: '',
				createTime: '2024-12-12T09:48:10.605Z',
				updateBy: '',
				updateTime: '2024-12-12T09:48:10.605Z',
				delFlag: '',
				tenantId: '',
			},
		],
	},
	vLoading: {
		type: String,
		default: 'false',
	},
	cellStyle: {
		type: Object,
	},
	headerCellStyle: {
		type: Object,
	},
	pagination: {
		type: Object,
	},
	formDialogRef: {
		type: Object,
		required: true, 
	},
	lastParam: {
		type: String,
		default: '0',
	},
	userId: {
		type: String,
	},
});
// 多选变量
const selectObjs = ref([]) as any;
const multiple = ref(true);
// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
	selectObjs.value = objs.map(({ id }) => id);
	multiple.value = !objs.length;
};
const emit = defineEmits(['handleDelete', 'sortChangeHandle', 'handleShow']);
const sortChangeHandle = () => {
	emit('sortChangeHandle');
};

const orderStatusItem = computed(() => {
	return (row) => {
		return DIC_PROP.ORDER_STATUS.find((item) => item.value === row.billStatus);
	};
});

const editShow = (scope) => {
	// 当前状态为未发起时 任何人都可以删除修改
	if (scope.row.billStatus === '-2') {
		return true;
	} else {
		// 当前用户为创建人且当前状态为办理中、被驳回时,可以修改
		if ((scope.row.status === '0' || scope.row.status === '9') && props.userId == scope.row.createBy) {
			return true;
		}
	}
	return false;
};
const delShow = (scope) => {
	return scope.row.billStatus === '-2';
};
// 删除操作
const handleDelete = async (ids: string[]) => {
	emit('handleDelete', ids);
};

function handleShow(row) {
	emit('handleShow', row);
}
onMounted(() => {
	console.log(props.formDialogRef, 'page');
});
</script>


equipmentReturnCard.vue 新增、编辑弹窗(使用同一组件)

  点击编辑调用openDialog(id) 函数传参,点击新增调用openDialog()函数,判断id是否存在,true:编辑,false:新增

  实现编辑数据回显 id存在,调用接口请求数据,再次打开弹框,表单数据清空

// 重置表单数据

    nextTick(() => {

        dataFormRef.value?.resetFields();

    })

<template>
	<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible" :close-on-click-modal="false" draggable width="60%">
		<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="110px">
			<el-row :gutter="24">
				<el-col :span="8" class="mb20">
					<el-form-item label="归还名称" prop="leaseReturnName">
						<el-input v-model="form.leaseReturnName" placeholder="请输入租赁名称" />
					</el-form-item>
				</el-col>

				<el-col :span="8" class="mb20">
					<el-form-item label="归还方" prop="tenantry">
						<el-select v-model="form.tenantry" clearable filterable placeholder="请选择归还人" @change="userChange">
							<el-option v-for="item in userList" :key="item.tenantry" :label="item.tenantry" :value="item.tenantry" />
						</el-select>
					</el-form-item>
				</el-col>
				<el-col :span="8" class="mb20">
					<el-form-item label="联系方式" prop="tenantryPhone">
						<el-input v-model="form.tenantryPhone" placeholder="归还方联系方式" type="tel" />
					</el-form-item>
				</el-col>

				<el-col :span="8" class="mb20">
					<el-form-item label="归还时间" prop="leaseReturnTime">
						<el-date-picker v-model="form.leaseReturnTime" value-format="YYYY-MM-DD HH:mm:ss" type="date" placeholder="选择归还时间">
						</el-date-picker>
					</el-form-item>
				</el-col>
				<el-col :span="16" class="mb20">
					<el-form-item label="归还说明" prop="remarks">
						<el-input v-model="form.remarks" placeholder="请输入归还说明" />
					</el-form-item>
				</el-col>
				<el-col :span="8">
					<el-upload
						class="upload-demo"
						action="/api/equipment/minio/upload"
						:headers="uploadHeaders"
						:file-list="form.deviceLeaseReturnFileEntityList"
						list-type="text"
						:on-remove="handleFileRemove"
						:on-success="handleFileSuccess"
						:auto-upload="true"
						:before-upload="beforeFileUpload"
						multiple
						:limit="10"
					>
						<el-button icon="folder-add" type="primary" class="ml10" v-auth="'pigx_etDeviceLeaseFile_add'"> 上传文件 </el-button>
					</el-upload>
				</el-col>
			</el-row>
		</el-form>

		<el-form ref="dataFormRefs" :model="form.deviceLeaseEntity" :rules="dataRule" formDialogRef label-width="120px">
			<el-row>
				<el-col :span="7" class="mb20">
					<el-form-item label="租赁编号:" prop="leaseNum">
						<el-select
							@change="receiveChange"
							clearable
							filterable
							v-model="form.deviceLeaseEntity.leaseNum"
							value-key="id"
							placeholder="请选择领用编号"
						>
							<el-option v-for="item in userListAll" :key="item.id" :label="item.leaseNum" :value="item.leaseNum"></el-option>
						</el-select>
					</el-form-item>
				</el-col>
				<el-col :span="5" class="mb20">
					<el-form-item label="开始时间:" prop="startTime">
						{{ form.deviceLeaseEntity.startTime }}
					</el-form-item>
				</el-col>
				<el-col :span="5" class="mb20">
					<el-form-item label="结束时间:" prop="endTime">
						{{ form.deviceLeaseEntity.endTime }}
					</el-form-item>
				</el-col>
				<el-col :span="5" class="mb20">
					<el-form-item label="时长:" prop="duration">
						{{ form.deviceLeaseEntity.duration ? form.deviceLeaseEntity.duration + '天' : '---天' }}
					</el-form-item>
				</el-col>
			</el-row>
		</el-form>
		<el-row>
			<el-col :span="24" class="mb20"> 
				<el-table
					ref="tableRefs"
					:data="form.deviceLeaseDetailEntityList"
					border
					:cell-style="tableStyle.cellStyle"
					@selection-change="selectionChangHandle"
					:header-cell-style="tableStyle.headerCellStyle"
					:row-key="(row) => row.leaseId"
				>
					<el-table-column type="selection" label="#" width="40" align="center" />
					<el-table-column prop="equipmentNum" label="设备编号" show-overflow-tooltip />
					<el-table-column prop="equipmentName" label="设备名称" show-overflow-tooltip />
					<el-table-column prop="specificationModel" label="规格型号" show-overflow-tooltip />
					<el-table-column prop="typeName" label="设备类型" show-overflow-tooltip />
					<el-table-column prop="assetCategoryName" label="资产类型" show-overflow-tooltip />
					<el-table-column prop="buyPrice" label="设备原值" show-overflow-tooltip />
					<el-table-column prop="leasePrise" label="租赁价格" show-overflow-tooltip />
					<el-table-column prop="depreciationPrise" label="折旧价格" show-overflow-tooltip>
						<template #default="{ row }">
							<el-input type="number" v-model="row.depreciationPrise" placeholder="请输入折旧价格" />
						</template>
					</el-table-column>
				</el-table>
			</el-col>
		</el-row>
		<template #footer>
			<span class="dialog-footer">
				<el-button @click="visible = false">取消</el-button>
				<el-button type="primary" v-if="isShowInitiateProcess" @click="initiateProcess" :disabled="loading">确认并发起流程</el-button>
				<el-button type="primary" @click="onSubmit" :disabled="loading">确认</el-button>
			</span>
		</template>
	</el-dialog>
</template>

<script setup lang="ts" name="equipmentReturnCard">
import { useMessage, useMessageBox } from '/@/hooks/message';
//  updateStartWorkFlow, startWorkFlow
import { getObj, addObj, putObj, updateStartWorkFlow, startWorkFlow } from '/@/api/equipment/etDeviceLeaseReturn';
import { ref, reactive, nextTick } from 'vue';
import { BasicTableProps, useTable } from '/@/hooks/table';
import { rule as rules } from '/@/utils/validate';
import { Session } from '/@/utils/storage';
import { getAllTenantry, getAllByTenantry } from '/@/api/equipment/etDeviceLease';
import _ from 'lodash';

const emit = defineEmits(['refresh']);

const state: BasicTableProps = reactive<BasicTableProps>({
	queryForm: {},
	dataList: [],
});
// table hook
const { tableStyle } = useTable(state);
// 定义变量内容
const dataFormRef = ref();
const dataFormRefs = ref();
const visible = ref(false);
const loading = ref(false);
const tableRefs = ref();

const isShowInitiateProcess = ref(true);

// 出租归还方
const tenantry = ref('');
const userList = ref([]);
// 租赁数据
const userListAll = ref([]);
// 定义表单数据模型
const form = reactive<{
	id: string;
	leaseReturnName: string;
	leaseReturnNum: string;
	flowKey: string;
	flowInstId: string;
	leaseReturnTime: string;
	leaseReturnStartTime: string;
	leaseReturnEndTime: string;
	leaseId: string;
	remarks: string;
	billStatus: string;
	chargeDeptId: string;
	userId: string;
	deptId: string;
	revision: string;
	createBy: string;
	createTime: string;
	updateBy: string;
	updateTime: string;
	delFlag: string;
	tenantId: string;
	archives: string;
	tenantry: string;
	tenantryPhone: string;
	deviceLeaseEntity: Object;
	deviceLeaseDetailEntityList: {}[];
	deviceLeaseReturnDetailEntityList: {}[];
	deviceLeaseReturnFileEntityList: {}[];
}>({
	id: '',
	leaseReturnName: '',
	leaseReturnNum: '',
	flowKey: '',
	flowInstId: '',
	leaseReturnTime: '',
	leaseReturnStartTime: '',
	leaseReturnEndTime: '',
	leaseId: '',
	remarks: '',
	billStatus: '',
	chargeDeptId: '',
	userId: '',
	deptId: '',
	revision: '',
	createBy: '',
	createTime: '',
	updateBy: '',
	updateTime: '',
	delFlag: '',
	tenantId: '',
	archives: '',
	tenantry: '',
	tenantryPhone: '',
	deviceLeaseEntity: {},
	deviceLeaseDetailEntityList: [],
	deviceLeaseReturnDetailEntityList: [],
	deviceLeaseReturnFileEntityList: [],
});
//选中编号的数据 归还数据
// const form.deviceLeaseEntity = ref({});
//选择归还人处理函数
const userChange = async (value) => {
	let arr = await getAllByTenantry(value);
	userListAll.value = arr.data;
	form.deviceLeaseEntity = {};
	form.tenantry = value;
};

//选择租赁编号时获取tableData数据
const receiveChange = async (value) => {
	form.deviceLeaseEntity = userListAll.value.find((x, y) => {
		return x.leaseNum === value;
	});
	// 计算天数
	calculateDuration(form.deviceLeaseEntity.startTime, form.deviceLeaseEntity.endTime);
	form.leaseId = form.deviceLeaseEntity.id;
	// 表格数据
	form.deviceLeaseDetailEntityList = JSON.parse(JSON.stringify(form.deviceLeaseEntity.archivesList));
};

// 多选变量
const selectObjs = ref([]) as any;
const multiple = ref(true);
// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
	selectObjs.value = objs.map((item) => item);
	multiple.value = !objs.length;
};

//文件上传
const handleFileRemove = async (file: any, fileLists: Ref<[]>) => {
	const transformedArray = fileLists.forEach((x) => ({
		fileUrl: x.fileUrl,
		fileId: x.uid,
	}));
	form.deviceLeaseReturnFileEntityList = transformedArray;
};

// 设备档案文档
const handleFileSuccess = async (response: any, file: any, files: Ref<[]>) => {
	// 上传成功后的回调,可以更新后端返回的文件信息到本地state
	if (response.code == 1) {
		useMessage().error(response.msg);
	} else {
		form.deviceLeaseReturnFileEntityList?.push({
			fileUrl: response.data.url,
			fileId: response.data.id,
		});
	}
};
const beforeFileUpload = (file: File) => {
	// 获取文件扩展名
	const fileExtension = file.name.split('.').pop();

	// 允许上传的文件扩展名列表
	const acceptableExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'txt', 'rar'];

	// 判断文件扩展名是否在允许的列表中
	if (!acceptableExtensions.includes(fileExtension.toLowerCase())) {
		useMessage().error(`只能上传PDF、.doc、.docx、.xls、.xlsx、.txt、.rar格式的文件!`);
		return false;
	}

	// 这里还可以添加其他条件判断,如文件大小限制等
	return true;
};

// 计算租赁时长
const calculateDuration = (startTime: string, endTime: string) => {
	// 新增
	let start = new Date(startTime);
	let end = new Date(endTime);
	const timeDiff = end - start;
	const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数
	return Math.floor(timeDiff / oneDay) ? Math.floor(timeDiff / oneDay) : '---';
};

// 打开弹窗
const openDialog = (id: string) => {
	visible.value = true;
	form.id = '';
	userList.value = [];
	form.deviceLeaseReturnFileEntityList = [];
	(form.deviceLeaseEntity = {}), (form.deviceLeaseDetailEntityList = []), (form.deviceLeaseReturnDetailEntityList = []), (userListAll.value = []);

	form.value = _.clone({});
	// 获取所有承租方
	getAllTenantry(tenantry.value).then((res) => {
		userList.value = res.data;
	});
	// 重置表单数据
	nextTick(() => {
		dataFormRef.value?.resetFields();
	});

	// 获取etCheckItemPlan信息
	if (id) {
		form.id = id;
		getetDeviceLeaseData(id);
	}
};

// 初始化表单数据
const getetDeviceLeaseData = (id: string) => {
	// 获取数据
	loading.value = true;
	getObj(id)
		.then((res: any) => {
			Object.assign(form, res.data);
			form.tenantry = form.deviceLeaseEntity.tenantry;
			form.tenantryPhone = form.deviceLeaseEntity.tenantryPhone;
			form.leaseReturnTime = form.leaseReturnTime + ' 00:00:00';
			form.deviceLeaseReturnFileEntityList.forEach((item) => {
				item.name = item.fileName 
			});

			// 回显所有表格数据
			getAllByTenantry(form.tenantry)
				.then(async (result) => {
					userListAll.value = result.data; 
					// receiveChange(form.deviceLeaseEntity.leaseNum);

					setTimeout(() => {
						handleSetValue(form.deviceLeaseDetailEntityList, form.deviceLeaseReturnDetailEntityList);
					}, 800);
				})
				.catch((err) => {});  
			isShowInitiateProcess.value = res.data.billStatus === '-2';
		})
		.finally(() => {
			loading.value = false; 
		});
};

function handleSetValue(arr, list) {
	console.log('list', list);
	list = list.map((item) => item.archivesId);

	if (arr) {
		arr.forEach((item, index) => {
			if (list.includes(item.archivesId)) { 
				form.deviceLeaseReturnDetailEntityList.forEach((x,y) => { 
					
					if (item.archivesId === x.archivesId) {
						console.log(y);
						
						item.depreciationPrise = x.depreciationPrise
					}
				});
				tableRefs.value.toggleRowSelection(item, true); 
			} else {
				tableRefs.value.toggleRowSelection(item, false);
			}
		});
	} else {
		tableRefs.value.clearSelection();
	}
}
// 提交
const onSubmit = async () => {
	const valid = await dataFormRef.value.validate().catch(() => {});
	if (!valid) {
		console.log('校验失败valid');
		return false;
	}
	const valids = await dataFormRefs.value.validate().catch(() => {});
	if (!valids) {
		console.log('校验失败valids');
		return false;
	}

	// 选中的归还设备
	let selectList = selectObjs.value.length;
	if (!selectList) {
		useMessage().error('请选择归还设备');
		return false;
	}

	let isvalid = true;
	// 校验价格是否填写
	selectObjs.value.some((item) => {
		if (item.depreciationPrise === null || item.depreciationPrise === undefined) {
			useMessage().error('请输入折旧价格');
			return (isvalid = false); // 停止循环
		} else if (item.depreciationPrise < 0) {
			useMessage().error('折旧价格不能小于0');

			return (isvalid = false); // 停止循环
		}
	});
	if (!isvalid) return false;

	try {
		// // 归还设备数据
		form.deviceLeaseReturnDetailEntityList = _.cloneDeep(selectObjs.value);
		// 	租赁设备集合
		form.deviceLeaseDetailEntityList=== null?	form.deviceLeaseDetailEntityList = _.cloneDeep(form.deviceLeaseEntity.archivesList) :form.deviceLeaseDetailEntityList;
		form.deviceLeaseEntity.tenantry = form.tenantry;

		loading.value = true;
		const responseData = form.id ? await putObj(form) : await addObj(form);

		useMessage().success(form.id ? '修改成功' : '添加成功');
		visible.value = false;
		emit('refresh');
		return true;
	} catch (err: any) {
		useMessage().error(err.msg);
	} finally {
		loading.value = false;
	}
	return false;
};

// 发起流程
const initiateProcess = async () => {
	const yesOrNo = await onSubmit();
	console.log(yesOrNo, 'yesOrNo');

	if (yesOrNo) {
		loading.value = true;
		await updateStartWorkFlow({ id: form.id }).then((response) => {
			startWorkFlow(response.data).then((res) => {
				loading.value = false;
				if (res.code === 0) {
					useMessage().success('发起成功');
				} else {
					useMessage().error('发起失败,请联系管理员!');
				}
				loading.value = false;
				visible.value = false;
				emit('refresh');
			});
		});
	}
};

// 定义校验规则
const dataRules = ref({
	leaseReturnName: [{ required: true, message: '归还名称不能为空', trigger: 'blur' }],
	tenantry: [{ required: true, message: '归还方不能为空', trigger: 'blur' }],
	leaseReturnTime: [{ required: true, message: '请选择归还时间', trigger: 'blur' }],
	tenantryPhone: [
		{ required: true, message: '请输入联系方式', trigger: 'blur' },
		{
			validator: (rule, value, callback) => {
				rules.validatePhone(rule, value, callback);
			},
			trigger: 'blur',
		},
	],
});

const dataRule = ref({
	leaseNum: [{ required: true, message: '请选择租赁编号', trigger: 'blur' }],
});
// 暴露变量
defineExpose({
	openDialog,
});

const uploadHeaders = ref({});
onMounted(() => {
	// 图片上传
	uploadHeaders.value = {
		Authorization: 'Bearer ' + Session.get('token'),
		'TENANT-ID': Session.getTenant(),
	};
});
</script>
<style scoped>
:deep(.el-collapse-item__header) {
	font-size: 18px !important; /* 添加 '!important' 来提高样式的优先级 */
	font-weight: 500; /* 如果需要加粗也可以在这里设置 */
}

:deep(.el-select__selection.is-near) {
	flex-wrap: nowrap !important;
}

:deep(.el-select .el-select-tags-wrapper.has-prefix) {
	margin-left: 0px;
}
:deep(.el-select__tags) {
	margin-left: 2px;
}
.custom-popper {
	max-height: 1000px; /* 设置最大高度 */
	overflow-y: auto; /* 添加滚动条 */
}
</style> 

detailCard.vue

点击查看-tab展示数据、工作流状态、上传文档展示、文件下载

<template>
	<div>
		<el-tabs v-model="activeName">
			<el-tab-pane label="租赁信息" name="first">
				<el-form :model="form" label-width="120px" ref="queryRef" :inline="true"> 
					<el-row :gutter="12">
						<el-col :span="8">
							<el-form-item label="归还名称:" prop="leaseName">
								{{ form.leaseReturnName }}
							</el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="归还方:" prop="lessor">
								{{ form.deviceLeaseEntity?.tenantry }}
							</el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="联系方式:" props="tenantryPhone"> {{ form.deviceLeaseEntity?.tenantryPhone }} </el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="归还时间:" prop="leaseReturnTime"> {{ form.leaseReturnTime}} </el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="归还说明:" prop="remarks"> {{ form.remarks }} </el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="租赁编号:" prop="leaseNum"> {{  form.deviceLeaseEntity?.leaseNum }} </el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="开始时间:" prop="startTime"> {{ form.deviceLeaseEntity?.startTime }} </el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="结束时间:" prop="endTime">{{ form.deviceLeaseEntity?.endTime }}</el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="时长:" prop="duration">
								{{ calculateDuration(form.deviceLeaseEntity?.startTime, form.deviceLeaseEntity?.endTime)? calculateDuration(form.deviceLeaseEntity.startTime, form.deviceLeaseEntity.endTime)+'天' :'---' }}
								<!-- {{  form.duration+ '天'  }} -->
							</el-form-item>
						</el-col>
					</el-row>
				</el-form>
				<el-table
					ref="tableRefs"
					:data="form.deviceLeaseReturnDetailEntityList"
					border
					:cell-style="tableStyle.cellStyle" 
					:header-cell-style="tableStyle.headerCellStyle"
				>
					<el-table-column prop="equipmentNum" label="设备编号" show-overflow-tooltip />
					<el-table-column prop="equipmentName" label="设备名称" show-overflow-tooltip />
					<el-table-column prop="specificationModel" label="规格型号" show-overflow-tooltip />
					<el-table-column prop="typeName" label="设备类型" show-overflow-tooltip />
					<el-table-column prop="assetCategoryName" label="资产类型" show-overflow-tooltip />
					<el-table-column prop="buyPrice" label="设备原值" show-overflow-tooltip />
					<el-table-column prop="leasePrise" label="租赁价格" show-overflow-tooltip />
					<el-table-column prop="depreciationPrise" label="折旧价格" show-overflow-tooltip />
				</el-table>
				<!-- <Equipment :form="viewDeviceReceiveDetailList" :loading="isLoading"></Equipment> -->
				<!-- <Equipment :form="form.archivesList"></Equipment> -->
			</el-tab-pane>
			<el-tab-pane label="关联文档" name="text">     
					<div class="fileDiv" v-if="form.deviceLeaseReturnFileEntityList?.length">
						<div class="fileView" v-for="(item, index) in form.deviceLeaseReturnFileEntityList" :key="item.fileUrl">
							<template v-if="item.fileSuffix === 'doc' || item.fileSuffix === 'word'">
								<img style="width: 4rem" src="/@/assets/word.png" alt="" />
							</template>
							<template v-else-if="item.fileSuffix === 'xls' || item.fileSuffix === 'xlsx'">
								<img style="width: 4rem" src="/@/assets/excel.png" alt="" />
							</template>
							<template v-else-if="item.fileSuffix === 'txt'">
								<img style="width: 4rem" src="/@/assets/txt.png" alt="" />
							</template>

							<template v-else-if="item.fileSuffix === 'pdf'">
								<img style="width: 4rem" src="/@/assets/pdf.png" alt="" />
							</template>

							<template v-else-if="item.fileSuffix === 'ppt'">
								<img style="width: 4rem" src="/@/assets/ppt.png" alt="" />
							</template>

							<text class="fileName">{{ item.fileName }}</text>
							<dl class="fileData">
								<dd>文件类型: {{ item.fileSuffix }}</dd>
								<dd>大小: {{ parseInt(item.fileSize, 10) / 1024 / 1024 }} MB</dd>
								<dd>上传人:{{ item.userName }}</dd>
								<dd>
									<text>{{ item.createdTime ? formatDate(item.createdTime) : '' }}</text>
									<el-button type="primary" size="small" @click="unload(item)" style="margin-left: 10px"> 下载</el-button>
								</dd>
							</dl>
						</div>
					</div>
					<div v-else style="padding: 60px 0">
						<el-empty :image-size="80" description="还没有文件哦,快去上传吧!" />
					</div> 
			</el-tab-pane>
			<el-tab-pane label="查看审批流程" name="third" v-if="props.showExamineAndApprove">
				<flow :currJob="{ flowInstId: form.flowInstId, flowKey: form.flowKey }"></flow>
			</el-tab-pane>
			<!-- <el-tab-pane label="查看流程图" name="tu"> 查看流程图 </el-tab-pane> -->
		</el-tabs>
	</div>
</template>

<script setup lang="ts" name="EtUpkeepItemDialog"> 
import { useMessage } from '/@/hooks/message';
import { getObj ,getByFlowInstId } from '/@/api/equipment/etDeviceLeaseReturn';  
import { BasicTableProps, useTable } from '/@/hooks/table';
import { downloadFile } from '/@/components/downloadFile/downloadFile'; // 导入封装的下载文件方法
const emit = defineEmits(['refresh']);
const flow = defineAsyncComponent(() => import('/@/views/jsonflow/comment/flow.vue'));  


const state: BasicTableProps = reactive<BasicTableProps>({
	queryForm: {},
	dataList: [],
});
// table hook
const { tableStyle } = useTable(state);
// 定义变量内容
const dataFormRef = ref();
const visible = ref(false);
const loading = ref(false);
const activeName = ref('first');
// 计算租赁时长
const calculateDuration = (startTime: string, endTime: string) => {
	// 新增
	let start = new Date(startTime);
	let end = new Date(endTime);
	const timeDiff = end - start;
	const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数
	return Math.floor(timeDiff / oneDay) ? Math.floor(timeDiff / oneDay) : '---';
};

// 下载文件
const unload = (e) => {
    let { fileName ,fileUrl} =e
	downloadFile(fileUrl, fileName)
};
// 提交表单数据
// 定义表单数据模型
const form = reactive<{
	id: String;
	startTime: String;
	endTime: String;
	billStatus: String;
	tenantry: String;
	tenantryPhone: String;
	lessor: string;
	duration: string;
	leaseName: string;
	leaseNum: String;
	flowKey: String;
	flowInstId: String;
	lessorPhone: String;
	tenantId: String;
	createBy: String;
	createTime: string;
	updateBy: String;
	updateTime: string;
	delFlag: String;
	archives: String;
	archivesList: {
		id: number;
		leaseId: String;
		archivesId: String;
		leasePrise: String;
		isReturn: String;
		equipmentNum: String;
		equipmentName: String;
		specificationModel: String;
		typeName: String;
		assetCategoryName: String;
		buyPrice: String;
	}[];
	fileVOList: {
		id: number;
		leaseId: number;
		fileId: number;
		fileUrl: String;
		chargeDeptId: String;
		deptId: String;
		userId: String;
		createBy: String;
		createTime: String;
		updateBy: String;
		updateTime: String;
		fileType: String;
		fileName: String;
		fileSize: String;
		fileSuffix: String;
		userName: String;
		fileUserName: String;
		createdTime: String;
	}[];
}>({
	id: '',
	startTime: '',
	endTime: '',
	billStatus: '',
	tenantry: '',
	tenantryPhone: '',
	lessor: '',
	duration: '',
	leaseName: '',
	leaseNum: '',
	flowKey: '',
	flowInstId: '',
	lessorPhone: '',
	tenantId: '',
	createBy: '',
	createTime: '',
	updateBy: '',
	updateTime: '',
	delFlag: '',
	archives: '',
	archivesList: [
		{
			id: NaN,
			leaseId: '',
			archivesId: '',
			leasePrise: '',
			isReturn: '',
			equipmentNum: '',
			equipmentName: '',
			specificationModel: '',
			typeName: '',
			assetCategoryName: '',
			buyPrice: '',
		},
	],
	fileVOList: [
		{
			id: NaN,
			leaseId: NaN,
			fileId: NaN,
			fileUrl: '',
			chargeDeptId: '',
			deptId: '',
			userId: '',
			createBy: '',
			createTime: '',
			updateBy: '',
			updateTime: '',
			fileType: '',
			fileName: '',
			fileSize: '',
			fileSuffix: '',
			userName: '',
			fileUserName: '',
			createdTime: '',
		},
	],
});

const props = defineProps({
	checkTypeCode: {
		type: String,
		default: '',
	},
	dataId: {
		type: String,
		default: '',
	},
	flowInstId: {
		type: String,
		default: null,
	},
	dialogVisibleType: {
		type: Boolean,
		default: false,
	},
	showExamineAndApprove: {
		type: Boolean,
		default: true,
	},
});

const tableData = ref([]);

const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
	if (columnIndex === 0) {
		if (rowIndex > 0 && row.specificationModel === tableData.value[rowIndex - 1].specificationModel) {
			return { rowspan: 0, colspan: 0 }; // Return 0 to hide the cell
		}
		let rowspan = 1;
		for (let i = rowIndex + 1; i < tableData.value.length; i++) {
			if (row.specificationModel === tableData.value[i].specificationModel) {
				rowspan++;
			} else {
				break;
			}
		}
		return { rowspan: rowspan, colspan: 1 };
	}
};

const formatDate = (dateString) => {
	if (dateString !== null && dateString !== '' && dateString !== undefined) {
		const date = new Date(dateString);
		const year = date.getFullYear();
		const month = String(date.getMonth() + 1).padStart(2, '0'); // January is month 0
		const day = String(date.getDate()).padStart(2, '0');

		return `${year}-${month}-${day}`;
	} else {
		return '';
	}
};

// 打开弹窗
const openDialog = (id: string) => {
	visible.value = true;
	form.id = '';

	// 重置表单数据
	nextTick(() => {
		dataFormRef.value?.resetFields();
	});

	// 获取etUpkeepItem信息
	if (id) {
		form.id = id;
		getetUpkeepItemPlanData(id);
	}
};
 
// 初始化表单数据
const getetUpkeepItemPlanData = (id: string) => {
	// 获取数据
	loading.value = true;
	tableData.value = [];
	getObj(id)
		.then((res: any) => {
			Object.assign(form, res.data); 
		})
		.finally(() => {
			loading.value = false;
		});
};

watch(
	() => props.dialogVisibleType,
	(newId) => {
		if (newId) {
			form.id = '';
			form.flowInstId = '';
			activeName.value = 'first';
			tableData.value = [];
			nextTick(() => {
				dataFormRef.value?.resetFields();
			});
			getetUpkeepItemPlanData(props.dataId);
		}
	},
	{ immediate: true } // 添加immediate选项以在初始渲染时立即触发watcher
);
// 新增:监听 flowInstId 的变化
watch(
	() => props.flowInstId,
	(newFlowInstId) => {
		if (newFlowInstId) {
			form.id = '';
			form.flowInstId = '';
			tableData.value = [];
			nextTick(() => {
				dataFormRef.value?.resetFields();
			});
			// 获取数据
			loading.value = true; 
		}
	},
	{ immediate: true } // 同样添加immediate以在初始渲染时立即触发watcher
);

// 暴露变量
defineExpose({
	openDialog,
});
</script>
<style scoped>
.fileName {
	color: #545454;
	font-size: 16px;
	font-weight: 600;
}
.fileView {
	margin: 15px 24px;
	background-color: #fff;
	width: 14rem;
	height: 18rem;
	/* border-radius: 40px 40px 40px 40px; */
	border: 1px solid #ededed;
	display: flex;
	flex-direction: column;
	text-align: center;
	justify-content: space-around;
	align-items: center;
}
.fileView:hover {
	background: #eef3fa;
}
.fileData {
	height: 9rem;
	display: flex;
	flex-direction: column;
	text-align: center;
	justify-content: space-around;
	align-items: center;
}
.fileDiv {
	width: 100%;
	display: flex;
	flex-direction: row;
	flex: 5;
	flex-wrap: wrap;
}
</style>

表格数据的增删改查图片展示

表格展示-查询-分页-正选反选

数据编辑回显-新增数据

查看数据回显展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值