qaz 1 day ago
parent
commit
012f03b9dd

+ 7 - 0
src/assets/u2855.svg

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="78px" height="78px" xmlns="http://www.w3.org/2000/svg">
+  <g transform="matrix(1 0 0 1 -1067 -62 )">
+    <path d="M 1106 66  C 1125.6 66  1141 81.4  1141 101  C 1141 120.6  1125.6 136  1106 136  C 1086.4 136  1071 120.6  1071 101  C 1071 81.4  1086.4 66  1106 66  Z " fill-rule="nonzero" fill="#ffffff" stroke="none" />
+    <path d="M 1106 64.5  C 1126.44 64.5  1142.5 80.56  1142.5 101  C 1142.5 121.44  1126.44 137.5  1106 137.5  C 1085.56 137.5  1069.5 121.44  1069.5 101  C 1069.5 80.56  1085.56 64.5  1106 64.5  Z " stroke-width="5" stroke="#f77105" fill="none" />
+  </g>
+</svg>

+ 3 - 3
src/views/system/borrow/component/ClassroomBorrow/index.vue

@@ -251,7 +251,7 @@ function resetForm() {
     app_user_borrower: 1,
     borrower_dept: '',
     team_type: 1,
-    team_members_count: 1,
+    team_members_count: 2,
     team_members: '',
     expected_start_time: '',
     expected_end_time: '',
@@ -314,9 +314,9 @@ function onSave() {
             }));
 			const firstLocation = form.value.items[0]?.location || '';
             form.value.return_location = firstLocation;
-			// form.value.expected_start_time = now;
+			form.value.expected_start_time = now;
 			form.value.expected_end_time = dayjs(form.value.expected_end_time).format('YYYY-MM-DD HH:mm:ss')|| now;
-			form.value.team_members_count=Number(form.team_members_count)||1;
+			form.value.team_members_count=Number(form.value.team_members_count)||1;
 			emit('submit', { ...form.value });
 			emit('update:visible', false);
 			// ElMessage.success("添加成功!");

+ 1 - 1
src/views/system/borrow/component/CollectEquipment/SelectDeviceDialog/index.vue

@@ -68,7 +68,7 @@ async function fetchData(resetPage = false) {
 	deviceApi.GetList({ page: page.value, limit: pageSize.value, code: search.value,status:1 })
 	.then((res) => {
 		const devices = res.data
-		.filter(device => device.available_quantity > 0)
+		/* .filter(device => device.available_quantity > 0) */
 		.map((device) => ({
             ...device,
             warehouse: `${warehouseMap.value[device.warehouse] || `ID:${device.warehouse}`} (${device.available_quantity})`

+ 165 - 0
src/views/system/borrow/component/CollectEquipment/SettlementDialog.vue

@@ -0,0 +1,165 @@
+<template>
+  <el-dialog
+    v-model="dialogVisible"
+    title="领取设备结算单"
+    width="75%"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+   <div class="title">
+        <img src="../../../../../assets/u2855.svg" alt="">
+        <span>已领取</span>
+    </div>
+    <el-form :model="formData" label-width="110px" label-position="top">
+      <el-row :gutter="16">
+        <el-col :span="8">
+          <el-form-item label="借用单编号">
+            <el-input v-model="formData.application_no" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="借用人">
+            <el-input v-model="formData.emergency_contact" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="学号/工号">
+            <el-input v-model="userCode" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="借用性质">
+            <el-input v-model="borrowType" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="借出时间">
+            <el-input v-model="formData.expected_start_time" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="预计归还时间">
+            <el-input v-model="formData.expected_end_time" disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <div style="margin: 16px 0 8px 0; font-weight: bold">借用明细表</div>
+      <el-table :data="formData.items" border style="width: 100%">
+        <el-table-column type="index" label="序号" width="60" align="center" />
+        <el-table-column prop="device_code" label="设备编号" align="center" />
+        <el-table-column prop="device_category_name" label="设备分类" align="center" />
+        <el-table-column prop="device_name" label="设备名称" align="center" />
+        <el-table-column prop="quantity" label="借用数量" align="center" />
+        <el-table-column prop="device_specification" label="规格型号" align="center" />
+        <el-table-column prop="device_storage_location" label="存放位置" align="center">
+          <template #default="scope">
+            {{ scope.row.device_storage_location || '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="remark" label="备注" align="center">
+          <template #default="scope">
+            {{ scope.row.remark || '-' }}
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <div style="margin: 16px 0 8px 0; font-weight: bold">配件信息</div>
+      <el-input v-model="formData.accessory_info" disabled />
+
+      <div style="margin: 16px 0 8px 0; font-weight: bold">备注</div>
+      <el-input v-model="formData.remark" type="textarea" disabled />
+    </el-form>
+   
+
+    <template #footer>
+      <el-button @click="handleClose">关闭</el-button>
+      <el-button type="primary" @click="handlePrint">打印</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, defineProps, defineEmits, watch, computed } from 'vue';
+
+const props = defineProps<{
+  visible: boolean;
+  settlementData: any;
+  modelValue: any;
+}>();
+
+const emit = defineEmits(['update:visible', 'update:modelValue']);
+
+const dialogVisible = ref(false);
+const formData = ref<any>({});
+
+watch(
+  () => props.visible,
+  (val) => {
+    dialogVisible.value = val;
+    if (val) {
+      // 优先使用 modelValue,如果没有则使用 settlementData
+      formData.value = props.modelValue || props.settlementData || {};
+    }
+  }
+);
+
+watch(
+  () => props.modelValue,
+  (val) => {
+    console.log("val:::",val);
+    if (val) {
+    /* formData.value.app_user_borrower = val.borrower_info.user_code; */
+      formData.value = val;
+      
+    }
+  },
+  { immediate: true }
+);
+
+const userCode = computed(() => {
+  return formData.value?.app_user_borrower || formData.value?.borrower_info?.user_code || '';
+});
+
+const borrowType=computed(() => {
+  return formData.value?.borrow_type_label || formData.value?.borrow_type || '';
+});
+
+const handleClose = () => {
+  emit('update:visible', false);
+  emit('update:modelValue', formData.value);
+};
+
+const handlePrint = () => {
+  window.print();
+};
+</script>
+
+<style scoped>
+@media print {
+  .el-dialog__footer {
+    display: none;
+  }
+}
+.title{
+    display: flex;
+    justify-content: flex-end;
+    position: relative;
+
+}
+.title span{
+    position: absolute;
+    right:10px ;
+    bottom: 30%;
+    align-self: flex-start;
+    padding: 0px 0px 0px 0px;
+    box-sizing: border-box;
+    transform: rotate(315deg);
+    font-family: "Impact Bold", "Impact Normal", "Impact", sans-serif;
+    font-weight: 700;
+    font-style: normal;
+    font-size: 17px;
+    color: #F77105;
+}
+
+</style> 

+ 649 - 180
src/views/system/borrow/component/CollectEquipment/index.vue

@@ -1,168 +1,341 @@
 <template>
 	<el-dialog v-model="visible" :title="isCollect ? '领取' : '归还'" width="75%" :close-on-click-modal="false" @close="onCancel">
-		<el-form :model="form" label-width="110px" label-position="top" :rules="rules" ref="formRef">
-			<el-row :gutter="16">
-				<el-col :span="8">
-					<el-form-item label="借用单编号" prop="application_no">
-						<el-input v-model="form.application_no" placeholder="自动生成" disabled />
-					</el-form-item>
-				</el-col>
-				<el-col :span="8">
-					<el-form-item label="借用人" prop="emergency_contact">
-						<el-input v-model="form.emergency_contact" placeholder="请输入借用人" :disabled="true" />
-					</el-form-item>
-				</el-col>
-				<el-col :span="8">
-					<el-form-item label="学号/工号" prop="app_user_borrower">
-						<el-input v-model="form.app_user_borrower" placeholder="请输入学号/工号"  :disabled="true"/>
-					</el-form-item>
-				</el-col>
-				<el-col :span="8">
-					<el-form-item label="联系电话" prop="emergency_phone">
-						<el-input v-model="form.emergency_phone" placeholder="请输入联系电话" :disabled="true" />
-					</el-form-item>
-				</el-col>
-				<el-col :span="8">
-					<el-form-item label="借用部门" prop="borrower_dept">
-						<el-input v-model="form.borrower_dept" placeholder="请输入借用部门" :disabled="true" />
-					</el-form-item>
-				</el-col>
-				<el-col :span="8">
-					<el-form-item label="预计归还时间" prop="expected_end_time">
-						<el-date-picker v-model="form.expected_end_time" type="datetime" placeholder="请选择预计归还时间" style="width: 100%"  :disabled="true"/>
-					</el-form-item>
-				</el-col>
-				<el-col :span="4">
-					<el-form-item label="个人/团队" prop="team_type" >
-						<el-select v-model="form.team_type" placeholder="请选择" :disabled="true">
-							<el-option label="个人" :value="0" />
-							<el-option label="团队" :value="1" />
-						</el-select>
-					</el-form-item>
-				</el-col>
-				<el-col :span="4" v-show="form.team_type===1">
-					<el-form-item label="团队人数" prop="team_members_count">
-						<el-input v-model="form.team_members_count" placeholder="请输入"  :disabled="true"/>
-					</el-form-item>
-				</el-col>
-				<el-col :span="16" v-show="form.team_type===1">
-					<el-form-item label="团队其他人员名单" prop="team_members">
-						<el-input v-model="form.team_members" placeholder="请输入团队其他人员名单"  :disabled="true"/>
-					</el-form-item>
-				</el-col>
-				<el-col :span="24">
-					<el-form-item label="借用原因" prop="purpose">
-						<el-input v-model="form.purpose" type="textarea" placeholder="请输入借用原因" :disabled="true" />
-					</el-form-item>
-				</el-col>
-				<el-col :span="4">
-					<el-form-item label="审批人" prop="applicant_remark_type">
-						<el-select v-model="form.applicant_remark_type" placeholder="请选择" :disabled="true" >
-							<el-option label="管理员" value="1"/>
-						</el-select>
-					</el-form-item>
-				</el-col>
-				<el-col :span="20">
-					<el-form-item label="备注" prop="applicant_remark">
-						<el-input v-model="form.applicant_remark" placeholder="请输入备注"  :disabled="true"/>
-					</el-form-item>
-				</el-col>
-			</el-row>
-			<div style="margin: 16px 0 8px 0; font-weight: bold"> {{ isCollect ? '借用明细表' : '归还明细表' }}</div>
-			<el-table :data="form.items" border style="width: 100%; margin-bottom: 12px">
-				<el-table-column type="index" label="序号" width="60" />
-				<el-table-column prop="remark" label="设备分类" />
-				<!-- <el-table-column prop="quantity" label="借用数量" /> -->
-				<el-table-column :label="isCollect ? '借用数量' : '归还数量'">
-				<template #default="{ row }">
-				<el-input v-model="row.quantity" type="number" :min="1" prop="quantity" size="small" :disabled="isView" />
-				</template>
-				</el-table-column>
-                <el-table-column prop="condition" label="归还备注" v-if="isReturn">
-                    <template #default="{ row }">
-                        <el-input v-model="row.condition" placeholder="请输入备注"  :disabled="isView" />
-                    </template>
-                </el-table-column>
-				<el-table-column prop="location" label="存放仓库" />
-				<el-table-column label="操作" width="80">
-					<template #default="{ row, $index }">
-						<el-button type="text" style="color: red" @click="removeItem($index)" :disabled="isView">移除</el-button>
-					</template>
-				</el-table-column>
-			</el-table>
-			<el-button type="primary" @click="addItem" v-if="!isView">添加设备</el-button>
-			<div style="margin: 16px 0 8px 0; font-weight: bold">配件信息</div>
-			<el-input v-model="form.accessory_info" placeholder="请输入配件信息"  :disabled="isView"/>
-
-			<div style="margin: 16px 0 8px 0; font-weight: bold">附件</div>
-			<el-upload
-			action="#"
-			drag
-			list-type="text"
-			accept=".bmp,.gif,.jpeg,.jpg,.png,‌.webp,.svg"
-			multiple
-			:show-file-list="true"
-			:on-success="handleUploadSuccess"
-			:on-error="handleUploadError"
-			>
-			<i class="el-icon-upload"></i>
-			<div class="el-upload__text">将文件拖到此处,或 <em>点击上传</em></div>
-			</el-upload>
-		</el-form>
-		<!-- 审批信息流程展示 -->
-		<div v-if="isView"  style="margin-top: 24px; padding: 0 12px">
-		<div style="font-weight: bold; margin-bottom: 12px">审批流程进度</div>
-		<el-steps :active="activeStep" align-center>
-			<el-step
-			title="创建申请"
-			:description="`创建时间:${ timeline.create }`"
-			icon="CircleCheck"
-			:status="activeStep >= 1 ? 'finish' : 'wait'"
-			/>
-			<el-step
-			title="待审批"
-			description="待超级管理员审批"
-			icon="CircleCheck"
-			:status="activeStep >= 2 ? 'finish' : 'wait'"
-			/>
-			<el-step
-			title="审批通过"
-			:description="`审批人:${timeline.approver},时间:${timeline.approve}`"
-			icon="CircleCheck"
-			:status="activeStep >= 3 ? 'finish' : 'wait'"
-			/>
-			<el-step
-			title="流程完成"
-			description="流程已结束"
-			icon="CircleCheck"
-			:status="activeStep >= 4 ? 'finish' : 'wait'"
-			/>
-		</el-steps>
-		</div>
+        <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+            <el-tab-pane label="借用单信息" name="first">       
+                <el-form :model="form" label-width="110px" label-position="top" :rules="rules" ref="formRef">
+                    <el-row :gutter="16">
+                        <el-col :span="8">
+                            <el-form-item label="借用单编号" prop="application_no">
+                                <el-input v-model="form.application_no" placeholder="自动生成" disabled />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="8">
+                            <el-form-item label="借用人" prop="emergency_contact">
+                                <el-input v-model="form.emergency_contact" placeholder="请输入借用人" :disabled="true" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="8">
+                            <el-form-item label="学号/工号" prop="app_user_borrower">
+                                <el-input v-model="form.app_user_borrower" placeholder="请输入学号/工号"  :disabled="true"/>
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="8">
+                            <el-form-item label="联系电话" prop="emergency_phone">
+                                <el-input v-model="form.emergency_phone" placeholder="请输入联系电话" :disabled="true" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="8">
+                            <el-form-item label="借用部门" prop="borrower_dept">
+                                <el-input v-model="form.borrower_dept" placeholder="请输入借用部门" :disabled="true" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="8">
+                            <el-form-item label="预计归还时间" prop="expected_end_time">
+                                <el-date-picker v-model="form.expected_end_time" type="datetime" placeholder="请选择预计归还时间" style="width: 100%"  :disabled="true"/>
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="4">
+                            <el-form-item label="个人/团队" prop="team_type" >
+                                <el-select v-model="form.team_type" placeholder="请选择" :disabled="true">
+                                    <el-option label="个人" :value="0" />
+                                    <el-option label="团队" :value="1" />
+                                </el-select>
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="4" v-show="form.team_type===1">
+                            <el-form-item label="团队人数" prop="team_members_count">
+                                <el-input v-model="form.team_members_count" placeholder="请输入"  :disabled="true"/>
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="16" v-show="form.team_type===1">
+                            <el-form-item label="团队其他人员名单" prop="team_members">
+                                <el-input v-model="form.team_members" placeholder="请输入团队其他人员名单"  :disabled="true"/>
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="24">
+                            <el-form-item label="借用原因" prop="purpose">
+                                <el-input v-model="form.purpose" type="textarea" placeholder="请输入借用原因" :disabled="true" />
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="4">
+                            <el-form-item label="审批人" prop="applicant_remark_type">
+                                <el-select v-model="form.applicant_remark_type" placeholder="请选择" :disabled="true" >
+                                    <el-option label="管理员" value="1"/>
+                                </el-select>
+                            </el-form-item>
+                        </el-col>
+                        <el-col :span="20">
+                            <el-form-item label="备注" prop="applicant_remark">
+                                <el-input v-model="form.applicant_remark" placeholder="请输入备注"  :disabled="true"/>
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                    <div style="margin: 16px 0 8px 0; font-weight: bold"> {{ isCollect ? '借用明细表' : '归还明细表' }}</div>
+                    <el-table :data="form.items" border style="width: 100%; margin-bottom: 12px">
+                        <el-table-column type="index" label="序号" width="60" />
+                        <el-table-column prop="remark" label="设备分类" />
+                        <!-- <el-table-column prop="quantity" label="借用数量" /> -->
+                        <el-table-column :label="isCollect ? '借用数量' : '归还数量'">
+                        <template #default="{ row }">
+                        <el-input v-model="row.quantity" type="number" :min="1" prop="quantity" size="small" :disabled="isView" />
+                        </template>
+                        </el-table-column>
+                        <el-table-column prop="condition" label="归还备注" v-if="isReturn">
+                            <template #default="{ row }">
+                                <el-input v-model="row.condition" placeholder="请输入备注"  :disabled="isView" />
+                            </template>
+                        </el-table-column>
+                        <el-table-column prop="location" label="存放仓库" />
+                        <el-table-column label="操作" width="80">
+                            <template #default="{ row, $index }">
+                                <el-button type="text" style="color: red" @click="removeItem($index)" :disabled="isView">移除</el-button>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                    <el-button type="primary" @click="addItem" v-if="!isView" :disabled="true">添加设备</el-button>
+                    <div style="margin: 16px 0 8px 0; font-weight: bold">配件信息</div>
+                    <el-input v-model="form.accessory_info" placeholder="请输入配件信息"  :disabled="true"/>
 
+                    <div style="margin: 16px 0 8px 0; font-weight: bold" >附件</div>
+                    <el-upload
+                    action="#"
+                    drag
+                    list-type="text"
+                    accept=".bmp,.gif,.jpeg,.jpg,.png,‌.webp,.svg"
+                    multiple
+                    :show-file-list="true"
+                    :on-success="handleUploadSuccess"
+                    :on-error="handleUploadError"
+                    :disabled="true"
+                    >
+                    <i class="el-icon-upload"></i>
+                    <div class="el-upload__text">将文件拖到此处,或 <em>点击上传</em></div>
+                    </el-upload>
+                </el-form>
+                <!-- 审批信息流程展示 -->
+                <div v-if="isView"  style="margin-top: 24px; padding: 0 12px">
+                <div style="font-weight: bold; margin-bottom: 12px">审批流程进度</div>
+                    <el-steps :active="activeStep" align-center>
+                        <el-step
+                        title="创建申请"
+                        :description="`创建时间:${ timeline.create }`"
+                        icon="CircleCheck"
+                        :status="activeStep >= 1 ? 'finish' : 'wait'"
+                        />
+                        <el-step
+                        title="待审批"
+                        description="待超级管理员审批"
+                        icon="CircleCheck"
+                        :status="activeStep >= 2 ? 'finish' : 'wait'"
+                        />
+                        <el-step
+                        title="审批通过"
+                        :description="`审批人:${timeline.approver},时间:${timeline.approve}`"
+                        icon="CircleCheck"
+                        :status="activeStep >= 3 ? 'finish' : 'wait'"
+                        />
+                        <el-step
+                        title="流程完成"
+                        description="流程已结束"
+                        icon="CircleCheck"
+                        :status="activeStep >= 4 ? 'finish' : 'wait'"
+                        />
+                    </el-steps>
+                </div>
+            </el-tab-pane>
+        <el-tab-pane v-if="isCollect" label="设备清单" name="second">
+            <el-form :model="form" label-width="110px">
+                <el-row :gutter="16">
+                    <el-col :span="24">
+                        <div style="margin: 8px 0">
+                            <el-input v-model="searchText" placeholder="请扫描设备条码添加" style="width: 300px" @keyup.enter="handleScanSearch" />
+                            <el-button type="primary" style="margin-left: 16px" @click="handleAdd">手动添加</el-button>
+                        </div>
+                        <el-table :data="deviceList" border style="width: 100%">
+                            <el-table-column type="index" label="序号" width="60" align="center" />
+                            <el-table-column prop="device_no" label="设备编号" align="center" />
+                            <el-table-column prop="device_type" label="设备分类" align="center" />
+                            <el-table-column prop="device_name" label="设备名称" align="center" />
+                            <el-table-column prop="borrow_count" label="借用数量" align="center" width="150">
+                                <template #default="{ row }">
+                                    <el-input-number v-model="row.borrow_count" :min="1" :max="999" size="small" />
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="brand" label="品牌" align="center" />
+                            <el-table-column prop="model" label="现货型号" align="center" />
+                            <el-table-column prop="warehouse" label="存放仓库" align="center" />
+                            <el-table-column label="操作" width="80" align="center">
+                                <template #default="{ $index }">
+                                    <el-button type="text" style="color: red" @click="handleRemove($index)">移除</el-button>
+                                </template>
+                            </el-table-column>
+                        </el-table>
+                    </el-col>
+                </el-row>
+                <el-row :gutter="16" style="margin-top: 16px">
+                    <el-col :span="24">
+                        <div style="font-weight: bold; margin-bottom: 8px">配件信息</div>
+                        <el-input v-model="accessoryInfo" type="textarea" placeholder="请输入配件信息" />
+                    </el-col>
+                    <el-col :span="24" style="margin-top: 16px">
+                        <div style="font-weight: bold; margin-bottom: 8px">备注</div>
+                        <el-input v-model="remark" type="textarea" placeholder="请输入备注" />
+                    </el-col>
+                </el-row>
+                <el-row :gutter="16" style="margin-top: 16px">
+                    <el-col :span="24">
+                        <div style="font-weight: bold; margin-bottom: 8px">异常记录 <span>{{ 0 }}</span> 条</div>
+                        <el-table v-if="abnormalList.length > 0" :data="abnormalList" border style="width: 100%">
+                            <el-table-column type="index" label="序号" width="60" align="center" />
+                            <el-table-column prop="borrowNo" label="借用单编号" align="center" />
+                            <el-table-column prop="borrower" label="借用人" align="center" />
+                            <el-table-column prop="time" label="发生时间" align="center" />
+                            <el-table-column prop="type" label="异常类型" align="center">
+                                <template #default="{ row }">
+                                    <el-tag :type="row.type === '逾期' ? 'danger' : 'warning'">{{ row.type }}</el-tag>
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="operation" label="操作" align="center" width="80">
+                                <template #default="{ row }">
+                                    <el-button type="text" @click="handleView(row)">查看</el-button>
+                                </template>
+                            </el-table-column>
+                        </el-table>
+                    </el-col>
+                </el-row>
+            </el-form>
+        </el-tab-pane>
+        <el-tab-pane v-else label="设备清单" name="third">
+            <el-form :model="form" label-width="110px">
+                <el-row :gutter="16">
+                    <el-col :span="24">
+                        <div style="margin: 8px 0">
+                            <el-input v-model="returnSearchText" placeholder="请扫描设备条码添加" style="width: 300px" @keyup.enter="handleReturnScanSearch" />
+                            <el-button type="primary" style="margin-left: 16px" @click="handleAdd">手动添加</el-button>
+                        </div>
+                        <el-table :data="returnDeviceList" border style="width: 100%">
+                            <el-table-column type="index" label="序号" width="60" align="center" />
+                            <el-table-column prop="device_no" label="设备编号" align="center" />
+                            <el-table-column prop="device_type" label="设备分类" align="center" />
+                            <el-table-column prop="device_name" label="设备名称" align="center" />
+                            <el-table-column prop="borrow_count" label="借用数量" align="center" width="150">
+                                <template #default="{ row }">
+                                    <el-input-number v-model="row.borrow_count" :min="1" :max="999" size="small" />
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="brand" label="品牌" align="center" />
+                            <el-table-column prop="model" label="规格型号" align="center" />
+                            <el-table-column prop="warehouse" label="存放仓库" align="center" />
+                            <el-table-column prop="status" label="状态" align="center">
+                                <template #default="{ row }">
+                                    <el-tag :type="row.status === '已归还' ? 'success' : 'warning'">{{ row.status }}</el-tag>
+                                </template>
+                            </el-table-column>
+                            <el-table-column label="操作" width="80" align="center">
+                                <template #default="{ $index }">
+                                    <el-button type="text" style="color: red" @click="handleReturnRemove($index)">移除</el-button>
+                                </template>
+                            </el-table-column>
+                        </el-table>
+                    </el-col>
+                </el-row>
+                <el-row :gutter="16" style="margin-top: 16px">
+                    <el-col :span="16">
+                        <div style="font-weight: bold; margin-bottom: 8px">配件信息</div>
+                        <el-input v-model="returnAccessoryInfo"  placeholder="请输入配件信息" />
+                    </el-col>
+                    <el-col :span="8">
+                        <div style="font-weight: bold; margin-bottom: 8px">当前状态</div>
+                        <el-input v-model="form.status_label"  :disabled="true" placeholder="" style="width: 150px" />
+                        <el-button type="primary" style="margin-left: 16px" @click="clickReturn">归还</el-button>
+                    </el-col>
+                    <el-col :span="24" style="margin-top: 16px">
+                        <div style="font-weight: bold; margin-bottom: 8px">备注</div>
+                        <el-input v-model="returnRemark" type="textarea" placeholder="请输入备注" />
+                    </el-col>
+                </el-row>
+            </el-form>
+        </el-tab-pane>
+        </el-tabs>
 		<template #footer>
 			<el-button @click="onCancel">关闭</el-button>
-			<el-button type="primary" @click="onSubmit" v-if="!isView">提交</el-button>
+			<el-button type="primary" @click="onSubmit" v-if="!isView"> {{ isCollect ? '提交' : '确认' }}</el-button>
 		</template>
 	</el-dialog>
 	<SelectDeviceDialog v-model:visible="showSelectDeviceDialog" @confirm="onDeviceSelected" />
+	<SettlementDialog v-model:visible="showSettlementDialog" :settlement-data="settlementData" />
 </template>
 
 <script setup lang="ts">
 import { ref, watch, defineProps, defineEmits, onMounted,computed } from 'vue';
 import SelectDeviceDialog from './SelectDeviceDialog/index.vue';
+import SettlementDialog from './SettlementDialog.vue';
 import dayjs from 'dayjs';
 import { ElMessage } from 'element-plus';
 import * as api from '../../api';
-import { CollectEquipment,ReturnEquipment } from '../../api';
+import * as deviceApi from '../../../device/api';
+import { CollectEquipment, ReturnEquipment } from '../../api';
+import type { TabsPaneContext } from 'element-plus';
 
-const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
+interface ApiResponse {
+  code: number;
+  data?: any;
+  message?: string;
+}
 
+// 定义接口
+interface Device {
+  id: string | number;
+  category_name: string;
+  name?: string;
+  brand?: string;
+  model?: string;
+  warehouse: string;
+}
 
+interface DeviceListItem {
+  device_no: string | number;
+  device_type: string;
+  device_name: string;
+  borrow_count: number;
+  brand: string;
+  model: string;
+  warehouse: string;
+  status?: string;  // 添加状态字段
+}
 
+interface FormItem {
+  device: string | number;
+  remark: string;
+  quantity: number;
+  location: string;
+}
 
-const props = defineProps<{ visible: boolean; modelValue?: any }>();
+interface FormData {
+  application_no: string;
+  emergency_contact: string;
+  emergency_phone: string;
+  app_user_borrower: number;
+  team_type: number;
+  team_members_count: number;
+  team_members: string;
+  expected_start_time: string;
+  expected_end_time: string;
+  borrower_dept: string;
+  purpose: string;
+  applicant_remark_type: string;
+  applicant_remark: string;
+  items: FormItem[];
+  accessory_info: string;
+  borrow_type: number;
+  return_location: string;
+  status_label?: string;
+  id?: number;
+}
+
+const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
 
+const props = defineProps<{ visible: boolean; modelValue?: any }>();
 
 const isEdit = computed(() => props.modelValue?.mode === 'edit');
 const isView = computed(() => props.modelValue?.mode === 'view');
@@ -174,8 +347,6 @@ const emit = defineEmits(['update:visible', 'update:modelValue', 'submit']);
 const visible = ref(props.visible);
 const formRef = ref();
 
-// import { ElSteps } from 'element-plus';
-
 const timeline = ref({
   create: '',
   approve: '',
@@ -183,18 +354,233 @@ const timeline = ref({
 });
 const activeStep = ref(1);
 
-function handleUploadSuccess(response, file, fileList) {
+const activeName = ref('first');
+
+// 借用明细表相关数据
+const searchText = ref('');
+const deviceList = ref<DeviceListItem[]>([]);
+const accessoryInfo = ref('');
+const remark = ref('');
+
+// 归还设备相关数据
+const returnSearchText = ref('');
+const returnDeviceList = ref<DeviceListItem[]>([]);
+const returnAccessoryInfo = ref('');
+const returnRemark = ref('');
+
+// 添加结算单相关的状态
+const showSettlementDialog = ref(false);
+const settlementData = ref<any>(null);
+
+// 处理扫码搜索
+const handleScanSearch = async () => {
+    if (!searchText.value.trim()) return;
+    
+    try {
+        const res = await deviceApi.GetList({ 
+            page: 1, 
+            limit: 1, 
+            code: searchText.value.trim(),
+            status: 1 
+        });
+        
+        if (res.data && res.data.length > 0) {
+            const device = res.data[0];
+            if (device.available_quantity <= 0) {
+                ElMessage.warning('该设备当前无可用数量');
+                return;
+            }
+            
+            // 检查是否已存在
+            const existingDevice = deviceList.value.find(d => d.device_no === device.id);
+            if (existingDevice) {
+                existingDevice.borrow_count++;
+                ElMessage.success('设备数量已更新');
+            } else {
+                // 添加新设备到列表
+                deviceList.value.push({
+                    device_no: device.id,
+                    device_type: device.category_name,
+                    device_name: device.name || '',
+                    borrow_count: 1,
+                    brand: device.brand || '',
+                    model: device.model || '',
+                    warehouse: device.warehouse
+                });
+                ElMessage.success('设备已添加到列表');
+            }
+        } else {
+            ElMessage.warning('未找到对应的设备');
+        }
+    } catch (error) {
+        ElMessage.error('搜索设备失败');
+    } finally {
+        searchText.value = ''; // 清空搜索框
+    }
+};
+
+// 处理归还扫码搜索
+const handleReturnScanSearch = async () => {
+    if (!returnSearchText.value.trim()) return;
+    
+    try {
+        const res = await deviceApi.GetList({ 
+            page: 1, 
+            limit: 1, 
+            code: returnSearchText.value.trim(),
+            status: 1 
+        });
+        
+        if (res.data && res.data.length > 0) {
+            const device = res.data[0];
+            
+            // 检查是否已存在
+            const existingDevice = returnDeviceList.value.find(d => d.device_no === device.id);
+            if (existingDevice) {
+                existingDevice.borrow_count++;
+                ElMessage.success('设备数量已更新');
+            } else {
+                // 添加新设备到列表
+                returnDeviceList.value.push({
+                    device_no: device.id,
+                    device_type: device.category_name,
+                    device_name: device.name || '',
+                    borrow_count: 1,
+                    brand: device.brand || '',
+                    model: device.model || '',
+                    warehouse: device.warehouse,
+                    status: '未归还'
+                });
+                ElMessage.success('设备已添加到列表');
+            }
+        } else {
+            ElMessage.warning('未找到对应的设备');
+        }
+    } catch (error) {
+        ElMessage.error('搜索设备失败');
+    } finally {
+        returnSearchText.value = ''; // 清空搜索框
+    }
+};
+
+// 异常记录列表数据
+const abnormalList = ref([
+    /* {
+        borrowNo: '202409002',
+        borrower: '张同学',
+        time: '2024-09-12 10:21:32',
+        type: '逾期'
+    },
+    {
+        borrowNo: '202505013',
+        borrower: '张同学',
+        time: '2025-05-13 15:12:35',
+        type: '损坏'
+    } */
+]);
+
+// 查看异常记录详情
+const handleView = (row: any) => {
+    console.log('查看异常记录:', row);
+    // 这里可以添加查看详情的逻辑
+};
+
+// 借用明细表相关方法
+const handleAdd = () => {
+  showSelectDeviceDialog.value = true;
+};
+
+const handleRemove = (index: number) => {
+  deviceList.value.splice(index, 1);
+};
+const handleReturnRemove = (index: number) => {
+  returnDeviceList.value.splice(index, 1);
+};
+
+// 设备选择处理
+function onDeviceSelected(devices: Device[]) {
+  console.log("devices:::",devices,"activeName:::",activeName.value);
+  if (activeName.value === 'first') {
+    // 第一个标签页的处理逻辑
+    form.value.items.push(
+      ...devices.map((d) => ({
+        device: d.id,
+        remark: d.category_name,
+        quantity: 1,
+        location: d.warehouse,
+      }))
+    );
+  } else if (activeName.value === 'second') {
+    // 第二个标签页的处理逻辑 - 直接添加到设备列表
+    deviceList.value.push(
+      ...devices.map(d => ({
+        device_no: d.id,
+        device_type: d.category_name,
+        device_name: d.name || '',
+        borrow_count: 1,
+        brand: d.brand || '',
+        model: d.model || '',
+        warehouse: d.warehouse
+      }))
+    );
+  }else if(activeName.value === 'third'){
+    // 在添加前先检查是否存在相同id的设备
+   /*  const newDevices = devices.filter(d => {
+      const existingItem = form.value.items.find(item => item.device === d.id);
+      console.log("existingItem:::",existingItem);
+      if (!existingItem) {
+        ElMessage.warning(`设备 ${d.category_name} 不在借用清单中`);
+        return false;
+      }
+      return true;
+    }); */
+
+    returnDeviceList.value.push(
+      ...devices.map(d => ({
+        device_no: d.id,
+        device_type: d.category_name,
+        device_name: d.name || '',
+        borrow_count: 1,
+        brand: d.brand || '',
+        model: d.model || '',
+        warehouse: d.warehouse
+      }))
+    );
+  
+  }
+}
+
+// 移除同步相关的 watch
+// const handleClick = (tab: TabsPaneContext, event: Event) => {
+//   if (tab.props.name === 'second') {
+//     deviceList.value = form.value.items.map(item => ({
+//       device_no: item.device,
+//       device_type: item.remark,
+//       device_name: '',
+//       borrow_count: item.quantity,
+//       brand: '',
+//       model: '',
+//       warehouse: item.location
+//     }));
+//   }
+// }
+
+function handleClick(tab: TabsPaneContext) {
+  console.log('Tab clicked:', tab.props.name);
+}
+
+function handleUploadSuccess(response: any, file: any, fileList: any) {
 	// eslint-disable-next-line no-console
   console.log('上传成功:', file.name);
 }
 
-function handleUploadError(err, file, fileList) {
+function handleUploadError(err: any, file: any, fileList: any) {
 	// eslint-disable-next-line no-console
   console.error('上传失败:', file.name);
 }
 
 
-const form = ref({
+const form = ref<FormData>({
 	application_no: '',
 	emergency_contact: '',
 	emergency_phone: '',
@@ -316,46 +702,130 @@ watch(() => props.modelValue, async (val) => {
 function addItem() {
 	showSelectDeviceDialog.value = true;
 }
-function onDeviceSelected(devices) {
-	form.value.items.push(
-		...devices.map((d) => ({
-			device: d.id,
-			remark: d.category_name,
-			quantity: 1,
-			location: d.warehouse,
-		}))
-	);
-}
 function removeItem(index: number) {
 	form.value.items.splice(index, 1);
 }
 function onCancel() {
+    activeName.value = 'first';
 	emit('update:visible', false);
 }
+// 提交时合并数据
 function onSubmit() {
-    if(isCollect.value){
-        form.value.items = form.value.items.map(item => ({
-            ...item,
-            device_id: Number(item.device) || 0  
-        }));
-    CollectEquipment(form.value).then(res=>{
-        if(res.code===2000){
-            ElMessage.success("领取成功");
-            emit('update:visible', false);
-            emit('submit'); // 触发submit事件通知父组件刷新列表
-        }
+  if(isCollect.value){
+    // 验证是否有设备信息
+    const hasDevicesInFirstTab = form.value.items && form.value.items.length > 0;
+    const hasDevicesInSecondTab = deviceList.value && deviceList.value.length > 0;
+    
+    if (!hasDevicesInFirstTab && !hasDevicesInSecondTab) {
+      ElMessage.warning('请添加设备信息后再提交');
+      activeName.value = 'second'; // 自动切换到借用明细表标签页
+      return;
+    }
+
+    // 验证设备数量
+    const hasInvalidQuantityInFirstTab = form.value.items.some(item => !item.quantity || item.quantity <= 0);
+    const hasInvalidQuantityInSecondTab = deviceList.value.some(item => !item.borrow_count || item.borrow_count <= 0);
+
+    if (hasInvalidQuantityInFirstTab || hasInvalidQuantityInSecondTab) {
+      ElMessage.warning('请确保所有设备的数量大于0');
+      activeName.value = 'second'; // 自动切换到借用明细表标签页
+      return;
+    }
+
+    // 合并两个标签页的设备数据
+    const allDevices = [
+      ...deviceList.value.map(item => ({
+        condition: remark.value,
+        quantity: item.borrow_count,
+        device_id: Number(item.device_no) || 0
+      }))
+    ];
+    
+    const submitData = {
+        id:form.value.id,
+        item_id:form.value.id,
+        device_assignments: allDevices,
+        remark:remark.value,
+    };
+
+    CollectEquipment(submitData).then((res: ApiResponse) => {
+      if(res.code===2000){
+        ElMessage.success("领取成功");
+        // 准备结算单数据
+        settlementData.value = {
+          ...form.value,
+          items: deviceList.value,
+          accessory_info: accessoryInfo.value,
+          remark: remark.value,
+          expected_start_time: dayjs().format('YYYY-MM-DD HH:mm:ss')
+        };
+        // 显示结算单
+        showSettlementDialog.value = true;
+        emit('update:visible', false);
+        emit('submit');
+      }
     });
-}else{
-    form.value.items = form.value.items.map(item => ({
-            ...item,
-            device_id: Number(item.device) || 0  
-        }));
-    ReturnEquipment(form.value).then(res=>{
-        if(res.code===2000){
-            ElMessage.success("归还成功");
-            emit('update:visible', false);
-            emit('submit'); // 触发submit事件通知父组件刷新列表
+  } else {
+    emit('update:visible', false);
+  }
+}
+
+function clickReturn(){
+    console.log("clickReturn:::",form.value);
+     // 验证是否有设备信息
+     const hasDevicesInFirstTab = form.value.items && form.value.items.length > 0;
+    const hasDevicesInSecondTab = returnDeviceList.value && returnDeviceList.value.length > 0;
+    
+    if (!hasDevicesInFirstTab && !hasDevicesInSecondTab) {
+      ElMessage.warning('请添加设备信息后再提交');
+      activeName.value = 'third'; // 自动切换到借用明细表标签页
+      return;
+    }
+
+    // 验证设备数量
+    const hasInvalidQuantityInFirstTab = form.value.items.some(item => !item.quantity || item.quantity <= 0);
+    const hasInvalidQuantityInSecondTab = returnDeviceList.value.some(item => !item.borrow_count || item.borrow_count <= 0);
+
+    if (hasInvalidQuantityInFirstTab || hasInvalidQuantityInSecondTab) {
+      ElMessage.warning('请确保所有设备的数量大于0');
+      activeName.value = 'third'; // 自动切换到借用明细表标签页
+      return;
+    }
+
+    // 合并两个标签页的设备数据
+    const allDevices = [
+      ...returnDeviceList.value.map(item => ({
+        device: item.device_no,
+        quantity: item.borrow_count,
+        condition:returnRemark.value,
+        device_id: Number(item.device_no) || 0
+      }))
+    ];
+    
+    const submitData = {
+      id:form.value.id,
+      items: allDevices
+    };
+
+    console.log("submitData:::",submitData);
+    
+    ReturnEquipment(submitData).then(async (res: ApiResponse) => {
+      if(res.code===2000){
+        ElMessage.success("归还成功");
+        // 获取最新详情
+        try {
+          if (form.value.id) {
+            const detailRes = await api.GetApplicationDetail(form.value.id);
+            if (detailRes.code === 2000 && detailRes.data) {
+              // 只更新状态标签,保持其他数据不变
+              form.value.status_label = detailRes.data.status_label || '';
+            }
+          }
+        } catch (e) {
+          ElMessage.error('获取最新状态失败');
         }
+        emit('submit');
+      }
     });
 }
 
@@ -376,6 +846,5 @@ function onSubmit() {
 		}
 	}); */
 	
-}
 
 </script>

+ 1 - 1
src/views/system/borrow/component/SpecialBorrow/index.vue

@@ -191,7 +191,7 @@ const form = ref({
 	emergency_phone: '',
 	app_user_borrower: 1,
 	team_type: 0,
-	team_members_count: 1,
+	team_members_count: 2,
 	team_members: '',
 	expected_start_time:'',
 	expected_end_time: '',

+ 13 - 2
src/views/system/borrow/crud.tsx

@@ -51,7 +51,7 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 			},
 			rowHandle: {
 				fixed: 'right',
-				width: 300,
+				width: 330,
 				buttons: {
 					view: {
 						show: true,
@@ -74,7 +74,18 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 					},
 					remove: {
 						order:5,
-						show: true,
+						show: false,
+					},
+					/* 查看结算单 */
+					settlement: {
+						order:6,
+						show:compute( ({row})=>{
+							return row.status === 5;
+						}), 
+						text: '查看结算单',
+						click: ({ row }) => {
+							window.dispatchEvent(new CustomEvent('borrow-settlement', { detail: row }));
+						}
 					},
 					collectEquipment:{
 						order:2,

+ 15 - 1
src/views/system/borrow/index.vue

@@ -11,6 +11,7 @@
 		/>
 		<SpecialBorrow v-if="showSpecialBorrowDialog" v-model:visible="showSpecialBorrowDialog" :modelValue="borrowForm" @submit="handleBorrowSubmit" />
 		<CollectEquipmentDialog  v-model:visible="showCollectDialog" :modelValue="borrowForm" @submit="handleCollectSubmit" />
+		<SettlementDialog  v-model:visible="showSettlementDialog" :modelValue="borrowForm" />
 	</fs-page>
 </template>
 <script lang="ts" setup name="borrow">
@@ -24,6 +25,7 @@ import BorrowTypeSelect from './component/BorrowTypeSelect/index.vue';
 import ClassroomBorrow from './component/ClassroomBorrow/index.vue';
 import SpecialBorrow from './component/SpecialBorrow/index.vue';
 import CollectEquipmentDialog from './component/CollectEquipment/index.vue';
+import SettlementDialog from './component/CollectEquipment/SettlementDialog.vue';
 import * as api from './api';
 import { ElMessage } from 'element-plus';
 
@@ -34,6 +36,10 @@ const showClassroomBorrowDialog = ref(false);
 const showSpecialBorrowDialog = ref(false);
 const showCollectDialog = ref(false);
 const borrowForm = ref({});
+const showSettlementDialog = ref(false);	
+
+
+
 
 function onBorrowTypeSelected(type: number, mode: 'view' | 'edit' | 'add' |'collect',record?: any) {
 	showBorrowTypeDialog.value = false;
@@ -110,7 +116,13 @@ async function handleRemove(e: CustomEvent) {
 	const row = e.detail;
 	onBorrowTypeSelected(row.borrow_type);
 }
-
+async function handleSettlement(e: CustomEvent) {
+	const row = e.detail;
+	showSettlementDialog.value = true;
+	nextTick(() => {
+		borrowForm.value = { ...row, mode: 'settlement' };
+	});
+}
 let observer: MutationObserver | null = null;
 
 onMounted(() => {
@@ -125,6 +137,7 @@ onMounted(() => {
 	window.addEventListener('borrow-remove', handleRemove);
 	window.addEventListener('borrow-collect', handleCollect);
 	window.addEventListener('borrow-return', handleReturn);
+	window.addEventListener('borrow-settlement', handleSettlement);
 	// 创建借用单按钮
 	function insertButton() {
 		const fsActionbar = document.querySelector('.borrow-page .fs-actionbar');
@@ -156,6 +169,7 @@ onBeforeUnmount(() => {
 	window.removeEventListener('borrow-view', handleView);
 	window.removeEventListener('borrow-collect', handleCollect);
 	window.removeEventListener('borrow-return', handleReturn);
+	window.removeEventListener('borrow-settlement', handleSettlement);
 });
 </script>
 <style lang="scss" scoped></style>