index.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. <template>
  2. <div class="app-container">
  3. <el-radio-group v-model="tabPosition" style="margin: 5px">
  4. <el-radio-button label="first">物资柜位置</el-radio-button>
  5. <el-radio-button label="second">物资柜列表</el-radio-button>
  6. </el-radio-group>
  7. <!-- 优化后带样式的无数据提示盒子 -->
  8. <div
  9. v-if="jobconfig.imageUrl==''"
  10. style="
  11. position: absolute;
  12. top: 40%;
  13. left: 40%;
  14. font-size: 18px;
  15. color: #666;
  16. text-align: center;
  17. "
  18. >
  19. 暂无数据,请到基础数据菜单进行配置
  20. </div>
  21. <div
  22. style="
  23. display: flex;
  24. justify-content: center;
  25. align-items: center;
  26. position: relative;
  27. "
  28. v-show="tabPosition == 'first'"
  29. >
  30. <!-- 缩放容器 -->
  31. <div
  32. ref="mapContainer"
  33. :style="{
  34. transform: `scale(${scaleFactor})`,
  35. transformOrigin: 'top left',
  36. width: '1250px',
  37. height: '700px',
  38. position: 'relative',
  39. }"
  40. >
  41. <img
  42. :style="{width:jobconfig.width+'px',height:jobconfig.height+'px'}"
  43. :src="jobconfig.imageUrl"
  44. alt=""
  45. />
  46. <!-- <img-->
  47. <!-- v-for="(cabinet, index) in TicketListPage"-->
  48. <!-- :key="cabinet.cabinetId"-->
  49. <!-- :style="{-->
  50. <!-- width: '35px',-->
  51. <!-- height: '35px',-->
  52. <!-- position: 'absolute',-->
  53. <!-- cursor: 'pointer',-->
  54. <!-- // 图标垂直居中-->
  55. <!-- top: `${deptXLGCenter.top - 53}px`,-->
  56. <!-- // 图标水平居中,动态计算偏移-->
  57. <!-- left: `${-->
  58. <!-- deptXLGCenter.left - -->
  59. <!-- (TicketListPage.length * 35 + (TicketListPage.length - 1) * 5) /-->
  60. <!-- 2 +-->
  61. <!-- index * 40-->
  62. <!-- }px`,-->
  63. <!-- }"-->
  64. <!-- :src="require(`@/assets/images/${imageMap[cabinet.status]}.jpg`)"-->
  65. <!-- alt=""-->
  66. <!-- @click="handleCabinetClick(cabinet)"-->
  67. <!-- />-->
  68. <div v-for="(item, index) in jobconfigPoint.records" :key="item.id">
  69. <div
  70. class="deptXLG"
  71. :style="{left:item.x+'px',top:item.y+'px'}"
  72. >
  73. {{ item.entityName }}
  74. </div>
  75. <!-- // 使图标位于岗位上方-->
  76. <img
  77. v-for="(cabinet, index) in TicketListPage[item.entityId] || []"
  78. :key="cabinet.cabinetId"
  79. :style="{
  80. width: '35px',
  81. height: '35px',
  82. position: 'absolute',
  83. cursor: 'pointer',
  84. top: (item.y - 40) + 'px', // 让图标浮在岗位的上方
  85. left: (
  86. item.x -
  87. ((TicketListPage[item.entityId] ? TicketListPage[item.entityId].length * 35 : 0) - 53) / 2 + // 计算总宽度并居中,减去单个图标宽度,确保居中
  88. index * 40 // 处理图标间隔
  89. ) + 'px'
  90. }"
  91. :src="imageMap[cabinet.status]"
  92. alt=""
  93. @click="handleCabinetClick(cabinet)"
  94. />
  95. </div>
  96. <!-- 左侧警告部分内容-->
  97. <img style="width: 40px;height: 40px;position: absolute;top:2%;right: -4%" :src="this.ExceptionTableImage"
  98. alt=""
  99. @click="showExTable"
  100. >
  101. <div v-if="exceptionTableVisible"
  102. style="width: 430px;height: 300px;position: absolute;top:2%;right:0;background: white "
  103. >
  104. <div style="display: flex">
  105. <img :src="this.ExceptionTableImage2" style="width: 20px;height: 20px;margin: 10px" alt="">
  106. <span style="margin: 10px">异常信息</span>
  107. </div>
  108. <el-table :data="exceptionTable">
  109. <el-table-column label="物资柜" prop="loanFromName"></el-table-column>
  110. <el-table-column label="异常类型" prop="exceptionType"></el-table-column>
  111. <el-table-column label="异常信息" prop="status"></el-table-column>
  112. </el-table>
  113. </div>
  114. </div>
  115. </div>
  116. <!-- 物资列表 -->
  117. <div v-if="tabPosition == 'second'" class="CabinetListcon">
  118. <div class="left">
  119. <!-- 岗位树 -->
  120. <div class="deptTree">
  121. <div class="head-container">
  122. <el-input
  123. v-model="queryParams.workstationName"
  124. placeholder="请输入区域名称"
  125. clearable
  126. size="small"
  127. prefix-icon="el-icon-search"
  128. style="margin-bottom: 20px"
  129. @clear="handleClear"
  130. />
  131. </div>
  132. <div class="head-container">
  133. <el-tree
  134. :data="workstationOptions"
  135. :props="defaultProps"
  136. :expand-on-click-node="false"
  137. :filter-node-method="filterNode"
  138. ref="treeData"
  139. node-key="id"
  140. default-expand-all
  141. @node-click="handleNodeClick"
  142. highlight-current
  143. />
  144. </div>
  145. </div>
  146. </div>
  147. <div class="right">
  148. <el-row>
  149. <el-form
  150. :model="queryParams"
  151. ref="queryForm"
  152. size="small"
  153. :inline="true"
  154. v-show="showSearch"
  155. label-width="100px"
  156. >
  157. <el-form-item label="物资柜编号" prop="cabinetId">
  158. <el-input
  159. v-model="queryParams.cabinetId"
  160. placeholder="请输入物资柜编号"
  161. clearable
  162. oninput="value=value.replace(/[^\d.]/g,'')"
  163. @keyup.enter.native="handleQuery"
  164. />
  165. </el-form-item>
  166. <el-form-item label="物资柜名称" prop="cabinetName">
  167. <el-input
  168. v-model="queryParams.cabinetName"
  169. placeholder="请输入物资柜名称"
  170. clearable
  171. @keyup.enter.native="handleQuery"
  172. />
  173. </el-form-item>
  174. <!-- <el-form-item label="物资柜状态" prop="status">-->
  175. <!-- <el-select v-model="queryParams.status" placeholder="物资柜状态">-->
  176. <!-- <el-option-->
  177. <!-- v-for="dict in dict.type.cabinet_status"-->
  178. <!-- :key="dict.value"-->
  179. <!-- :label="dict.label"-->
  180. <!-- :value="dict.value"-->
  181. <!-- />-->
  182. <!-- </el-select>-->
  183. <!-- </el-form-item>-->
  184. <el-form-item>
  185. <el-button
  186. v-no-more-click
  187. type="primary"
  188. icon="el-icon-search"
  189. size="mini"
  190. @click="handleQuery"
  191. >搜索
  192. </el-button
  193. >
  194. <el-button
  195. v-no-more-click
  196. icon="el-icon-refresh"
  197. size="mini"
  198. @click="resetQuery"
  199. >重置
  200. </el-button
  201. >
  202. </el-form-item>
  203. </el-form>
  204. </el-row>
  205. <el-row :gutter="10" class="mb8">
  206. <el-col :span="1.5">
  207. <el-button
  208. v-no-more-click
  209. type="primary"
  210. plain
  211. icon="el-icon-plus"
  212. size="mini"
  213. @click="handleAdd"
  214. v-hasPermi="['iscs:cabinet:add']"
  215. >新增
  216. </el-button>
  217. </el-col>
  218. <right-toolbar
  219. :showSearch.sync="showSearch"
  220. @queryTable="getList"
  221. ></right-toolbar>
  222. </el-row>
  223. <el-table
  224. v-loading="loading"
  225. :data="CabinetList"
  226. @selection-change="handleSelectionChange"
  227. >
  228. <!-- <el-table-column type="selection" width="55" align="center"/>-->
  229. <el-table-column label="物资柜编号" align="center" prop="cabinetId">
  230. </el-table-column>
  231. <el-table-column label="物资柜名称" prop="cabinetName" width="150"/>
  232. <el-table-column label="物资柜图片" prop="cabinetPicture" width="100">
  233. <template slot-scope="scope">
  234. <div class="img-box" v-if="scope.row.cabinetPicture">
  235. <el-image
  236. style="width: 75px; height: 75px"
  237. :preview-teleported="true"
  238. class="images"
  239. :hide-on-click-modal="true"
  240. :src="scope.row.cabinetPicture"
  241. :zoom-rate="1.2"
  242. :preview-src-list="[scope.row.cabinetPicture]"
  243. :initial-index="1"
  244. >
  245. </el-image>
  246. <i class="el-icon-zoom-in" id="eyeicon"></i>
  247. </div>
  248. <span v-else>-</span>
  249. </template>
  250. </el-table-column>
  251. <el-table-column label="物资柜状态" align="center" prop="status">
  252. <template slot-scope="scope">
  253. <dict-tag
  254. :options="dict.type.cabinet_status"
  255. :value="scope.row.status"
  256. />
  257. </template>
  258. </el-table-column>
  259. <el-table-column label="异常类型" prop="exReason" width="100">
  260. <template slot-scope="scope">
  261. <dict-tag
  262. :options="dict.type.exception_reason"
  263. :value="scope.row.exReason"
  264. />
  265. </template>
  266. </el-table-column>
  267. <el-table-column label="物资柜详情" align="center">
  268. <template slot-scope="scope">
  269. <el-button
  270. v-no-more-click
  271. size="mini"
  272. type="text"
  273. @click="handleLook(scope.row)"
  274. >查看
  275. </el-button>
  276. </template>
  277. </el-table-column>
  278. <el-table-column
  279. label="操作"
  280. align="center"
  281. class-name="small-padding fixed-width"
  282. >
  283. <template slot-scope="scope">
  284. <el-button
  285. v-no-more-click
  286. size="mini"
  287. type="text"
  288. icon="el-icon-edit"
  289. @click="handleUpdate(scope.row)"
  290. v-hasPermi="['iscs:cabinet:edit']"
  291. >修改
  292. </el-button>
  293. <el-button
  294. v-no-more-click
  295. size="mini"
  296. type="text"
  297. icon="el-icon-delete"
  298. @click="handleDelete(scope.row)"
  299. v-hasPermi="['iscs:cabinet:remove']"
  300. >删除
  301. </el-button>
  302. </template>
  303. </el-table-column>
  304. </el-table>
  305. <pagination
  306. v-show="total > 0"
  307. :total="total"
  308. :page.sync="queryParams.current"
  309. :limit.sync="queryParams.size"
  310. @pagination="getList"
  311. />
  312. </div>
  313. </div>
  314. <!-- 添加或修改物资柜对话框 -->
  315. <el-dialog :visible.sync="open" width="510px" append-to-body>
  316. <div slot="title" class="dialog-title">
  317. <i></i>
  318. <span class="title">{{ title }}</span>
  319. </div>
  320. <el-form ref="form" :model="form" :rules="rules" label-width="110px">
  321. <el-form-item label="物资柜编码" prop="cabinetCode">
  322. <el-input
  323. v-model="form.cabinetCode"
  324. placeholder="请输入物资柜编码"
  325. style="width: 200px; margin-right: 10px"
  326. />
  327. <el-switch
  328. v-model="autoGenFlag"
  329. active-color="#13ce66"
  330. active-text="自动生成"
  331. @change="handleAutoGenChange(autoGenFlag)"
  332. >
  333. </el-switch>
  334. </el-form-item>
  335. <el-form-item label="物资柜名称" prop="cabinetName">
  336. <el-input
  337. style="width: 348px"
  338. v-model="form.cabinetName"
  339. placeholder="请输入物资柜名称"
  340. />
  341. </el-form-item>
  342. <el-form-item label="所属区域" prop="workstationId">
  343. <treeselect
  344. style="width: 348px"
  345. v-model="form.workstationId"
  346. :options="marsOptions"
  347. :normalizer="Marsnormalizer"
  348. placeholder="选择所属区域"
  349. />
  350. </el-form-item>
  351. <el-form-item label="物资柜图片" prop="cabinetPicture">
  352. <ImageUploadSingle
  353. :limit="1"
  354. :value="form.cabinetPicture"
  355. :fileSize="5"
  356. @onUploaded="handleIconUplaoded"
  357. @onRemoved="handleIconRemoved"
  358. ></ImageUploadSingle>
  359. </el-form-item>
  360. <el-form-item label="备注" prop="remark">
  361. <el-input
  362. v-model="form.remark"
  363. type="textarea"
  364. placeholder="请输入内容"
  365. style="width: 348px"
  366. />
  367. </el-form-item>
  368. </el-form>
  369. <div slot="footer" class="dialog-footer">
  370. <el-button
  371. v-no-more-click
  372. type="primary"
  373. @click="cancel"
  374. v-if="optType == 'view'"
  375. >返回
  376. </el-button>
  377. <el-button v-no-more-click type="primary" @click="submitForm" v-else
  378. >确 定
  379. </el-button>
  380. <el-button v-no-more-click @click="cancel">取 消</el-button>
  381. </div>
  382. </el-dialog>
  383. </div>
  384. </template>
  385. <script>
  386. import {
  387. getMaterialsCabinet,
  388. addMaterialsCabinet,
  389. updateMaterialsCabinet,
  390. deleteMaterialsCabinet,
  391. selectMaterialsCabinetById
  392. } from '@/api/mes/material/lockers.js'
  393. import Treeselect from '@riophae/vue-treeselect'
  394. import '@riophae/vue-treeselect/dist/vue-treeselect.css'
  395. import { genCode } from '@/api/system/autocode/rule'
  396. import { listMarsDept } from '@/api/system/marsdept'
  397. import { listLoto } from '@/api/mes/lotoStation/lotoStation'
  398. import { listMaterials } from '@/api/mes/material/information'
  399. import { MaterialsLoanExceptionPage } from '@/api/mes/material/exception'
  400. import { selectIsMapById } from '@/api/system/mapconfig'
  401. import { getIsMapPointPage } from '@/api/system/mappoint'
  402. import { getIsSystemAttributeByKey } from '@/api/system/configuration'
  403. export default {
  404. name: 'Team',
  405. components: {
  406. Treeselect
  407. },
  408. dicts: ['material_status', 'cabinet_status', 'exception_reason'],
  409. data() {
  410. return {
  411. jobconfig: null,//接口传递地图与宽高数据
  412. jobconfigPoint: null,//接口传递的岗位位置信息
  413. //自动生成编码
  414. autoGenFlag: false,
  415. optType: undefined,
  416. tabPosition: 'first', //顶部切换
  417. // 遮罩层
  418. loading: true,
  419. // 选中数组
  420. ids: [],
  421. codes: [],
  422. // 非单个禁用
  423. single: true,
  424. // 非多个禁用
  425. multiple: true,
  426. // 显示搜索条件
  427. showSearch: true,
  428. // 总条数
  429. total: 0,
  430. // 班组表格数据
  431. CabinetList: [],
  432. // 弹出层标题
  433. title: '',
  434. // 是否显示弹出层
  435. open: false,
  436. // 查询参数
  437. createTime: '',
  438. queryParams: {
  439. current: 1,
  440. size: 10,
  441. workstationName: undefined,
  442. workstationId: undefined,
  443. cabinetId: null,
  444. cabinetName: null,
  445. status: null
  446. },
  447. // queryParamsList: {
  448. // current: 1,
  449. // size: 10,
  450. // cabinetId: null,
  451. // cabinetName: null,
  452. // status: null,
  453. // },
  454. imageMap: {
  455. 0: 'table_map2', //正常
  456. 1: 'table_map1', //使用中
  457. 2: 'table_map3' //异常
  458. },
  459. pickerOptions: {
  460. shortcuts: [
  461. {
  462. text: '最近一周',
  463. onClick(picker) {
  464. const end = new Date()
  465. const start = new Date()
  466. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
  467. picker.$emit('pick', [start, end])
  468. }
  469. },
  470. {
  471. text: '最近一个月',
  472. onClick(picker) {
  473. const end = new Date()
  474. const start = new Date()
  475. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
  476. picker.$emit('pick', [start, end])
  477. }
  478. },
  479. {
  480. text: '最近三个月',
  481. onClick(picker) {
  482. const end = new Date()
  483. const start = new Date()
  484. start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
  485. picker.$emit('pick', [start, end])
  486. }
  487. }
  488. ]
  489. },
  490. // 表单参数
  491. form: {},
  492. // 表单校验
  493. rules: {
  494. cabinetCode: [
  495. { required: true, message: '物资柜编码不能为空', trigger: 'blur' }
  496. ],
  497. cabinetName: [
  498. { required: true, message: '物资柜名称不能为空', trigger: 'blur' }
  499. ]
  500. },
  501. marsOptions: [], //岗位
  502. TicketListPage: [], //R&R岗位
  503. scaleFactor: 1, // 缩放比例,初始值为1
  504. exceptionTableVisible: false,//地图显示异常物资柜具体信息
  505. exceptionTable: [],//地图异常数据table数据
  506. workstationOptions: [], //岗位
  507. defaultProps: {
  508. children: 'children',
  509. label: 'label'
  510. },
  511. sysAttrValue: null,//从基础数据接口里拿到物资柜底图的mapId
  512. ExceptionTableImage: '',//列表异常的图标
  513. ExceptionTableImage2: ''//列表异常的图标2
  514. }
  515. },
  516. watch: {
  517. 'queryParams.workstationId': function(newVal, oldVal) {
  518. if (newVal) {
  519. const data = {
  520. current: 1,
  521. size: -1,
  522. workstationId: this.queryParams.workstationId
  523. }
  524. getMaterialsCabinet(data).then((response) => {
  525. this.CabinetList = response.data.records
  526. })
  527. }
  528. },
  529. tabPosition: function(newVal, oldVal) {
  530. if (newVal) {
  531. this.getList()
  532. }
  533. }
  534. },
  535. created() {
  536. this.getList()
  537. this.getOtherList()
  538. this.getExpection()
  539. },
  540. methods: {
  541. // 显示异常的物资柜信息
  542. showExTable() {
  543. this.exceptionTableVisible = !this.exceptionTableVisible
  544. },
  545. /** 查询物资柜信息列表 */
  546. getList() {
  547. this.loading = true
  548. getMaterialsCabinet(this.queryParams).then((response) => {
  549. this.CabinetList = response.data.records
  550. console.log(response, '所有物资柜')
  551. this.total = response.data.total
  552. this.loading = false
  553. })
  554. const sysAttrKey1 = 'icon.cabinet.normal'
  555. const sysAttrKey2 = 'icon.cabinet.borrowed'
  556. const sysAttrKey3 = 'icon.cabinet.abnormal'
  557. const sysAttrKey4 = 'sys.exception.icon'
  558. const sysAttrKey5 = 'sys.exception2.icon'
  559. Promise.all([
  560. getIsSystemAttributeByKey(sysAttrKey1),
  561. getIsSystemAttributeByKey(sysAttrKey2),
  562. getIsSystemAttributeByKey(sysAttrKey3),
  563. getIsSystemAttributeByKey(sysAttrKey4),
  564. getIsSystemAttributeByKey(sysAttrKey5)
  565. ]).then((responses) => {
  566. this.imageMap[0] = responses[0].data.sysAttrValue // 正常
  567. this.imageMap[1] = responses[1].data.sysAttrValue // 使用中
  568. this.imageMap[2] = responses[2].data.sysAttrValue // 异常
  569. this.ExceptionTableImage = responses[3].data.sysAttrValue
  570. this.ExceptionTableImage2 = responses[4].data.sysAttrValue
  571. console.log(this.imageMap, this.ExceptionTableImage, this.ExceptionTableImage2, 'imageMap')
  572. })
  573. },
  574. getExpection() {
  575. // 调用 listMaterials 接口获取所有物资的信息
  576. listMaterials({ pages: 1, size: -1 }).then(response => {
  577. const materialsData = response.data.records || []
  578. // 处理损坏、过期的物资
  579. const damagedOrExpiredMaterials = materialsData.filter(material => material.status === '1' || material.status === '2')
  580. const damagedOrExpiredCabinets = Array.from(new Set(damagedOrExpiredMaterials.map(material => material.cabinetName)))
  581. console.log(damagedOrExpiredMaterials, 'damagedOrExpiredMaterials')
  582. // 处理归还异常的物资
  583. const misplacedMaterials = materialsData.filter(material => material.status === '3')
  584. const misplacedCabinets = Array.from(new Set(misplacedMaterials.map(material => material.cabinetName)))
  585. console.log(misplacedCabinets, 'misplacedCabinets')
  586. // 整合归还异常的柜子信息
  587. const misplacedCabinetDetails = misplacedCabinets.map(cabinet => ({
  588. loanFromName: cabinet,
  589. exceptionType: '物资放错柜子',
  590. status: `${misplacedMaterials.filter(material => material.cabinetName === cabinet).length}件物资放错`
  591. }))
  592. // 整合损坏、过期的柜子信息
  593. const damagedOrExpiredCabinetDetails = damagedOrExpiredCabinets.map(cabinet => ({
  594. loanFromName: cabinet,
  595. exceptionType: '物资过期损坏',
  596. status: `${damagedOrExpiredMaterials.filter(material => material.cabinetName === cabinet).length}件物资过期或损坏`
  597. }))
  598. // 调用 MaterialsLoanExceptionPage 接口获取柜门未关闭的数据
  599. return MaterialsLoanExceptionPage({
  600. pages: 1,
  601. size: -1,
  602. exceptionType: 1, // 1表示柜门未关
  603. status: 0 // 0表示未处理
  604. }).then(response1 => {
  605. const unClosedCabinets = response1.data.records || []
  606. if (unClosedCabinets) {
  607. // 整合柜门未关闭的柜子信息
  608. const unClosedCabinetDetails = unClosedCabinets.map(cabinet => ({
  609. loanFromName: cabinet.loanFromName,
  610. exceptionType: '超时未关柜门',
  611. status: `柜门超过${this.calculateTimeDifference(cabinet.occurTime)}未关`
  612. }))
  613. // 合并所有结果
  614. const result = [
  615. ...misplacedCabinetDetails,
  616. ...damagedOrExpiredCabinetDetails,
  617. ...unClosedCabinetDetails
  618. ]
  619. const resultData = result.filter((item) => {
  620. return item.loanFromName !== null
  621. })
  622. this.exceptionTable = resultData
  623. } else {
  624. // 合并所有结果
  625. const result = [
  626. ...misplacedCabinetDetails,
  627. ...damagedOrExpiredCabinetDetails
  628. ]
  629. const resultData = result.filter((item) => {
  630. return item.loanFromName !== null
  631. })
  632. this.exceptionTable = resultData
  633. }
  634. })
  635. }).catch(error => {
  636. console.error('Error fetching data:', error)
  637. })
  638. },
  639. getOtherList() {
  640. const data = {
  641. pasge: 1,
  642. size: -1
  643. }
  644. getMaterialsCabinet(data).then((response) => {
  645. console.log(response, '所有物资柜')
  646. let cabinetByWorkstation = {}
  647. response.data.records.forEach((cabinet) => {
  648. if (!cabinetByWorkstation[cabinet.workstationId]) {
  649. cabinetByWorkstation[cabinet.workstationId] = []
  650. }
  651. cabinetByWorkstation[cabinet.workstationId].push(cabinet)
  652. })
  653. this.TicketListPage = cabinetByWorkstation
  654. this.total = response.data.total
  655. this.loading = false
  656. })
  657. listMarsDept(data).then((response) => {
  658. // 新增岗位单选
  659. const data = response.data.records.filter((item) => {
  660. return item.parentId == '0'
  661. })
  662. this.marsOptions = this.handleTree(data, 'workstationId', 'parentId')
  663. // mars岗位树数据
  664. this.workstationOptions = this.transformToTree(data)
  665. // 使用递归函数查找匹配的节点
  666. const selectedTreeNode = this.findNodeById(
  667. this.workstationOptions,
  668. this.queryParams.workstationId
  669. )
  670. // 调用 handleNodeClick 方法
  671. if (selectedTreeNode) {
  672. this.handleNodeClick(selectedTreeNode)
  673. } else {
  674. console.log('未找到匹配的节点')
  675. }
  676. })
  677. // 获取物资柜地图与物资柜对应状态的柜子图片
  678. const sysAttrKey = 'sys.map.cabinet'
  679. getIsSystemAttributeByKey(sysAttrKey).then(response => {
  680. console.log(response, '获取物资柜底图')
  681. this.sysAttrValue = response.data.sysAttrValue
  682. // 这里获取全局配置地图参数里的作业票地图
  683. selectIsMapById(this.sysAttrValue).then((res) => {
  684. console.log(res, '作业票地图 图片数据')
  685. this.jobconfig = res.data
  686. })
  687. })
  688. const dataMap = {
  689. pages: 1,
  690. size: -1,
  691. mapId: 4
  692. }
  693. getIsMapPointPage(dataMap).then((res) => {
  694. console.log(res, '作业票地图岗位位置信息接口')
  695. this.jobconfigPoint = res.data
  696. })
  697. },
  698. //辅助函数计算超时时间
  699. calculateTimeDifference(occurTime) {
  700. if (!occurTime) return '未知'
  701. // 将时间字符串转换为 Date 对象
  702. const occurDate = new Date(occurTime)
  703. if (isNaN(occurDate.getTime())) {
  704. console.error('Invalid date format:', occurTime)
  705. return '未知'
  706. }
  707. const currentTime = new Date().getTime()
  708. const timeDifference = (currentTime - occurDate.getTime()) / (1000 * 60) // 转换为分钟
  709. if (timeDifference < 1) {
  710. return `${(timeDifference * 60).toFixed(0)}秒`
  711. } else if (timeDifference < 60) {
  712. return `${timeDifference.toFixed(1)}分钟`
  713. } else {
  714. const hours = Math.floor(timeDifference / 60)
  715. const minutes = (timeDifference % 60).toFixed(0)
  716. return `${hours}小时${minutes}分钟`
  717. }
  718. },
  719. // mars岗位树点击事件
  720. handleNodeClick(data) {
  721. this.queryParams.workstationId = data.id //这里给查询传递参数
  722. this.queryParams.workstationName = data.label //这里给回显框显示中文
  723. },
  724. /** 转换mars岗位树数据为树形结构 */
  725. transformToTree(records) {
  726. const recordMap = {} // 创建一个 Map 以存储所有记录
  727. const tree = [] // 最终返回的树形结构
  728. // 初始化所有记录到 Map
  729. records.forEach((record) => {
  730. recordMap[record.workstationId] = {
  731. id: record.workstationId,
  732. label: record.workstationName,
  733. children: []
  734. }
  735. })
  736. // 遍历记录并构建树
  737. records.forEach((record) => {
  738. const parentId = record.parentId
  739. if (parentId === '0') {
  740. // 如果是顶层节点,直接添加到树中
  741. tree.push(recordMap[record.workstationId])
  742. } else if (recordMap[parentId]) {
  743. // 如果有父节点,则将当前节点加入父节点的 children 中
  744. recordMap[parentId].children.push(recordMap[record.workstationId])
  745. }
  746. })
  747. return tree
  748. },
  749. // mars岗位数深层次遍历
  750. findNodeById(nodes, targetId) {
  751. for (let i = 0; i < nodes.length; i++) {
  752. const node = nodes[i]
  753. if (node.id === targetId) {
  754. return node
  755. }
  756. if (node.children && node.children.length > 0) {
  757. const foundNode = this.findNodeById(node.children, targetId)
  758. if (foundNode) {
  759. return foundNode
  760. }
  761. }
  762. }
  763. return null
  764. },
  765. /** 转换mars岗位数据结构 */
  766. Marsnormalizer(node) {
  767. if (node.children && !node.children.length) {
  768. delete node.children
  769. }
  770. return {
  771. id: node.workstationId,
  772. label: node.workstationName,
  773. children: node.children
  774. }
  775. },
  776. // 筛选节点
  777. filterNode(value, data) {
  778. if (!value) return true
  779. return data.label.indexOf(value) !== -1
  780. },
  781. // 岗位查询 清除事件
  782. handleClear() {
  783. this.queryParams.workstationId = ''
  784. this.queryParams.workstationName = ''
  785. this.getList()
  786. },
  787. // 物资柜跳转详情
  788. handleCabinetClick(cabinet) {
  789. this.$router.push({
  790. path: '/mes/material/lockers/DetailsIndex',
  791. query: {
  792. cabinetId: cabinet.cabinetId,
  793. cabinetName: cabinet.cabinetName
  794. }
  795. })
  796. console.log(cabinet, '地图跳转详情拿到的')
  797. },
  798. // 物资柜列表跳转详情
  799. handleLook(row) {
  800. this.$router.push({
  801. path: '/mes/material/lockers/DetailsIndex',
  802. query: { cabinetId: row.cabinetId, cabinetName: row.cabinetName }
  803. })
  804. console.log('列表详情')
  805. },
  806. // 取消按钮
  807. cancel() {
  808. this.open = false
  809. this.reset()
  810. },
  811. // 表单重置
  812. reset() {
  813. this.form = {
  814. cabinetCode: '',
  815. cabinetName: '',
  816. workstationId: '',
  817. remark: '',
  818. cabinetPicture: ''
  819. }
  820. this.resetForm('form')
  821. this.autoGenFlag = false
  822. },
  823. /** 搜索按钮操作 */
  824. handleQuery() {
  825. this.queryParams.current = 1
  826. this.getList()
  827. },
  828. /** 重置按钮操作 */
  829. resetQuery() {
  830. this.createTime = ''
  831. this.queryParams.cabinetCode = null
  832. this.queryParams.cabinetName = null
  833. this.queryParams.cabinetId = null
  834. this.queryParams.status = null
  835. this.resetForm('queryForm')
  836. this.handleQuery()
  837. },
  838. // 多选框选中数据
  839. handleSelectionChange(selection) {
  840. this.ids = selection.map((item) => item.cabinetId)
  841. this.codes = selection.map((item) => item.cabinetCode)
  842. this.single = selection.length !== 1
  843. this.multiple = !selection.length
  844. },
  845. /** 新增按钮操作 */
  846. handleAdd() {
  847. this.reset()
  848. this.open = true
  849. this.form.workstationId = null
  850. this.title = '新增物资柜信息'
  851. this.optType = 'add'
  852. },
  853. /** 修改按钮操作 */
  854. handleUpdate(row) {
  855. this.reset()
  856. selectMaterialsCabinetById(row.cabinetId).then((response) => {
  857. this.form = response.data
  858. this.open = true
  859. this.title = '修改物资柜信息'
  860. this.optType = 'edit'
  861. })
  862. },
  863. /** 提交按钮 */
  864. submitForm() {
  865. this.$refs['form'].validate((valid) => {
  866. if (valid) {
  867. if (this.form.cabinetId != null) {
  868. updateMaterialsCabinet(this.form).then((response) => {
  869. console.log(response, '修改返回')
  870. this.$modal.msgSuccess('修改成功')
  871. this.open = false
  872. this.getList()
  873. })
  874. } else {
  875. addMaterialsCabinet(this.form).then((response) => {
  876. console.log(response, '新增返回')
  877. this.$modal.msgSuccess('新增成功')
  878. this.open = false
  879. this.getList()
  880. })
  881. }
  882. }
  883. })
  884. },
  885. /** 删除按钮操作 */
  886. handleDelete(row) {
  887. const cabinetIds = row.cabinetId || this.ids
  888. const cabinetCodes = row.cabinetCode || this.codes
  889. this.$modal
  890. .confirm('是否确认删除所选数据项?')
  891. .then(function() {
  892. return deleteMaterialsCabinet(cabinetIds)
  893. })
  894. .then(() => {
  895. this.getList()
  896. this.$modal.msgSuccess('删除成功')
  897. })
  898. .catch(() => {
  899. })
  900. },
  901. //图标上传成功
  902. handleIconUplaoded(imgUrl) {
  903. this.form.cabinetPicture = imgUrl[0].url
  904. },
  905. // 图标移除
  906. handleIconRemoved(imgUrl) {
  907. this.form.cabinetPicture = null
  908. },
  909. //自动生成编码
  910. handleAutoGenChange(autoGenFlag) {
  911. if (autoGenFlag) {
  912. genCode('MATERIALS_CABINET').then((response) => {
  913. this.form.cabinetCode = response
  914. })
  915. } else {
  916. this.form.cabinetCode = null
  917. }
  918. }
  919. }
  920. }
  921. </script>
  922. <style lang="scss" src="@/assets/styles/dialog-title.scss" scoped>
  923. </style>
  924. <style scoped lang="scss">
  925. .deptXLG {
  926. position: absolute;
  927. width: 65px;
  928. height: 25px;
  929. background: #70b26f;
  930. line-height: 25px;
  931. text-align: center;
  932. border-radius: 5px;
  933. color: #fff;
  934. cursor: pointer;
  935. }
  936. //图片放大
  937. .img-box {
  938. width: 75px;
  939. height: 75px;
  940. position: relative;
  941. #eyeicon {
  942. display: none;
  943. }
  944. }
  945. .img-box:hover {
  946. background: #000;
  947. .images {
  948. opacity: 0.6;
  949. }
  950. #eyeicon {
  951. display: block;
  952. position: absolute;
  953. top: 40%;
  954. left: 40%;
  955. z-index: 100;
  956. color: white;
  957. pointer-events: none;
  958. }
  959. }
  960. .el-input-width {
  961. width: 380px !important;
  962. }
  963. .app-container {
  964. width: 100%;
  965. height: 100%;
  966. // background: green;
  967. .CabinetListcon {
  968. width: 100%;
  969. height: 100%;
  970. display: flex;
  971. // background: pink;
  972. .left {
  973. width: 15%;
  974. height: 100%;
  975. margin-right: 10px;
  976. // background: rgb(175, 214, 175);
  977. .deptTree {
  978. width: 100%;
  979. height: 90%;
  980. // background: rgb(199, 252, 247);
  981. }
  982. }
  983. .right {
  984. width: 83%;
  985. height: 100%;
  986. // background: yellow;
  987. }
  988. }
  989. }
  990. </style>