index.vue 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250
  1. <template>
  2. <el-dialog v-model="visible" :title="isView ? '查看' : isCollect ? '领取' : '归还'" width="75%" :close-on-click-modal="false" @close="onCancel">
  3. <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
  4. <el-tab-pane label="借用单信息" name="first">
  5. <el-form :model="form" label-width="110px" label-position="top" :rules="rules" ref="formRef">
  6. <el-row :gutter="16">
  7. <el-col :span="8">
  8. <el-form-item label="借用单编号" prop="application_no">
  9. <el-input v-model="form.application_no" placeholder="自动生成" disabled />
  10. </el-form-item>
  11. </el-col>
  12. <el-col :span="8">
  13. <el-form-item label="借用人类型" prop="borrower_type">
  14. <el-select v-model="form.borrower_type" :placeholder="isView?'':'请选择借用人角色'" :disabled="true">
  15. <el-option label="管理员用户" :value=0 />
  16. <el-option label="应用用户" :value=1 />
  17. <el-option label="外部用户" :value=2 />
  18. </el-select>
  19. </el-form-item>
  20. </el-col>
  21. <el-col :span="8" >
  22. <!-- <el-form-item label="借用人" prop="external_borrower_name" v-if="form.borrower_type !== 2">
  23. <el-input v-model="form.borrower_info.name" placeholder="请输入借用人" :disabled="true" />
  24. </el-form-item> -->
  25. <el-form-item label="借用人" prop="admin_borrower" v-if="form.borrower_type == 0">
  26. <el-select v-model="form.admin_borrower" :placeholder="isView?'':'请选择借用人'" :disabled="true" >
  27. <el-option :label="adminList.name" :value="adminList.id" />
  28. </el-select>
  29. </el-form-item>
  30. <el-form-item label="借用人" prop="app_user_borrower" v-if="form.borrower_type == 1">
  31. <el-select v-model="form.app_user_borrower.id" :placeholder="isView?'':'请选择借用人'" :disabled="true" >
  32. <el-option v-for="item in allUserList" :key="item.id" :label="item.name" :value="item.id" />
  33. </el-select>
  34. </el-form-item>
  35. <el-form-item label="借用人" prop="external_borrower_name" v-if="form.borrower_type == 2">
  36. <el-input v-model="form.external_borrower_name" :placeholder="isView?'':'请输入借用人'" :disabled="true" />
  37. </el-form-item>
  38. </el-col>
  39. <el-col :span="8" v-if="form.borrower_type !== 2">
  40. <el-form-item label="学号/工号" prop="user_code" >
  41. <!-- {{ form.borrower_info.user_code }} -->
  42. <el-input v-model="form.app_user_borrower.user_code" :placeholder="isView?'':'请输入学号/工号'" :disabled="true"/>
  43. </el-form-item>
  44. </el-col>
  45. <el-col :span="8">
  46. <el-form-item label="联系电话" v-if="form.borrower_type !== 2">
  47. <el-input v-model="form.app_user_borrower.mobile" :placeholder="isView?'':'请输入联系电话'" :disabled="true" />
  48. </el-form-item>
  49. <el-form-item label="联系电话" v-if="form.borrower_type == 2">
  50. <el-input v-model="form.external_borrower_phone" :placeholder="isView?'':'请输入联系电话'" :disabled="true" />
  51. </el-form-item>
  52. </el-col>
  53. <el-col :span="8">
  54. <el-form-item label="借用部门" prop="borrower_dept">
  55. <el-input v-model="form.borrower_dept" placeholder="请输入借用部门" :disabled="true" />
  56. </el-form-item>
  57. </el-col>
  58. <el-col :span="8">
  59. <el-form-item label="预计归还时间" prop="expected_end_time">
  60. <el-date-picker v-model="form.expected_end_time" type="datetime" placeholder="请选择预计归还时间" style="width: 100%" :disabled="true"/>
  61. </el-form-item>
  62. </el-col>
  63. <el-col :span="4">
  64. <el-form-item label="个人/团队" prop="team_type" >
  65. <el-select v-model="form.team_type" placeholder="请选择" :disabled="true">
  66. <el-option label="个人" :value="0" />
  67. <el-option label="团队" :value="1" />
  68. </el-select>
  69. </el-form-item>
  70. </el-col>
  71. <el-col :span="4" v-show="form.team_type===1">
  72. <el-form-item label="团队人数" prop="team_members_count">
  73. <el-input v-model="form.team_members_count" :placeholder="isView?'':'请输入'" :disabled="true"/>
  74. </el-form-item>
  75. </el-col>
  76. <el-col :span="16" v-show="form.team_type===1">
  77. <el-form-item label="团队其他人员名单" prop="team_members">
  78. <el-input v-model="form.team_members" :placeholder="isView?'':'请输入团队其他人员名单'" :disabled="true"/>
  79. </el-form-item>
  80. </el-col>
  81. <el-col :span="24">
  82. <el-form-item label="借用原因" prop="purpose">
  83. <el-input v-model="form.purpose" type="textarea" :placeholder="isView?'':'请输入借用原因'" :disabled="true" />
  84. </el-form-item>
  85. </el-col>
  86. <el-col :span="4">
  87. <el-form-item label="审批人" prop="applicant_remark_type">
  88. <el-select v-model="form.applicant_remark_type" placeholder="请选择" :disabled="true" >
  89. <el-option label="管理员" value="1"/>
  90. </el-select>
  91. </el-form-item>
  92. </el-col>
  93. <el-col :span="20">
  94. <el-form-item label="备注" prop="applicant_remark">
  95. <el-input v-model="form.applicant_remark" :placeholder="isView?'':'请输入备注'" :disabled="true"/>
  96. </el-form-item>
  97. </el-col>
  98. </el-row>
  99. <div style="margin: 16px 0 8px 0; font-weight: bold"> {{ isCollect ? '借用列表' : '归还列表' }}</div>
  100. <el-table :data="form.items.filter(item => item.device === null)" border style="width: 100%; margin-bottom: 12px">
  101. <el-table-column type="index" label="序号" width="60" />
  102. <el-table-column prop="device_category_name" label="设备分类" />
  103. <!-- <el-table-column prop="quantity" label="借用数量" /> -->
  104. <el-table-column :label="isCollect ? '借用数量' : '归还数量'">
  105. <template #default="{ row }">
  106. <el-input v-model="row.quantity" type="number" :min="1" prop="quantity" size="small" :disabled="true" />
  107. </template>
  108. </el-table-column>
  109. <el-table-column prop="condition" label="归还备注" v-if="isReturn">
  110. <template #default="{ row }">
  111. <el-input v-model="row.condition" :placeholder="isView?'':'请输入备注'" :disabled="true" />
  112. </template>
  113. </el-table-column>
  114. <el-table-column prop="location" label="存放仓库" />
  115. <el-table-column label="操作" width="80">
  116. <template #default="{ $index }">
  117. <el-button type="text" style="color: red" @click="removeItem($index)" :disabled="true">移除</el-button>
  118. </template>
  119. </el-table-column>
  120. </el-table>
  121. <el-button type="primary" @click="addItem" v-if="!isView" :disabled="true">添加设备</el-button>
  122. <div style="margin: 16px 0 8px 0; font-weight: bold">配件信息</div>
  123. <el-input v-model="form.accessories" :placeholder="isView?'':'请输入配件信息'" :disabled="true"/>
  124. <div style="margin: 16px 0 8px 0; font-weight: bold" >附件</div>
  125. <el-upload
  126. action="#"
  127. drag
  128. list-type="text"
  129. accept=".bmp,.gif,.jpeg,.jpg,.png,‌.webp,.svg"
  130. multiple
  131. :show-file-list="true"
  132. :on-success="handleUploadSuccess"
  133. :on-error="handleUploadError"
  134. :disabled="true"
  135. >
  136. <i class="el-icon-upload"></i>
  137. <div class="el-upload__text">将文件拖到此处,或 <em>点击上传</em></div>
  138. </el-upload>
  139. </el-form>
  140. <!-- 审批信息流程展示 -->
  141. <!-- <div v-if="isView" style="margin-top: 24px; padding: 0 12px">
  142. <div style="font-weight: bold; margin-bottom: 12px">审批流程进度</div>
  143. <el-steps :active="activeStep" align-center>
  144. <el-step
  145. title="创建申请"
  146. :description="`创建时间:${ timeline.create }`"
  147. icon="CircleCheck"
  148. :status="activeStep >= 1 ? 'finish' : 'wait'"
  149. />
  150. <el-step
  151. title="待审批"
  152. description="待超级管理员审批"
  153. icon="CircleCheck"
  154. :status="activeStep >= 2 ? 'finish' : 'wait'"
  155. />
  156. <el-step
  157. title="审批通过"
  158. :description="`审批人:${timeline.approver},时间:${timeline.approve}`"
  159. icon="CircleCheck"
  160. :status="activeStep >= 3 ? 'finish' : 'wait'"
  161. />
  162. <el-step
  163. title="流程完成"
  164. description="流程已结束"
  165. icon="CircleCheck"
  166. :status="activeStep >= 4 ? 'finish' : 'wait'"
  167. />
  168. </el-steps>
  169. </div> -->
  170. <div v-if="isView" style="margin-top: 24px; padding: 0 12px">
  171. <div style="font-weight: bold; margin-bottom: 12px">审批流程进度</div>
  172. <el-steps :active="steps.length" align-center>
  173. <el-step
  174. v-for="(step, index) in steps"
  175. :key="index"
  176. :title="step.title"
  177. :description="step.description"
  178. icon="CircleCheck"
  179. :status="step.status"
  180. />
  181. </el-steps>
  182. </div>
  183. </el-tab-pane>
  184. <el-tab-pane v-if="isCollect" label="设备清单" name="second">
  185. <el-form :model="form" label-width="110px">
  186. <el-row :gutter="16">
  187. <el-col :span="24">
  188. <div style="margin: 8px 0">
  189. <el-input v-model="searchText" placeholder="请扫描设备条码添加" style="width: 300px" @keyup.enter="handleScanSearch" />
  190. <el-button type="primary" style="margin-left: 16px" @click="handleAdd">手动借用</el-button>
  191. </div>
  192. <el-table :data="deviceList" border style="width: 100%">
  193. <el-table-column type="index" label="序号" width="60" align="center" />
  194. <el-table-column prop="device_no" label="设备编号" align="center" />
  195. <el-table-column prop="device_type" label="设备分类" align="center" />
  196. <el-table-column prop="device_name" label="设备名称" align="center" />
  197. <el-table-column prop="borrow_count" label="借用数量" align="center" width="150">
  198. <template #default="{ row }">
  199. <el-input-number v-model="row.borrow_count" :disabled="isView" :min="1" :max="999" size="small" />
  200. </template>
  201. </el-table-column>
  202. <el-table-column prop="brand" label="品牌" align="center" />
  203. <el-table-column prop="model" label="现货型号" align="center" />
  204. <el-table-column prop="warehouse" label="存放仓库" align="center" />
  205. <el-table-column label="操作" width="80" align="center">
  206. <template #default="{ $index }">
  207. <el-button type="text" style="color: red" :disabled="isView" @click="handleRemove($index)">移除</el-button>
  208. </template>
  209. </el-table-column>
  210. </el-table>
  211. </el-col>
  212. </el-row>
  213. <el-row :gutter="16" style="margin-top: 16px">
  214. <el-col :span="24">
  215. <div style="font-weight: bold; margin-bottom: 8px">配件信息</div>
  216. <el-input v-model="form.accessories" :disabled="isView" type="textarea" :placeholder="isView?'':'请输入配件信息'" />
  217. </el-col>
  218. <el-col :span="24" style="margin-top: 16px">
  219. <div style="font-weight: bold; margin-bottom: 8px">备注</div>
  220. <el-input v-model="remark" type="textarea" :disabled="isView" :placeholder="isView?'':'请输入备注'" />
  221. </el-col>
  222. </el-row>
  223. <el-row :gutter="16" style="margin-top: 16px">
  224. <el-col :span="24">
  225. <div style="font-weight: bold; margin-bottom: 8px">异常记录 <span>{{
  226. abnormalList?.length ?
  227. abnormalList.reduce((sum, item) => sum + (Number(item?.condition) || 0), 0)
  228. : 0
  229. }}</span> 次</div>
  230. <el-table v-if="abnormalList.length > 0" :data="abnormalList" border style="width: 100%">
  231. <!-- <el-table-column type="index" label="序号" width="60" align="center" />
  232. <el-table-column prop="application_no" label="借用单编号" align="center" /> -->
  233. <el-table-column prop="operator_name" label="借用人" align="center" />
  234. <el-table-column prop="user_code" label="学号" align="center" />
  235. <el-table-column prop="emergency_phone" label="借用人电话" align="center" />
  236. <!-- <el-table-column prop="time" label="发生时间" align="center" /> -->
  237. <el-table-column prop="type" label="异常" align="center">
  238. <template #default="{ row }">
  239. {{ row.type }}
  240. </template>
  241. </el-table-column>
  242. <el-table-column prop="condition" label="数量" align="center">
  243. <template #default="{ row }">
  244. {{ row.condition }}
  245. </template>
  246. </el-table-column>
  247. </el-table>
  248. </el-col>
  249. </el-row>
  250. </el-form>
  251. </el-tab-pane>
  252. <el-tab-pane v-else label="设备清单" name="third">
  253. <el-form :model="form" label-width="110px">
  254. <el-row :gutter="16">
  255. <el-col :span="24">
  256. <div style="margin: 8px 0" v-if="!isView" >
  257. <el-input :disabled="isView" v-model="returnSearchText" placeholder="请扫描设备条码添加" style="width: 300px" @keyup.enter="handleReturnScanSearch" />
  258. <el-button type="primary" style="margin-left: 16px" @click="handleAdd" :disabled="isView">手动归还</el-button>
  259. </div>
  260. <el-table :data="returnDeviceList" border style="width: 100%" >
  261. <!-- <el-table-column type="selection" width="55" align="center" />@selection-change="handleSelectionChange" -->
  262. <el-table-column type="index" label="序号" width="60" align="center" />
  263. <el-table-column prop="device_no" label="设备编号" align="center" />
  264. <el-table-column prop="device_type" label="设备分类" align="center" />
  265. <el-table-column prop="device_name" label="设备名称" align="center" />
  266. <el-table-column prop="borrow_count" label="借用数量" align="center" width="150">
  267. <template #default="{ row }">
  268. <el-input-number v-model="row.borrow_count" :min="1" :max="999" size="small" :disabled="true" />
  269. </template>
  270. </el-table-column>
  271. <el-table-column prop="brand" label="品牌" align="center" />
  272. <el-table-column prop="model" label="规格型号" align="center" />
  273. <el-table-column prop="warehouse" label="存放仓库" align="center" />
  274. <el-table-column prop="status" label="状态" align="center">
  275. <template #default="{ row }">
  276. {{ row.return_status.label }}
  277. <!-- <el-tag v-if="!isView" :type="row.status === '已归还' ? 'success' : 'warning'">{{ row.status }}</el-tag>
  278. <el-tag v-else-if="['已领取', '已归还'].includes(form.status_label)">{{ form.status_label }}</el-tag> -->
  279. <!-- <span v-else>{{ form.status_label }}</span> -->
  280. </template>
  281. </el-table-column>
  282. <el-table-column prop="status" label="归还时间" align="center">
  283. <template #default="{ row }">
  284. {{ row.return_time ? dayjs(row.return_time).format('YYYY-MM-DD HH:mm:ss') : (row.return_status?.label === '已归还' ? dayjs().format('YYYY-MM-DD HH:mm:ss') : '') }}
  285. </template>
  286. </el-table-column>
  287. <el-table-column label="操作" width="150" align="center">
  288. <template #default="{ $index,row }">
  289. <el-button :disabled="isView" type="text" style="color: red"
  290. v-if="!isView && (!returnDeviceList[$index]?.condition || returnDeviceList[$index]?.photos?.length==0)&& row.problem_records?.length ==0"
  291. @click="handleAbnormal($index)">异常操作</el-button>
  292. <el-button
  293. type="text"
  294. style="color: #409EFF"
  295. @click="handleViewAbnormal($index)"
  296. v-if="row.problem_records?.length || (returnDeviceList[$index]?.condition || returnDeviceList[$index]?.photos?.length)"
  297. >查看异常</el-button>
  298. <!-- <el-button type="text" v-if="!isView" :disabled="isView" style="color: red" @click="handleReturnRemove($index)">移除</el-button> -->
  299. </template>
  300. </el-table-column>
  301. </el-table>
  302. </el-col>
  303. </el-row>
  304. <el-row :gutter="16" style="margin-top: 16px">
  305. <el-col :span="16">
  306. <div style="font-weight: bold; margin-bottom: 8px">配件信息</div>
  307. <el-input v-model="form.accessories" :disabled="isView" :placeholder="isView?'':'请输入配件信息'" />
  308. </el-col>
  309. <el-col :span="8">
  310. <div style="font-weight: bold; margin-bottom: 8px">当前状态</div>
  311. <el-input v-model="returnStatus" v-if="!isView" :disabled="true" placeholder="" style="width: 150px" />
  312. <el-input value="已归还" v-else :disabled="true" placeholder="" style="width: 150px" />
  313. <el-button type="primary" v-if="!isView" style="margin-left: 16px" @click="clickReturn"
  314. :disabled="returnStatus=='已归还'||isView">归还</el-button>
  315. </el-col>
  316. <el-col :span="24" style="margin-top: 16px">
  317. <div style="font-weight: bold; margin-bottom: 8px">备注</div>
  318. <el-input v-model="returnRemark" type="textarea" :disabled="isView" :placeholder="isView?'':'请输入备注'" />
  319. </el-col>
  320. </el-row>
  321. <el-row :gutter="16" style="margin-top: 16px">
  322. <el-col :span="24">
  323. <div style="font-weight: bold; margin-bottom: 8px">异常记录 <span>{{
  324. returnAbnormalList?.length ?
  325. returnAbnormalList.reduce((sum, item) => sum + (Number(item?.condition) || 0), 0)
  326. : 0
  327. }}</span> 次</div>
  328. <el-table v-if="returnAbnormalList?.length > 0" :data="returnAbnormalList" border style="width: 100%">
  329. <!-- <el-table-column type="index" label="序号" width="60" align="center" />
  330. <el-table-column prop="application_no" label="借用单编号" align="center" /> -->
  331. <el-table-column prop="operator_name" label="借用人" align="center" />
  332. <el-table-column prop="user_code" label="学号" align="center" />
  333. <el-table-column prop="emergency_phone" label="借用人电话" align="center" />
  334. <!-- <el-table-column prop="time" label="发生时间" align="center" /> -->
  335. <el-table-column prop="type" label="异常" align="center">
  336. <template #default="{ row }">
  337. {{ row.type }}
  338. </template>
  339. </el-table-column>
  340. <el-table-column prop="condition" label="数量" align="center">
  341. <template #default="{ row }">
  342. {{ row.condition }}
  343. </template>
  344. </el-table-column>
  345. </el-table>
  346. </el-col>
  347. </el-row>
  348. </el-form>
  349. </el-tab-pane>
  350. </el-tabs>
  351. <template #footer>
  352. <el-button @click="onCancel">关闭</el-button>
  353. <el-button type="primary" @click="onSubmit" v-if="!isView"> {{ isCollect ? '提交' : '确认' }}</el-button>
  354. </template>
  355. </el-dialog>
  356. <SelectDeviceDialog
  357. v-model:visible="showSelectDeviceDialog"
  358. @confirm="onDeviceSelected"
  359. :device-ids="returnDeviceList.filter(item => item.return_status.label !== '已归还').map(item => item.device_no)"
  360. />
  361. <SettlementDialog v-model:visible="showSettlementDialog" :settlement-data="settlementData" />
  362. <AbnormalDialog v-model:visible="showAbnormalDialog" @confirm="onAbnormalConfirm" />
  363. <ViewAbnormalDialog
  364. v-model:visible="showViewAbnormalDialog"
  365. :abnormal-data="currentAbnormalData"
  366. />
  367. </template>
  368. <script setup lang="ts">
  369. import { ref, watch, defineProps, defineEmits, onMounted, computed, nextTick } from 'vue';
  370. import SelectDeviceDialog from './SelectDeviceDialog/index.vue';
  371. import SettlementDialog from './SettlementDialog.vue';
  372. import AbnormalDialog from './AbnormalDialog/index.vue';
  373. import ViewAbnormalDialog from './ViewAbnormalDialog/index.vue';
  374. import dayjs from 'dayjs';
  375. import { ElMessage } from 'element-plus';
  376. import * as api from '../../api';
  377. import * as deviceApi from '../../../device/api';
  378. import { CollectEquipment, ReturnEquipment } from '../../api';
  379. import type { TabsPaneContext } from 'element-plus';
  380. import { getUserInfo } from '../../../login/api';
  381. /* 获取管理员列表 */
  382. const adminList = ref([]);
  383. async function getAdminList() {
  384. const res = await getUserInfo();
  385. adminList.value = res.data;
  386. console.log("adminList.value:::",adminList.value)
  387. }
  388. /* */
  389. /* 获取所有用户 */
  390. const allUserList = ref([]);
  391. async function getAllUserList() {
  392. const res = await api.GetAllUser();
  393. allUserList.value = res.data;
  394. // 设置默认选择第一个用户
  395. if (allUserList.value.length > 0) {
  396. form.value.app_user_borrower = allUserList.value[0].id;
  397. }
  398. console.log("allUserList.value:::",allUserList.value)
  399. }
  400. interface ApiResponse {
  401. code: number;
  402. data?: any;
  403. message?: string;
  404. }
  405. // 定义接口
  406. interface Device {
  407. id: string | number;
  408. category_name: string;
  409. name?: string;
  410. brand?: string;
  411. model?: string;
  412. warehouse: string;
  413. device_specification?: string;
  414. device_name?: string;
  415. }
  416. interface DeviceListItem {
  417. device_no: string | number;
  418. device_type: string;
  419. device_name?: string; // 改为可选
  420. borrow_count: number;
  421. brand: string;
  422. model?: string; // 改为可选
  423. warehouse: string;
  424. status?: string;
  425. condition?: string;
  426. photos?: Array<{
  427. filename: string;
  428. data: string;
  429. }>;
  430. device_specification?: string;
  431. }
  432. interface FormItem {
  433. device: string | number;
  434. remark: string;
  435. quantity: number;
  436. location: string;
  437. device_name?: string;
  438. device_specification?: string;
  439. condition?: string;
  440. photos?: Array<{
  441. filename: string;
  442. data: string;
  443. }>;
  444. }
  445. interface FormData {
  446. application_no: string;
  447. emergency_contact: string;
  448. emergency_phone: string;
  449. app_user_borrower: number;
  450. team_type: number;
  451. team_members_count: number;
  452. team_members: string;
  453. expected_start_time: string;
  454. expected_end_time: string;
  455. borrower_dept: string;
  456. purpose: string;
  457. applicant_remark_type: string;
  458. applicant_remark: string;
  459. items: FormItem[];
  460. accessory_info: string;
  461. borrow_type: number;
  462. return_location: string;
  463. status_label?: string;
  464. id?: number;
  465. records?: any[];
  466. borrower_info?: {
  467. user_code: string;
  468. };
  469. borrower_damage_count?: number;
  470. accessories?: string;
  471. }
  472. interface AbnormalData {
  473. condition: string;
  474. photos: Array<{
  475. filename: string;
  476. data: string;
  477. }>;
  478. }
  479. interface AbnormalRecord {
  480. application_no: string;
  481. operator_name: string;
  482. user_code: string;
  483. emergency_phone: string;
  484. type: '损坏' | '逾期';
  485. condition: number;
  486. create_time: string;
  487. }
  488. const now = dayjs().format('YYYY-MM-DD HH:mm:ss');
  489. const props = defineProps<{ visible: boolean; modelValue?: any }>();
  490. const isEdit = computed(() => props.modelValue?.mode === 'edit');
  491. const isView = computed(() => props.modelValue?.mode === 'view');
  492. const isAdd = computed(() => props.modelValue?.mode === 'add');
  493. const isCollect = computed(() => props.modelValue?.mode === 'collect');
  494. const isReturn = computed(() => props.modelValue?.mode === 'return');
  495. const emit = defineEmits(['update:visible', 'update:modelValue', 'submit']);
  496. const visible = ref(props.visible);
  497. const formRef = ref();
  498. const timeline = ref({
  499. create: '',
  500. approve: '',
  501. approver: ''
  502. });
  503. // const activeStep = ref(1);
  504. const activeName = ref('first');
  505. const returnStatus = ref('未归还'); // 添加独立的状态变量
  506. // 借用列表相关数据
  507. const searchText = ref('');
  508. const deviceList = ref<DeviceListItem[]>([]);
  509. const accessoryInfo = ref('');
  510. const remark = ref('');
  511. // 归还设备相关数据
  512. const returnSearchText = ref('');
  513. const returnDeviceList = ref<DeviceListItem[]>([]);
  514. const returnAccessoryInfo = ref('');
  515. const returnRemark = ref('');
  516. const selectedDevices = ref<DeviceListItem[]>([]); // 添加选中设备列表
  517. //审批步骤
  518. const steps = ref<any[]>([]);
  519. // 添加结算单相关的状态
  520. const showSettlementDialog = ref(false);
  521. const settlementData = ref<any>(null);
  522. // 添加异常操作相关的状态
  523. const showAbnormalDialog = ref(false);
  524. const currentAbnormalIndex = ref(-1);
  525. // 添加查看异常相关的状态
  526. const showViewAbnormalDialog = ref(false);
  527. const currentAbnormalData = ref<AbnormalData>({
  528. condition: '',
  529. photos: []
  530. });
  531. //审批
  532. function buildSteps(data: any) {
  533. steps.value = [
  534. {
  535. title: '创建申请',
  536. description: `创建时间:${data.create_datetime}`,
  537. status: 'finish'
  538. },
  539. {
  540. title: '待审批',
  541. description: '待超级管理员审批',
  542. status: data.status >= 2 ? 'finish' : 'process'
  543. }
  544. ];
  545. const approverinfo = data.approver_info ?? data.admin_approver_info
  546. if (data.status >= 2&&data.status!=3 && data.borrow_type!=1) {
  547. steps.value.push({
  548. title: '审批通过',
  549. description: `审批人:${approverinfo.name},时间:${data.approve_time}`,
  550. status: 'finish'
  551. });
  552. } else if (data.status === 3) {
  553. // console.log("data.approver_name:::",data.approver_info.name)
  554. steps.value.push({
  555. title: '审批拒绝',
  556. description: `审批人:${approverinfo.name},拒绝原因: ${data.approve_remark},时间:${data.approve_time}`,
  557. status: 'error'
  558. });
  559. }
  560. if (data.status >= 4 ||data.borrow_type==1) {
  561. steps.value.push({
  562. title: '流程完成',
  563. description: '流程已结束',
  564. status: 'finish'
  565. });
  566. }
  567. }
  568. // 处理异常操作
  569. const handleAbnormal = (index: number) => {
  570. currentAbnormalIndex.value = index;
  571. showAbnormalDialog.value = true;
  572. console.log("showAbnormalDialog:::", showAbnormalDialog.value, "currentAbnormalIndex:::", currentAbnormalIndex.value);
  573. };
  574. // 处理异常操作确认
  575. const onAbnormalConfirm = (data: { condition: string; photos: any[] }) => {
  576. console.log("异常操作确认数据:", data);
  577. if (currentAbnormalIndex.value !== -1) {
  578. const device = returnDeviceList.value[currentAbnormalIndex.value];
  579. device.condition = data.condition;
  580. device.photos = data.photos;
  581. ElMessage.success('异常信息已保存');
  582. }
  583. };
  584. // 处理查看异常
  585. const handleViewAbnormal = (index: number) => {
  586. const device = returnDeviceList.value[index];
  587. console.log("device:::",device);
  588. if (device) {
  589. if(device.problem_records?.length){
  590. currentAbnormalData.value = {
  591. condition: device.problem_records?.[0].device_condition_after ||'',
  592. photos: device.problem_records?.[0].returned_images.map((item:any)=>item.image_url) ||[]
  593. };
  594. }else{
  595. currentAbnormalData.value = {
  596. condition: device.condition ||'',
  597. photos: device.photos ||[]
  598. };
  599. }
  600. showViewAbnormalDialog.value = true;
  601. }
  602. };
  603. // 处理扫码搜索
  604. const handleScanSearch = async () => {
  605. if (!searchText.value.trim()) return;
  606. try {
  607. const res = await deviceApi.GetList({
  608. page: 1,
  609. limit: 1,
  610. code: searchText.value.trim(),
  611. status: 1
  612. });
  613. if (res.data && res.data.length > 0) {
  614. const device = res.data[0];
  615. if (device.available_quantity <= 0) {
  616. ElMessage.warning('该设备当前无可用数量');
  617. return;
  618. }
  619. // 检查是否已存在
  620. const existingDevice = deviceList.value.find(d => d.device_no === device.id);
  621. if (existingDevice) {
  622. existingDevice.borrow_count++;
  623. ElMessage.success('设备数量已更新');
  624. } else {
  625. // 添加新设备到列表
  626. deviceList.value.push({
  627. device_no: device.id,
  628. device_type: device.category_name,
  629. device_name: device.name || '',
  630. borrow_count: 1,
  631. brand: device.brand || '',
  632. model: device.model || '',
  633. warehouse: device.warehouse
  634. });
  635. ElMessage.success('设备已添加到列表');
  636. }
  637. } else {
  638. ElMessage.warning('未找到对应的设备');
  639. }
  640. } catch (error) {
  641. ElMessage.error('搜索设备失败');
  642. } finally {
  643. searchText.value = ''; // 清空搜索框
  644. }
  645. };
  646. // 处理归还扫码搜索
  647. const handleReturnScanSearch = async () => {
  648. if (!returnSearchText.value.trim()) return;
  649. try {
  650. const res = await deviceApi.GetList({
  651. page: 1,
  652. limit: 1,
  653. code: returnSearchText.value.trim(),
  654. status: 1
  655. });
  656. if (res.data && res.data.length > 0) {
  657. const device = res.data[0];
  658. // 检查是否已存在
  659. const existingDeviceIndex = returnDeviceList.value.findIndex(d => d.device_no === device.id);
  660. if (existingDeviceIndex !== -1) {
  661. // 如果设备已存在,更新其状态
  662. returnDeviceList.value[existingDeviceIndex].status = '已归还';
  663. ElMessage.success(`设备 ${device.category_name} 状态已更新为已归还`);
  664. } else {
  665. // 添加新设备到列表
  666. returnDeviceList.value.push({
  667. device_no: device.id,
  668. device_type: device.category_name,
  669. device_name: device.name || '',
  670. borrow_count: 1,
  671. brand: device.brand || '',
  672. model: device.model || '',
  673. warehouse: device.warehouse,
  674. return_status:device.return_status,
  675. return_time:device.return_times
  676. });
  677. ElMessage.success('设备已添加到列表');
  678. }
  679. } else {
  680. ElMessage.warning('未找到对应的设备');
  681. }
  682. } catch (error) {
  683. ElMessage.error('搜索设备失败');
  684. } finally {
  685. returnSearchText.value = ''; // 清空搜索框
  686. }
  687. };
  688. // 异常记录列表数据
  689. const abnormalList = ref([
  690. /* {
  691. borrowNo: '202409002',
  692. borrower: '张同学',
  693. time: '2024-09-12 10:21:32',
  694. type: '逾期'
  695. },
  696. {
  697. borrowNo: '202505013',
  698. borrower: '张同学',
  699. time: '2025-05-13 15:12:35',
  700. type: '损坏'
  701. } */
  702. ]);
  703. /* 归还设备异常记录 */
  704. const returnAbnormalList = ref([
  705. ]);
  706. // 查看异常记录详情
  707. const handleView = (row: any) => {
  708. console.log('查看异常记录:', row);
  709. // 这里可以添加查看详情的逻辑
  710. };
  711. // 借用列表相关方法
  712. const handleAdd = () => {
  713. showSelectDeviceDialog.value = true;
  714. };
  715. const handleRemove = (index: number) => {
  716. deviceList.value.splice(index, 1);
  717. };
  718. const handleReturnRemove = (index: number) => {
  719. returnDeviceList.value.splice(index, 1);
  720. };
  721. // 处理表格多选变化
  722. const handleSelectionChange = (selection: DeviceListItem[]) => {
  723. selectedDevices.value = selection;
  724. };
  725. // 设备选择处理
  726. function onDeviceSelected(devices: Device[]) {
  727. console.log("devices:::",devices,"activeName:::",activeName.value);
  728. if (activeName.value === 'first') {
  729. form.value.items.push(
  730. ...devices.map((d) => ({
  731. device: d.id,
  732. remark: d.category_name,
  733. quantity: 1,
  734. location: d.warehouse,
  735. device_name: d.name,
  736. device_specification: d.device_specification
  737. }))
  738. );
  739. } else if (activeName.value === 'second') {
  740. deviceList.value.push(
  741. ...devices.map(d => ({
  742. device_no: d.id,
  743. device_type: d.category_name,
  744. device_name: d.name || '',
  745. borrow_count: 1,
  746. brand: d.brand || '',
  747. model: d.model,
  748. device_specification: d.device_specification,
  749. warehouse: d.warehouse
  750. }))
  751. );
  752. }else if(activeName.value === 'third'){
  753. // 在添加前检查每个设备是否已存在
  754. devices.forEach(d => {
  755. const existingDeviceIndex = returnDeviceList.value.findIndex(item => item.device_no === d.id);
  756. if (existingDeviceIndex !== -1) {
  757. // 如果设备已存在,更新其状态
  758. returnDeviceList.value[existingDeviceIndex].return_status.value = 2;
  759. returnDeviceList.value[existingDeviceIndex].return_status.label = '已归还';
  760. returnDeviceList.value[existingDeviceIndex].is_return = true;
  761. returnDeviceList.value[existingDeviceIndex].return_time = dayjs().format('YYYY-MM-DD HH:mm:ss');
  762. ElMessage.success(`设备 ${d.category_name} 状态已更新为已归还`);
  763. } else {
  764. // 如果设备不存在,添加新记录
  765. /* returnDeviceList.value.push({
  766. device_no: d.id,
  767. device_type: d.category_name,
  768. device_name: d.name || '',
  769. borrow_count: 1,
  770. brand: d.brand || '',
  771. model: d.model || '',
  772. warehouse: d.warehouse,
  773. status: '已归还'
  774. }); */
  775. /* ElMessage.success(`设备 ${d.category_name} 已添加到归还列表`); */
  776. }
  777. });
  778. }
  779. }
  780. // 移除同步相关的 watch
  781. // const handleClick = (tab: TabsPaneContext, event: Event) => {
  782. // if (tab.props.name === 'second') {
  783. // deviceList.value = form.value.items.map(item => ({
  784. // device_no: item.device,
  785. // device_type: item.remark,
  786. // device_name: '',
  787. // borrow_count: item.quantity,
  788. // brand: '',
  789. // model: '',
  790. // warehouse: item.location
  791. // }));
  792. // }
  793. // }
  794. function handleClick(tab: TabsPaneContext) {
  795. console.log('Tab clicked:', tab.props.name);
  796. }
  797. function handleUploadSuccess(response: any, file: any, fileList: any) {
  798. // eslint-disable-next-line no-console
  799. console.log('上传成功:', file.name);
  800. }
  801. function handleUploadError(err: any, file: any, fileList: any) {
  802. // eslint-disable-next-line no-console
  803. console.error('上传失败:', file.name);
  804. }
  805. const form = ref<FormData>({
  806. borrower_info:{
  807. user_code:'',
  808. mobile:''
  809. },
  810. application_no: '',
  811. emergency_contact: '',
  812. emergency_phone: '',
  813. app_user_borrower: 1,
  814. team_type: 0,
  815. team_members_count: 1,
  816. team_members: '',
  817. expected_start_time:'',
  818. expected_end_time: '',
  819. borrower_dept: '',
  820. purpose: '',
  821. applicant_remark_type: "1",
  822. applicant_remark: '',
  823. items: [],
  824. accessory_info: '',
  825. borrow_type: 2,
  826. return_location:''
  827. });
  828. const showSelectDeviceDialog = ref(false);
  829. const rules = {
  830. emergency_contact: [
  831. { required: true, message: '请输入借用人', trigger: 'change' },
  832. ],
  833. app_user_borrower: [
  834. { required: true, message: '请输入学号或工号', trigger: 'change' },
  835. ],
  836. emergency_phone: [
  837. { required: true, message: '请输入联系电话', trigger: 'change' },
  838. ],
  839. borrower_dept: [
  840. { required: true, message: '请输入借用部门', trigger: 'change' },
  841. ],
  842. expected_end_time: [
  843. { required: true, message: '请输选择归还时间', trigger: 'change' },
  844. ],
  845. team_type: [
  846. { required: true, message: '请选择个人或者团队', trigger: 'change' },
  847. ],
  848. purpose: [
  849. { required: true, message: '请输入借用原因', trigger: 'change' },
  850. ],
  851. applicant_remark_type: [
  852. { required: true, message: '请选择审批人', trigger: 'change' },
  853. ],
  854. applicant_remark: [
  855. { required: false, message: '请输入备注', trigger: 'change' },
  856. ],
  857. };
  858. // 自动填充用户信息
  859. onMounted(() => {
  860. getAdminList()
  861. getAllUserList()
  862. try {
  863. const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
  864. if (userInfo) {
  865. form.value.emergency_contact = userInfo.username || '';
  866. form.value.app_user_borrower = Number(userInfo.dept_info?.dept_id )|| 1;
  867. form.value.emergency_phone = userInfo.mobile || '';
  868. form.value.borrower_dept = userInfo.dept_info?.dept_name || '';
  869. }
  870. } catch (e) {
  871. /* empty */
  872. }
  873. });
  874. watch(
  875. () => props.visible,
  876. (v) => (visible.value = v)
  877. );
  878. watch(() => props.modelValue, async (val) => {
  879. if (val && val.id) {
  880. try {
  881. const res = await api.GetApplicationDetail(val.id);
  882. console.log("res:::::",res)
  883. if (res.code === 2000 && res.data) {
  884. const data = res.data;
  885. Object.assign(form.value, data);
  886. buildSteps(data);
  887. timeline.value.create = data.create_datetime || '';
  888. timeline.value.approve = data.approve_time || '';
  889. const approverinfo = data.approver_info ?? data.admin_approver_info
  890. timeline.value.approver = approverinfo?.name || '审批人'
  891. // timeline.value.approver = data.admin_approver_info?.name || '审批人';
  892. // console.log("data:::",form.value);
  893. // activeStep.value = 1; // 创建
  894. // if (data.status >= 1) activeStep.value = 2; // 待审批
  895. // if (data.status >= 2) activeStep.value = 3; // 审批通过
  896. // if (data.status >= 3) activeStep.value = 4; // 完成
  897. // 同步 form.items 到 returnDeviceList
  898. if (form.value.items && form.value.items.length > 0) {
  899. returnDeviceList.value = form.value.items
  900. .filter(item => item.device !== null)
  901. .map(item => ({
  902. device_no: item.device,
  903. device_type: item.remark,
  904. device_name: item.device_name,
  905. borrow_count: item.quantity,
  906. brand: '',
  907. model: item.device_specification,
  908. warehouse: item.location,
  909. problem_records: item.problem_records,
  910. /* status: '未归还' */
  911. return_status:item.return_status,
  912. return_time:item.return_times
  913. }));
  914. }
  915. // 同步 form.records 到 returnAbnormalList
  916. if (form.value.records && form.value.records.length > 0) {
  917. // 添加损坏类型记录
  918. const damageRecord: AbnormalRecord = {
  919. application_no: form.value.application_no,
  920. operator_name: form.value.external_borrower_name||form.value.app_user_borrower?.name||'',
  921. user_code: form.value.borrower_info?.user_code || form.value.app_user_borrower?.user_code||'',
  922. emergency_phone: form.value.external_borrower_phone || form.value.app_user_borrower?.mobile||'',
  923. type: '损坏',
  924. condition: form.value.borrower_damage_count || 0,
  925. create_time: dayjs().format('YYYY-MM-DD HH:mm:ss')
  926. };
  927. // 添加逾期类型记录
  928. const overdueRecord: AbnormalRecord = {
  929. application_no: form.value.application_no,
  930. operator_name: form.value.external_borrower_name||form.value.app_user_borrower?.name||'',
  931. user_code: form.value.borrower_info?.user_code || form.value.app_user_borrower?.user_code||'',
  932. emergency_phone: form.value.external_borrower_phone || form.value.app_user_borrower?.mobile||'',
  933. type: '逾期',
  934. condition: form.value.borrower_overdue_count || 0, // 逾期数量设为1
  935. create_time: dayjs().format('YYYY-MM-DD HH:mm:ss')
  936. };
  937. returnAbnormalList.value = [damageRecord, overdueRecord];
  938. abnormalList.value = [damageRecord, overdueRecord];
  939. }
  940. }
  941. } catch (e) {
  942. console.log("审判失败:::",e)
  943. ElMessage.error('获取审批信息失败');
  944. }
  945. }else if(val&& isEdit.value){
  946. try {
  947. const res = await api.GetApplicationDetail(val.id);
  948. if (res.code === 2000 && res.data) {
  949. const data = res.data;
  950. Object.assign(form.value, data);
  951. // 同步 form.items 到 returnDeviceList
  952. if (form.value.items && form.value.items.length > 0) {
  953. returnDeviceList.value = form.value.items
  954. .filter(item => item.device !== null)
  955. .map(item => ({
  956. device_no: item.device,
  957. device_type: item.remark,
  958. device_name: item.device_name,
  959. borrow_count: item.quantity,
  960. brand: '',
  961. model: item.device_specification,
  962. warehouse: item.location,
  963. problem_records: item.problem_records,
  964. return_status:item.return_status,
  965. return_time:item.return_times
  966. }));
  967. }
  968. }
  969. } catch (e) {
  970. ElMessage.error('获取审批信息失败');
  971. }
  972. }
  973. }, { immediate: true });
  974. // watch(
  975. // () => props.modelValue,
  976. // (v) => {
  977. // if (v) {
  978. // // eslint-disable-next-line no-console
  979. // console.log("val:::::",v);
  980. // Object.assign(form.value, v);
  981. // }
  982. // }, { immediate: true }
  983. // );
  984. // 监听借用人选择变化
  985. watch(() => form.value.app_user_borrower, (newValue) => {
  986. if (newValue && allUserList.value.length > 0) {
  987. const selectedUser = allUserList.value.find(user => user.id === newValue);
  988. if (selectedUser) {
  989. form.value.user_code = selectedUser.user_code || '';
  990. form.value.mobile = selectedUser.mobile || '';
  991. }
  992. }
  993. });
  994. function addItem() {
  995. showSelectDeviceDialog.value = true;
  996. }
  997. function removeItem(index: number) {
  998. form.value.items.splice(index, 1);
  999. }
  1000. function onCancel() {
  1001. // 重置标签页到第一个
  1002. activeName.value = 'first';
  1003. // 清理异常记录列表
  1004. returnAbnormalList.value = [];
  1005. abnormalList.value = [];
  1006. // 清理设备列表
  1007. deviceList.value = [];
  1008. returnDeviceList.value = [];
  1009. // 清理搜索框
  1010. searchText.value = '';
  1011. returnSearchText.value = '';
  1012. // 清理备注
  1013. remark.value = '';
  1014. returnRemark.value = '';
  1015. // 重置状态
  1016. returnStatus.value = '未归还';
  1017. // 清理选中的设备
  1018. selectedDevices.value = [];
  1019. // 关闭所有对话框
  1020. showSelectDeviceDialog.value = false;
  1021. showSettlementDialog.value = false;
  1022. showAbnormalDialog.value = false;
  1023. showViewAbnormalDialog.value = false;
  1024. // 重置当前异常数据
  1025. currentAbnormalData.value = {
  1026. condition: '',
  1027. photos: []
  1028. };
  1029. // 发出关闭事件
  1030. emit('update:visible', false);
  1031. }
  1032. // 提交时合并数据
  1033. function onSubmit() {
  1034. if(isCollect.value){
  1035. // 验证是否有设备信息
  1036. const hasDevicesInFirstTab = form.value.items && form.value.items.length > 0;
  1037. const hasDevicesInSecondTab = deviceList.value && deviceList.value.length > 0;
  1038. if (!hasDevicesInFirstTab && !hasDevicesInSecondTab) {
  1039. ElMessage.warning('请添加设备信息后再提交');
  1040. activeName.value = 'second'; // 自动切换到借用列表标签页
  1041. return;
  1042. }
  1043. // 验证设备数量
  1044. const hasInvalidQuantityInFirstTab = form.value.items.some(item => !item.quantity || item.quantity <= 0);
  1045. const hasInvalidQuantityInSecondTab = deviceList.value.some(item => !item.borrow_count || item.borrow_count <= 0);
  1046. if (hasInvalidQuantityInFirstTab || hasInvalidQuantityInSecondTab) {
  1047. ElMessage.warning('请确保所有设备的数量大于0');
  1048. activeName.value = 'second'; // 自动切换到借用列表标签页
  1049. return;
  1050. }
  1051. // 合并两个标签页的设备数据
  1052. const allDevices = [
  1053. ...deviceList.value.map(item => ({
  1054. condition: remark.value,
  1055. quantity: item.borrow_count,
  1056. device_id: Number(item.device_no) || 0
  1057. }))
  1058. ];
  1059. const submitData = {
  1060. id:form.value.id,
  1061. item_id:form.value.id,
  1062. device_assignments: allDevices,
  1063. remark:remark.value,
  1064. accessories:form.value.accessories,
  1065. };
  1066. CollectEquipment(submitData).then((res: ApiResponse) => {
  1067. if(res.code===2000){
  1068. ElMessage.success("领取成功");
  1069. // 准备结算单数据
  1070. settlementData.value = {
  1071. ...form.value,
  1072. items: deviceList.value.map(item => ({
  1073. ...item,
  1074. device_category_name: item.device_type,
  1075. device_name: item.device_name,
  1076. device_specification: item.device_specification,
  1077. device_storage_location: item.warehouse,
  1078. remark: item.device_type,
  1079. quantity: item.borrow_count,
  1080. device_id: item.device_no,
  1081. device_category: item.device_type,
  1082. device_code: item.device_no,
  1083. borrow_type: form.value.borrow_type,
  1084. borrower_dept: form.value.borrower_dept,
  1085. emergency_contact: form.value.emergency_contact,
  1086. emergency_phone: form.value.emergency_phone,
  1087. team_type: form.value.team_type,
  1088. })),
  1089. accessory_info: accessoryInfo.value,
  1090. remark: remark.value,
  1091. expected_start_time: dayjs().format('YYYY-MM-DD HH:mm:ss')
  1092. };
  1093. // 先触发提交事件进行页面刷新
  1094. emit('submit');
  1095. // 关闭当前对话框
  1096. emit('update:visible', false);
  1097. // 使用 nextTick 确保在 DOM 更新后再显示结算单
  1098. nextTick(() => {
  1099. showSettlementDialog.value = true;
  1100. });
  1101. }
  1102. });
  1103. } else {
  1104. // 归还逻辑修改
  1105. // 使用所有设备列表而不是选中的设备
  1106. const allDevices = returnDeviceList.value
  1107. .filter(item => item.is_return === true) // 只选择 return_status 为 2 的设备
  1108. .map(item => ({
  1109. device: item.device_no,
  1110. quantity: item.borrow_count,
  1111. remark: returnRemark.value,
  1112. device_id: Number(item.device_no) || 0,
  1113. // 添加异常相关字段
  1114. condition: item.condition, // 异常说明
  1115. photo_urls: item.photos || [], // 异常照片
  1116. }));
  1117. const submitData = {
  1118. id: form.value.id,
  1119. items: allDevices,
  1120. status: returnStatus.value,
  1121. accessories: form.value.accessories,
  1122. };
  1123. ReturnEquipment(submitData).then(async (res: ApiResponse) => {
  1124. if(res.code===2000){
  1125. ElMessage.success("归还成功");
  1126. try {
  1127. if (form.value.id) {
  1128. const detailRes = await api.GetApplicationDetail(form.value.id);
  1129. if (detailRes.code === 2000 && detailRes.data) {
  1130. returnStatus.value = detailRes.data.status_label || returnStatus.value;
  1131. }
  1132. }
  1133. } catch (e) {
  1134. ElMessage.error('获取最新状态失败');
  1135. }
  1136. emit('submit');
  1137. emit('update:visible', false);
  1138. }
  1139. });
  1140. }
  1141. }
  1142. function clickReturn(){
  1143. returnStatus.value = '已归还';
  1144. // 自动选择所有设备
  1145. const tableRef = document.querySelector('.el-table__header-wrapper th.el-table__cell.is-leaf .el-checkbox');
  1146. if (tableRef) {
  1147. (tableRef as HTMLElement).click();
  1148. }
  1149. }
  1150. /* formRef.value.validate((valid: boolean) => {
  1151. if (valid) {
  1152. form.value.items = form.value.items.map(item => ({
  1153. ...item,
  1154. quantity: Number(item.quantity) || 0
  1155. }));
  1156. const firstLocation = form.value.items[0]?.location || '';
  1157. form.value.return_location = firstLocation;
  1158. form.value.expected_start_time = now;
  1159. form.value.expected_end_time = dayjs(form.value.expected_end_time).format('YYYY-MM-DD HH:mm:ss')|| now;
  1160. form.team_members_count=Number(form.team_members_count)||1;
  1161. emit('submit', { ...form.value });
  1162. emit('update:visible', false);
  1163. ElMessage.success("添加成功!");
  1164. }
  1165. }); */
  1166. </script>