index.vue 82 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781
  1. <template>
  2. <div class="main-container">
  3. <ibps-container
  4. class="page"
  5. >
  6. <template>
  7. <ibps-crud
  8. key="istree"
  9. ref="crud"
  10. :data="listData"
  11. :toolbars="listConfig.toolbars"
  12. :search-form="listConfig.searchForm"
  13. :pk-key="pkKey"
  14. :columns="listConfig.columns"
  15. :loading="loading"
  16. :pagination="pagination"
  17. :display-field="tableTitle"
  18. :index-row="false"
  19. @sort-change="handleSortChange"
  20. @action-event="handleAction"
  21. @pagination-change="handlePaginationChange"
  22. >
  23. <template
  24. slot="posSlot"
  25. slot-scope="{row}"
  26. >
  27. <ibps-user-selector
  28. v-model="row.bianZhiBuMen"
  29. type="position"
  30. readonly-text="text"
  31. :multiple="false"
  32. :disabled="true"
  33. />
  34. </template>
  35. <template
  36. slot="userSlot"
  37. slot-scope="{row}"
  38. >
  39. <ibps-user-selector
  40. v-model="row.guanLiRen"
  41. type="user"
  42. readonly-text="text"
  43. :multiple="true"
  44. :disabled="true"
  45. />
  46. </template>
  47. <template
  48. slot="deviceSlot"
  49. slot-scope="{row}"
  50. >
  51. <ibps-custom-dialog
  52. v-model="row.weiHuFangShi"
  53. size="mini"
  54. template-key="sbbqdhk"
  55. multiple
  56. :disabled="true"
  57. type="dialog"
  58. class="custom-dialog"
  59. placeholder="请选择"
  60. icon="el-icon-search"
  61. />
  62. </template>
  63. <template
  64. slot="deviceStateSlot"
  65. slot-scope="{row}"
  66. >
  67. <span>{{ stateList[row.sheBeiZhuangTa] || row.sheBeiZhuangTa || '' }}</span>
  68. </template>
  69. <template
  70. slot="deviceTypeSlot"
  71. slot-scope="{row}"
  72. >
  73. <span>{{ typeList[row.sheBeiLeiXing] || row.sheBeiLeiXing || '' }}</span>
  74. </template>
  75. <template
  76. slot="placeSlot"
  77. slot-scope="{row}"
  78. >
  79. <ibps-custom-dialog
  80. v-model="row.cunFangWeiZhi"
  81. size="mini"
  82. template-key="fjxzkdd"
  83. multiple
  84. :disabled="true"
  85. type="dialog"
  86. class="custom-dialog"
  87. placeholder="请选择"
  88. icon="el-icon-search"
  89. />
  90. </template>
  91. <template
  92. slot="customButton"
  93. slot-scope="{row}"
  94. >
  95. <el-button type="text" :icon="hasRole?'el-icon-edit-outline':'ibps-icon-eye'" @click="goEdit(row)">{{ hasRole?'修改':'查阅' }}</el-button>
  96. <!-- <el-button type="text" icon="el-icon-view" @click="goLook(row)">查阅</el-button> -->
  97. <el-button type="text" icon="ibps-icon-table" @click="goLookForm(row)">表单</el-button>
  98. </template>
  99. <template
  100. slot="expandSlot"
  101. slot-scope="{row}"
  102. >
  103. <el-row :gutter="20" style="height:145px;padding:0 20px 0 0" type="flex" align="middle">
  104. <el-col :span="5" :push="2">
  105. <el-row>
  106. <el-col :span="3">
  107. <el-image
  108. class="icon-image"
  109. :src="images[0]"
  110. fit="contain"
  111. />
  112. </el-col>
  113. <el-col :span="21">
  114. <div class="title">验收信息</div>
  115. <div class="ctx">
  116. <div class="item">接收日期:{{ row.jieShouRiQi || '/' }}</div>
  117. <div class="item">验收日期:{{ row.yanShouRiQi || '/' }}</div>
  118. <div class="item">核查日期:{{ row.biXuSheShi || '/' }}</div>
  119. </div>
  120. </el-col>
  121. </el-row>
  122. </el-col>
  123. <el-col :span="5" :push="2">
  124. <el-row>
  125. <el-col :span="3">
  126. <el-image
  127. class="icon-image"
  128. :src="images[1]"
  129. fit="contain"
  130. />
  131. </el-col>
  132. <el-col :span="21">
  133. <div class="title">建档信息</div>
  134. <div class="ctx">
  135. <div class="item">
  136. <div class="cusitem">
  137. <span class="span">建档人:</span>
  138. <ibps-user-selector
  139. :value="row.bianZhiRen"
  140. type="user"
  141. readonly-text="text"
  142. :multiple="true"
  143. :disabled="true"
  144. size="mini"
  145. style="width:100px"
  146. />
  147. </div>
  148. </div>
  149. <div class="item">
  150. <div class="cusitem">
  151. <span class="span">建档部门:</span>
  152. <ibps-user-selector
  153. :value="row.bianZhiBuMen"
  154. type="position"
  155. readonly-text="text"
  156. :disabled="true"
  157. :multiple="false"
  158. size="mini"
  159. style="width:100px"
  160. />
  161. </div>
  162. </div>
  163. <div class="item">建档时间:{{ row.bianZhiShiJian || '/' }}</div>
  164. </div>
  165. </el-col>
  166. </el-row>
  167. </el-col>
  168. <el-col :span="5" :push="2">
  169. <el-row>
  170. <el-col :span="3">
  171. <el-image
  172. class="icon-image"
  173. :src="images[2]"
  174. fit="contain"
  175. />
  176. </el-col>
  177. <el-col :span="21">
  178. <div class="title">维护信息</div>
  179. <div class="ctx">
  180. <div class="item">是否维护:{{ row.shiFouWeiHu || '/' }}</div>
  181. <div class="item">是否24H开机:{{ row.jianKongYiJu || '/' }}</div>
  182. <div class="item">是否限用:{{ row.xiaoZhunWuCha || '/' }}</div>
  183. </div>
  184. </el-col>
  185. </el-row>
  186. </el-col>
  187. <el-col :span="5" :push="2">
  188. <el-row>
  189. <el-col :span="3">
  190. <el-image
  191. class="icon-image"
  192. :src="images[3]"
  193. fit="contain"
  194. />
  195. </el-col>
  196. <el-col :span="21">
  197. <div class="title">校准信息</div>
  198. <div class="ctx">
  199. <div class="item">是否校准:{{ row.shiFouXiaoZhun || '/' }}</div>
  200. <div class="item">校准周期:{{ row.xiaoZhunZQ?`${row.xiaoZhunZQ}月` : '/' }}</div>
  201. <div class="item">最近校准时间:{{ row.yiXiaoRiQi || '/' }}</div>
  202. <div class="item">校准有效期至:{{ row.xiaoZhunYouXia || '/' }}</div>
  203. </div>
  204. </el-col>
  205. </el-row>
  206. </el-col>
  207. <el-col :span="4" :push="1">
  208. <el-row>
  209. <el-col :span="24">
  210. <el-image
  211. class="device-image"
  212. :src="ImageUrl(row)"
  213. fit="fill"
  214. :preview-src-list="ImageAllUrl(row)"
  215. :title="`[${row.sheBeiMingCheng}]设备首图,点击查看更多`"
  216. >
  217. <div slot="error" class="image-slot">
  218. <el-empty class="device-image" description="暂无图片" :image-size="70" />
  219. </div>
  220. </el-image>
  221. </el-col>
  222. </el-row>
  223. </el-col>
  224. </el-row>
  225. </template>
  226. <!-- 搜索条件 -->
  227. <template slot="pos">
  228. <ibps-user-selector
  229. v-model="search.pos"
  230. type="position"
  231. readonly-text="text"
  232. :multiple="true"
  233. size="mini"
  234. :filter="filter"
  235. filtrate
  236. />
  237. </template>
  238. <template slot="time">
  239. <el-date-picker
  240. v-model="search.time"
  241. size="mini"
  242. type="daterange"
  243. :picker-options="pickerOptions"
  244. range-separator="至"
  245. start-placeholder="开始日期"
  246. end-placeholder="结束日期"
  247. align="right"
  248. value-format="yyyy-MM-dd"
  249. />
  250. </template>
  251. <template slot="validity">
  252. <el-date-picker
  253. v-model="search.validity"
  254. size="mini"
  255. type="daterange"
  256. :picker-options="pickerOptions"
  257. range-separator="至"
  258. start-placeholder="开始日期"
  259. end-placeholder="结束日期"
  260. align="right"
  261. value-format="yyyy-MM-dd"
  262. />
  263. </template>
  264. <template slot="nowNumber">
  265. <el-input v-model="search.nowNumber" size="mini" />
  266. </template>
  267. <template slot="preNumber">
  268. <el-input v-model="search.preNumber" size="mini" />
  269. </template>
  270. <template slot="deviceName">
  271. <el-input v-model="search.deviceName" size="mini" />
  272. </template>
  273. <template slot="deviceType">
  274. <el-select v-model="search.deviceType" placeholder="请选择" size="mini" :clearable="true">
  275. <el-option
  276. v-for="(v,k) in typeList"
  277. :key="k"
  278. :label="v"
  279. :value="k"
  280. />
  281. </el-select>
  282. </template>
  283. <template slot="deviceStatus">
  284. <el-select v-model="search.deviceStatus" placeholder="请选择" size="mini" :clearable="true">
  285. <el-option
  286. v-for="(v,k) in stateList"
  287. :key="k"
  288. :label="v"
  289. :value="k"
  290. />
  291. </el-select>
  292. </template>
  293. <template slot="place">
  294. <el-input v-model="search.place" size="mini" />
  295. </template>
  296. <template slot="managePeople">
  297. <ibps-user-selector
  298. v-model="search.managePeople"
  299. type="user"
  300. readonly-text="text"
  301. :multiple="true"
  302. size="mini"
  303. :filter="filter"
  304. filtrate
  305. />
  306. </template>
  307. <template slot="deviceClass">
  308. <ibps-custom-dialog
  309. v-model="search.deviceClass"
  310. size="mini"
  311. template-key="sbbqdhk"
  312. multiple
  313. :disabled="false"
  314. type="dialog"
  315. class="custom-dialog"
  316. placeholder="请选择"
  317. icon="el-icon-search"
  318. />
  319. </template>
  320. </ibps-crud>
  321. </template>
  322. </ibps-container>
  323. <DeviceDialog
  324. v-if="deviceDialogShow"
  325. :params="params"
  326. :state-list="stateList"
  327. :type-list="typeList"
  328. :tab-list="tabList"
  329. :hide-sys-device-no="hideSysDeviceNo"
  330. :readonly="!hasRole"
  331. @close="close"
  332. />
  333. <input id="" ref="file1" type="file" name="" accept=".xlsx,.xls" @change="handleUploadChange1">
  334. <input id="" ref="file2" type="file" name="" accept=".xlsx,.xls" @change="handleUploadChange2">
  335. <custom-dialog
  336. :visible="customDialogVisible"
  337. :value="[]"
  338. template-key="sbfzpz"
  339. :dynamic-params="{}"
  340. @close="(visible) => (customDialogVisible = visible)"
  341. />
  342. <bpmn-formrender
  343. :visible="npmDialogFormVisible"
  344. def-id="1120718364969271296"
  345. @close="visible => npmDialogFormVisible = visible"
  346. />
  347. <!-- <DeviceTagWeiNing v-if="tagName==='deviceTagWeiNing'" :scan-visible="printVisible" :obj="printObj" :state-list="stateList" @scanOff="scanOff" /> -->
  348. <DeviceTagTemplateTwo v-if="tagName==='deviceTagTemplateTwo'" :tag-data="tagData" :scan-visible="printVisible" :obj="printObj" :state-list="stateList" @scanOff="scanOff" />
  349. <DeviceTag v-else :scan-visible="printVisible" :obj="printObj" :tag-data="tagData" :state-list="stateList" @scanOff="scanOff" />
  350. <el-dialog
  351. :close-on-click-modal="false"
  352. :close-on-press-escape="false"
  353. :top="'3vh'"
  354. :width="'90%'"
  355. class="js-custom-dialog"
  356. append-to-body
  357. :fullscreen="false"
  358. :visible.sync="iframeVisible"
  359. >
  360. <iframe :src="srcUrl" :height="'100%'" :width="'100%'" frameborder="0" scrolling="no" />
  361. </el-dialog>
  362. </div>
  363. </template>
  364. <script>
  365. import { getSetting } from '@/utils/query'
  366. import image01 from '@/assets/images/device/01.png'
  367. import image02 from '@/assets/images/device/02.png'
  368. import image03 from '@/assets/images/device/03.png'
  369. import image04 from '@/assets/images/device/04.png'
  370. import { getImage } from '@/api/platform/file/attachment'
  371. import { download } from '@/api/platform/file/attachment'
  372. import xlsx from 'xlsx'
  373. import fs from 'file-saver'
  374. import DataTemplateFormrenderDialog from '@/business/platform/data/templaterender/form/dialog.vue'
  375. import ActionUtils from '@/utils/action'
  376. import FixHeight from '@/mixins/height'
  377. import ibpsUserSelector from '@/business/platform/org/selector'
  378. import DeviceDialog from './deviceDialog.vue'
  379. import { queryequipmentCard, removeEquipmentCard, getequipmentCard, saveEquipmentCard } from '@/api/platform/device/device'
  380. import CustomDialog from '@/business/platform/data/templaterender/custom-dialog/dialog'
  381. import dayjs from 'dayjs'
  382. import DeviceTag from '@/views/system/jbdScan/goods/deviceTag.vue'
  383. // import DeviceTagWeiNing from '@/views/system/jbdScan/goods/deviceTagWeiNing.vue'
  384. import DeviceTagTemplateTwo from '@/views/system/jbdScan/goods/deviceTagTemplateTwo'
  385. export default {
  386. components: {
  387. DeviceTag,
  388. // DeviceTagWeiNing,
  389. DeviceTagTemplateTwo,
  390. DataTemplateFormrenderDialog,
  391. DeviceDialog,
  392. ibpsUserSelector,
  393. CustomDialog,
  394. IbpsCustomDialog: () => import('@/business/platform/data/templaterender/custom-dialog')
  395. },
  396. mixins: [FixHeight],
  397. data () {
  398. const { userId, level = {}, position } = this.$store.getters || {}
  399. return {
  400. filter: [{
  401. descVal: '1',
  402. includeSub: true,
  403. old: 'position',
  404. partyId: this.$store.getters.userInfo.employee.positions,
  405. partyName: '',
  406. scriptContent: '',
  407. type: 'user',
  408. userType: 'position'
  409. }],
  410. images: [image01, image02, image03, image04],
  411. ImportDeviceType: '',
  412. iframeVisible: false,
  413. srcUrl: '',
  414. printObj: [],
  415. printVisible: false,
  416. DialogVisible: true,
  417. npmDialogFormVisible: false,
  418. customDialogVisible: false,
  419. pickerOptions: {
  420. shortcuts: [{
  421. text: '最近一周',
  422. onClick (picker) {
  423. const end = new Date()
  424. const start = new Date()
  425. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
  426. picker.$emit('pick', [start, end])
  427. }
  428. }, {
  429. text: '最近一个月',
  430. onClick (picker) {
  431. const end = new Date()
  432. const start = new Date()
  433. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
  434. picker.$emit('pick', [start, end])
  435. }
  436. }, {
  437. text: '最近三个月',
  438. onClick (picker) {
  439. const end = new Date()
  440. const start = new Date()
  441. start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
  442. picker.$emit('pick', [start, end])
  443. }
  444. }]
  445. },
  446. params: {},
  447. deviceDialogShow: false,
  448. position: position,
  449. level: level.second || level.first,
  450. userId: userId,
  451. search: {
  452. pos: '',
  453. time: [],
  454. nowNumber: '',
  455. preNumber: '',
  456. deviceName: '',
  457. deviceType: '',
  458. deviceStatus: '',
  459. place: '',
  460. managePeople: '',
  461. deviceClass: '',
  462. validity: ''
  463. },
  464. loading: false,
  465. pkKey: 'id', // 主键 如果主键不是pk需要传主键
  466. pkValue: '',
  467. templateKey: '',
  468. visible: false,
  469. categoryKey: '',
  470. tableTitle: '设备基本信息列表', // 标题
  471. listData: [],
  472. selectListData: [], // 全部数据
  473. bianlistData: {
  474. dataResult: [],
  475. pageResult: {
  476. limit: 0,
  477. page: 0,
  478. totalCount: 0,
  479. totalPages: 0
  480. }
  481. },
  482. listConfig: {
  483. // 工具栏
  484. toolbars: [
  485. { key: 'search' },
  486. { key: 'customAdd', label: '设备建档', icon: 'ibps-icon-plus', type: 'success' },
  487. { key: 'customBpm', label: '设备台账', icon: 'ibps-icon-file-text', type: 'info' },
  488. { key: 'customPrint', label: '打印标签', icon: 'ibps-icon-cog', type: 'warning' },
  489. { key: 'customExport', label: '导出数据', icon: 'ibps-icon-sign-in', type: 'primary' },
  490. { key: 'customImport', label: '导入数据', icon: 'ibps-icon-sign-in', type: 'primary' },
  491. { key: 'customSetting', label: '岗位/分组配置', icon: 'ibps-icon-cogs', type: 'info' },
  492. { key: 'customRemove', label: '删除', icon: 'ibps-icon-close', type: 'danger', hidden: () => { return !this.hasRole } }
  493. ],
  494. // 查询条件
  495. searchForm: {
  496. forms: [
  497. { prop: '', label: '部门', fieldType: 'slot', slotName: 'pos' }, // user 插槽
  498. { prop: '', label: '建档时间', fieldType: 'slot', slotName: 'time' },
  499. { prop: '', label: '设备编号', fieldType: 'slot', slotName: 'nowNumber' },
  500. { prop: '', label: '原设备编号', fieldType: 'slot', slotName: 'preNumber' },
  501. { prop: '', label: '设备名称', fieldType: 'slot', slotName: 'deviceName' },
  502. { prop: '', label: '设备类型', fieldType: 'slot', slotName: 'deviceType' },
  503. { prop: '', label: '设备状态', fieldType: 'slot', slotName: 'deviceStatus' },
  504. { prop: '', label: '放置地点', fieldType: 'slot', slotName: 'place' },
  505. { prop: '', label: '管理人', fieldType: 'slot', slotName: 'managePeople' },
  506. { prop: '', label: '岗位/分组', fieldType: 'slot', slotName: 'deviceClass' },
  507. { prop: '', label: '校准有效期', fieldType: 'slot', slotName: 'validity' }
  508. ]
  509. },
  510. // 表格字段配置
  511. columns: [
  512. { type: 'expand', slotName: 'expandSlot' },
  513. { prop: 'bianZhiBuMen', label: '部门', slotName: 'posSlot', sortable: true },
  514. { prop: 'bianZhiShiJian', label: '建档时间', sortable: true },
  515. { prop: 'sheBeiShiBieH', label: '设备编号', sortable: true },
  516. { prop: 'yuanSheBeiBian', label: '原设备编号', sortable: true },
  517. { prop: 'sheBeiMingCheng', label: '设备名称', sortable: true },
  518. { prop: 'sheBeiLeiXing', label: '设备类型', sortable: true, slotName: 'deviceTypeSlot' },
  519. { prop: 'guiGeXingHao', label: '规格型号', sortable: true },
  520. { prop: 'sheBeiZhuangTa', label: '设备状态', sortable: true, slotName: 'deviceStateSlot' },
  521. { prop: 'guanLiRen', label: '保管人', slotName: 'userSlot', sortable: true },
  522. { prop: 'weiHuFangShi', label: '岗位/分组', slotName: 'deviceSlot', sortable: true },
  523. { prop: 'cunFangWeiZhi', label: '放置地点', slotName: 'placeSlot', sortable: true },
  524. { prop: '', label: '操作', width: 130, slotName: 'customButton' }
  525. ]
  526. },
  527. pagination: {
  528. limit: 20, page: 1
  529. },
  530. sorts: [{ field: 'BIAN_ZHI_SHI_JIAN', order: 'desc' }],
  531. sqlWhere: {},
  532. searchWhere: {},
  533. deviceColumns: {
  534. bianZhiBuMen: '部门',
  535. sheBeiMingCheng: '设备名称',
  536. // sheBeiShiBieH: '设备编号(导入无需填写)',
  537. yuanSheBeiBian: '原设备编号(必填,且不可重复)',
  538. sheBeiZhuangTa: '设备状态(合格/停用/限用)',
  539. sheBeiLeiXing: '设备类型(检验系统/通用设备/软件/信息系统)',
  540. shiFouWeiHu: '是否维护(是/否)',
  541. shiFouXiaoZhun: '是否校准(是/否)',
  542. weiHuFangShi: '岗位/分组',
  543. guiGeXingHao: '规格型号',
  544. cunFangDiDian: '存放地点(格式:房间号+空格+房间名)',
  545. guanLiRen: '保管人',
  546. ziChanBianHao: '资产编号',
  547. ziChanYuanZhi: '资产原值(元)',
  548. gongYingShang: '供应商',
  549. lianXiFangShi: '联系方式',
  550. changShang: '厂商',
  551. jiShenXuHao: '机身序号',
  552. zhuCeZhengHao: '注册证号',
  553. heChaXiaoZhun: '使用年限(年)',
  554. chuChangRiQi: '出厂日期',
  555. yanShouRiQi: '验收日期',
  556. jieShouRiQi: '接收日期',
  557. qiYongRiQi: '投入日期',
  558. yiXiaoRiQi: '已校日期',
  559. xiaoZhunZQ: '检定/校准周期(以月为单位)',
  560. xiaoZhunYouXia: '校准有效期至',
  561. shiYongKeShi: '检定/校准单位',
  562. ceLiangGongZuo: '预期测量范围',
  563. huanJingYaoQiu: '环境要求',
  564. dianYuanYaoQiu: '电源要求',
  565. jieShouZhuangTai: '接收时状态(新设备/二手或翻新设备)',
  566. jianDingXiao: '检定/校准参数',
  567. zuiDaYunCha: 'U/精确度/最大允差',
  568. zhengShuBianHa: '证书编号',
  569. xiuZhengZhiXiu: '修正值/修正因子',
  570. wenDuYingYong: '温度应用修正值',
  571. shiDuYingYong: '湿度应用修正值'
  572. // biXuDeHuanJin: '核查人',
  573. // biXuSheShi: '核查日期',
  574. },
  575. projectColums: {
  576. yuanSheBeiBian: '原设备编号*',
  577. sheBeiMingCheng: '设备名称*',
  578. weiHuLeiXing: '维护类型*(日保养/周保养/月保养/季度保养/半年保养/年保养/按需保养)',
  579. weiHuRiQi: '维护日期*',
  580. weiHuXiangMuC: '维护项目*'
  581. },
  582. dateFieldRange: ['chuChangRiQi', 'yanShouRiQi', 'jieShouRiQi', 'qiYongRiQi', 'yiXiaoRiQi', 'xiaoZhunYouXia'],
  583. requiredFieldMap: {
  584. bianZhiBuMen: '部门',
  585. sheBeiMingCheng: '设备名称',
  586. yuanSheBeiBian: '原设备编号',
  587. sheBeiZhuangTa: '设备状态',
  588. sheBeiLeiXing: '设备类型',
  589. shiFouWeiHu: '是否维护',
  590. shiFouXiaoZhun: '是否校准'
  591. },
  592. dateFieldsMap: {
  593. 'chuChangRiQi': '出厂日期',
  594. 'yanShouRiQi': '验收日期',
  595. 'jieShouRiQi': '接收日期',
  596. 'qiYongRiQi': '投入日期',
  597. 'yiXiaoRiQi': '已校日期',
  598. 'xiaoZhunYouXia': '校准有效期至'
  599. // 'biXuSheShi': '核查日期'
  600. },
  601. validationRules: {
  602. '设备状态': {
  603. field: 'sheBeiZhuangTa',
  604. range: ['合格', '停用', '限用']
  605. },
  606. '设备类型': {
  607. field: 'sheBeiLeiXing',
  608. range: ['检验系统', '通用设备', '软件', '信息系统']
  609. },
  610. '接收时状态': {
  611. field: 'jieShouZhuangTai',
  612. range: ['新设备', '二手或翻新设备']
  613. },
  614. '是否校准': {
  615. field: 'shiFouXiaoZhun',
  616. range: ['是', '否']
  617. },
  618. '是否维护': {
  619. field: 'shiFouWeiHu',
  620. range: ['是', '否']
  621. }
  622. },
  623. numberFieldsMap: {
  624. 'xiaoZhunZQ': '检定/校准周期(以月为单位)',
  625. 'heChaXiaoZhun': '使用年限(年)',
  626. 'ziChanYuanZhi': '资产原值(元)'
  627. },
  628. maintenanceRequiredFieldMap: {
  629. yuanSheBeiBian: '原设备编号',
  630. sheBeiMingCheng: '设备名称',
  631. weiHuLeiXing: '维护类型',
  632. weiHuRiQi: '维护日期',
  633. weiHuXiangMuC: '维护项目'
  634. },
  635. maintenanceValidationRules: {
  636. '维护类型': {
  637. field: 'weiHuLeiXing',
  638. range: ['日保养', '周保养', '月保养', '季度保养', '半年保养', '年保养', '按需保养']
  639. }
  640. },
  641. maintenanceDateValidationRules: {
  642. '日保养': this.generateDayRule(),
  643. '周保养': this.generateRule(7, `每周`, ``),
  644. '月保养': this.generateRule(28, `每月第`, `日`),
  645. '半年保养': this.generateRule(6, `每半年第`, `个月`),
  646. '季度保养': this.generateRule(3, `每季度第`, `个月`),
  647. '年保养': this.generateRule(12, `每年第`, `个月`),
  648. '按需保养': ['/']
  649. },
  650. stateList: { '停用': '停用', '报废': '报废', '合格': '合格' },
  651. hideSysDeviceNo: false,
  652. tabList: {},
  653. hasRole: true,
  654. typeList: { '检验系统': '检验系统', '通用设备': '通用设备', '软件': '软件', '信息系统': '信息系统' },
  655. tagName: '',
  656. tagData: {}
  657. }
  658. },
  659. async mounted () {
  660. const { stateList, hideSysDeviceNo, tabList, hasDeviceRole, typeList } = await getSetting('device') || {}
  661. const { tagName } = await getSetting('deviceTag') || ''
  662. const { tagData } = await getSetting('deviceTag') || {}
  663. if (tagName) {
  664. console.debug('tagName', tagName)
  665. this.tagName = tagName
  666. this.tagData = tagData
  667. }
  668. if (hasDeviceRole) {
  669. console.debug('hasDeviceRole', hasDeviceRole)
  670. const { role, isSuper } = this.$store.getters || {}
  671. this.hasRole = isSuper || role.some(r => hasDeviceRole.includes(r.alias))
  672. }
  673. if (stateList) {
  674. console.debug('stateList', stateList)
  675. this.stateList = stateList
  676. }
  677. if (typeList) {
  678. console.debug('typeList', typeList)
  679. this.typeList = typeList
  680. }
  681. if (hideSysDeviceNo) {
  682. this.hideSysDeviceNo = hideSysDeviceNo
  683. // 列表隐藏设备编号 将原设备编号改为设备编号
  684. this.listConfig.columns = this.listConfig.columns.filter(i => i.prop !== 'sheBeiShiBieH')
  685. this.listConfig.columns.find(i => i.prop === 'yuanSheBeiBian').label = '设备编号'
  686. // 查询条件隐藏设备编号 将原设备编号改为设备编号
  687. this.listConfig.searchForm.forms = this.listConfig.searchForm.forms.filter(i => i.slotName !== 'nowNumber')
  688. this.listConfig.searchForm.forms.find(i => i.slotName === 'preNumber').label = '设备编号'
  689. }
  690. if (tabList) {
  691. console.debug('tabList', tabList)
  692. this.tabList = tabList
  693. }
  694. this.getDatas()
  695. },
  696. methods: {
  697. ImageAllUrl (row) {
  698. if (row && row.buMen) {
  699. const imgId = row.buMen.split(',')
  700. return imgId.map(item => getImage(item))
  701. }
  702. return []
  703. },
  704. ImageUrl (row) {
  705. if (row && row.buMen) {
  706. const imgId = row.buMen.split(',')[0]
  707. return getImage(imgId)
  708. }
  709. return ''
  710. },
  711. async getDatas () {
  712. this.loading = true
  713. const parameters = {
  714. relation: 'AND',
  715. parameters: []
  716. }
  717. // 增加地点过滤
  718. const obj = { relation: 'AND', parameters: [] }
  719. obj.parameters.push({ key: 'Q^di_dian_^S', value: this.level, param: this.$utils.guid() })
  720. parameters.parameters.push(obj)
  721. // 部门搜索(可多选)
  722. if (this.search.pos) {
  723. const obj = { relation: 'OR', parameters: [] }
  724. this.search.pos.split(',').forEach(item => {
  725. obj.parameters.push({ key: 'Q^bian_zhi_bu_men_^S', value: item, param: this.$utils.guid() })
  726. })
  727. parameters.parameters.push(obj)
  728. }
  729. // 建档时间搜索
  730. if (this.search.time && this.search.time.length === 2) {
  731. const obj = { relation: 'AND', parameters: [] }
  732. obj.parameters.push({ key: 'Q^bian_zhi_shi_jian^DL^yyyy-MM-dd', value: this.search.time[0], param: this.$utils.guid() })
  733. obj.parameters.push({ key: 'Q^bian_zhi_shi_jian^DG^yyyy-MM-dd', value: this.search.time[1], param: this.$utils.guid() })
  734. parameters.parameters.push(obj)
  735. }
  736. if (this.search.validity && this.search.validity.length === 2) {
  737. const obj = { relation: 'AND', parameters: [] }
  738. obj.parameters.push({ key: 'Q^xiao_zhun_you_xia^DL^yyyy-MM-dd', value: this.search.validity[0], param: this.$utils.guid() })
  739. obj.parameters.push({ key: 'Q^xiao_zhun_you_xia^DG^yyyy-MM-dd', value: this.search.validity[1], param: this.$utils.guid() })
  740. parameters.parameters.push(obj)
  741. }
  742. // 设备编号搜索
  743. if (this.search.nowNumber) {
  744. const obj = { relation: 'AND', parameters: [] }
  745. obj.parameters.push({ key: 'Q^she_bei_shi_bie_h^SL', value: this.search.nowNumber, param: this.$utils.guid() })
  746. parameters.parameters.push(obj)
  747. }
  748. // 原设备编号搜索
  749. if (this.search.preNumber) {
  750. const obj = { relation: 'AND', parameters: [] }
  751. obj.parameters.push({ key: 'Q^yuan_she_bei_bian^SL', value: this.search.preNumber, param: this.$utils.guid() })
  752. parameters.parameters.push(obj)
  753. }
  754. // 设备名称搜索
  755. if (this.search.deviceName) {
  756. const obj = { relation: 'AND', parameters: [] }
  757. obj.parameters.push({ key: 'Q^she_bei_ming_cheng_^SL', value: this.search.deviceName, param: this.$utils.guid() })
  758. parameters.parameters.push(obj)
  759. }
  760. // 设备类型搜索
  761. if (this.search.deviceType) {
  762. const obj = { relation: 'AND', parameters: [] }
  763. obj.parameters.push({ key: 'Q^she_bei_lei_xing_^S', value: this.search.deviceType, param: this.$utils.guid() })
  764. parameters.parameters.push(obj)
  765. }
  766. // 设备状态搜索
  767. if (this.search.deviceStatus) {
  768. const obj = { relation: 'AND', parameters: [] }
  769. obj.parameters.push({ key: 'Q^she_bei_zhuang_ta^S', value: this.search.deviceStatus, param: this.$utils.guid() })
  770. parameters.parameters.push(obj)
  771. }
  772. // 放置地点搜索
  773. if (this.search.place) {
  774. const obj = { relation: 'AND', parameters: [] }
  775. obj.parameters.push({ key: 'Q^cun_fang_di_dian_^SL', value: this.search.place, param: this.$utils.guid() })
  776. parameters.parameters.push(obj)
  777. }
  778. // 保管人搜索(可多选)
  779. if (this.search.managePeople) {
  780. const obj = { relation: 'OR', parameters: [] }
  781. this.search.managePeople.split(',').forEach(item => {
  782. obj.parameters.push({ key: 'Q^guan_li_ren_^S', value: item, param: this.$utils.guid() })
  783. })
  784. parameters.parameters.push(obj)
  785. }
  786. // 岗位/分组搜索(可多选)
  787. if (this.search.deviceClass) {
  788. const obj = { relation: 'OR', parameters: [] }
  789. this.search.deviceClass.split(',').forEach(item => {
  790. obj.parameters.push({ key: 'Q^wei_hu_fang_shi_^S', value: item, param: this.$utils.guid() })
  791. })
  792. parameters.parameters.push(obj)
  793. }
  794. const params = {
  795. requestPage: {
  796. pageNo: this.pagination.page,
  797. limit: this.pagination.limit
  798. },
  799. sorts: this.sorts
  800. }
  801. if (parameters.parameters.length > 0) {
  802. params.parameters = [parameters]
  803. }
  804. const { data: { dataResult, pageResult }} = await queryequipmentCard(params)
  805. this.bianlistData.pageResult = pageResult
  806. this.bianlistData.dataResult = dataResult
  807. ActionUtils.handleListData(this, this.bianlistData) // 调用内置方法
  808. this.loading = false
  809. },
  810. // 查看表单
  811. goLookForm (row) {
  812. const first = this.$store.getters.level.first
  813. this.srcUrl = this.$reportPath.replace('show', 'pdf') + '设备/设备档案卡.rpx&id_=' + row.id + '&org_=' + first
  814. this.iframeVisible = true
  815. },
  816. // 按钮事件处理
  817. handleAction (command, position, selection, data, index, button) {
  818. switch (command) {
  819. case 'search':// 查询
  820. this.getDatas()
  821. break
  822. case 'customAdd':
  823. this.handleCustomAdd()
  824. break
  825. case 'customSetting':
  826. this.handleCustomSetting()
  827. break
  828. case 'customRemove':
  829. this.handleCustomRemove(selection)
  830. break
  831. case 'customExport':
  832. this.handleCustomExport(selection, data)
  833. break
  834. case 'customImport':
  835. this.handleCustomImport()
  836. break
  837. case 'customBpm':
  838. this.handleCustomBpm()
  839. break
  840. case 'customPrint':
  841. this.handleCustomPrint(selection)
  842. break
  843. default:
  844. break
  845. }
  846. },
  847. // 打印标签
  848. handleCustomPrint (selection = []) {
  849. if (selection.length === 0) {
  850. return this.$message.warning('请先选择需要打印标签的数据!')
  851. }
  852. this.printObj = selection
  853. this.printVisible = true
  854. },
  855. // 关闭标签
  856. scanOff () {
  857. this.printVisible = false
  858. },
  859. // 设备台账
  860. handleCustomBpm () {
  861. this.npmDialogFormVisible = true
  862. },
  863. // 处理分页事件
  864. async handlePaginationChange (page) {
  865. ActionUtils.setPagination(this.pagination, page)
  866. this.getDatas()
  867. },
  868. // 处理排序
  869. handleSortChange (sort) {
  870. function removeUnderscores (str) {
  871. return str.replace(/^_+|_+$/g, '')
  872. }
  873. const { order, sortBy } = sort
  874. let s = ''
  875. switch (sortBy) {
  876. case 'BIAN_ZHI_SHI_JIAN_':
  877. case 'SHE_BEI_SHI_BIE_H_':
  878. case 'YUAN_SHE_BEI_BIAN_':
  879. case 'SHE_BEI_ZHUANG_TA_':
  880. s = removeUnderscores(sortBy)
  881. break
  882. default:
  883. s = sortBy
  884. }
  885. let o = null
  886. if (order === 'descending') {
  887. o = 'desc'
  888. } else if (order === 'ascending') {
  889. o = 'asc'
  890. }
  891. this.sorts = [{ field: s, order: o }]
  892. this.getDatas()
  893. },
  894. handleCustomAdd () {
  895. this.params = {}
  896. this.deviceDialogShow = true
  897. },
  898. close () {
  899. this.deviceDialogShow = false
  900. this.getDatas()
  901. },
  902. goEdit (row) {
  903. this.params = row
  904. this.deviceDialogShow = true
  905. },
  906. handleCustomSetting () {
  907. this.customDialogVisible = true
  908. },
  909. handleCustomRemove (selection) {
  910. if (!this.hasRole) return
  911. console.log('selection', selection)
  912. if (!selection || selection.length === 0) {
  913. return this.$message.warning('请选择要删除的数据!')
  914. }
  915. this.$confirm('确定删除所选项?删除后无法恢复!', '提示', {
  916. confirmButtonText: '继续',
  917. cancelButtonText: '取消',
  918. type: 'warning'
  919. }).then(async () => {
  920. await removeEquipmentCard({
  921. ids: selection + ''
  922. })
  923. // 删除后刷新
  924. await this.getDatas()
  925. this.$message.success('删除成功!')
  926. }).catch(() => {})
  927. },
  928. // 导出
  929. handleCustomExport (selection, data) {
  930. this.$confirm('请选择导出的类型', '提示', {
  931. confirmButtonText: '导出设备',
  932. cancelButtonText: '导出维护项目',
  933. closeOnClickModal: false,
  934. closeOnPressEscape: false,
  935. distinguishCancelAndClose: true,
  936. type: 'info'
  937. }).then(() => {
  938. this.ExportDevice(selection, data)
  939. }).catch((action) => {
  940. if (action === 'close') return
  941. if (action === 'cancel') {
  942. this.ExportProject(selection, data)
  943. }
  944. })
  945. },
  946. // 导入
  947. handleCustomImport () {
  948. this.$confirm('确请选择导入的类型', '提示', {
  949. confirmButtonText: '导入设备',
  950. cancelButtonText: '导入维护项目',
  951. closeOnClickModal: false,
  952. closeOnPressEscape: false,
  953. distinguishCancelAndClose: true,
  954. type: 'info'
  955. }).then(() => {
  956. this.ImportDevice()
  957. }).catch((action) => {
  958. if (action === 'close') return
  959. if (action === 'cancel') {
  960. this.$confirm('请选择设备维护项目导入类型', '提示', {
  961. confirmButtonText: '增量添加',
  962. cancelButtonText: '全量替换',
  963. closeOnClickModal: false,
  964. closeOnPressEscape: false,
  965. distinguishCancelAndClose: true,
  966. type: 'info'
  967. }).then(() => {
  968. this.ImportDeviceType = '增量添加'
  969. this.ImportProject()
  970. }).catch((action) => {
  971. if (action === 'close') return
  972. if (action === 'cancel') {
  973. this.ImportDeviceType = '全量替换'
  974. this.ImportProject()
  975. }
  976. })
  977. }
  978. })
  979. },
  980. // 导入设备
  981. ImportDevice () {
  982. this.$refs.file1.click()
  983. console.log('导入设备')
  984. },
  985. // 导入维护项目
  986. ImportProject () {
  987. this.$refs.file2.click()
  988. console.log('导入维护项目')
  989. },
  990. getTimeStamp () {
  991. return dayjs().format('YYYYMMDDHHmmss')
  992. },
  993. xlsx (json, fields, filename = '.xlsx') { // 导出xlsx
  994. json.forEach(item => {
  995. for (const i in item) {
  996. if (fields.hasOwnProperty(i)) {
  997. item[fields[i]] = item[i]
  998. }
  999. delete item[i] // 删除原先的对象属性
  1000. }
  1001. })
  1002. const sheetName = filename // excel的文件名称
  1003. const wb = xlsx.utils.book_new() // 工作簿对象包含一SheetNames数组,以及一个表对象映射表名称到表对象。XLSX.utils.book_new实用函数创建一个新的工作簿对象。
  1004. const ws = xlsx.utils.json_to_sheet(json, { header: Object.values(fields) }) // 将JS对象数组转换为工作表。
  1005. wb.SheetNames.push(sheetName)
  1006. wb.Sheets[sheetName] = ws
  1007. const defaultCellStyle = { font: { name: 'Verdana', sz: 13, color: 'FF00FF88' }, fill: { fgColor: { rgb: 'FFFFAA00' }}}// 设置表格的样式
  1008. const wopts = { bookType: 'xlsx', bookSST: false, type: 'binary', cellStyles: true, defaultCellStyle: defaultCellStyle, showGridLines: false } // 写入的样式
  1009. const wbout = xlsx.write(wb, wopts)
  1010. const blob = new Blob([this.s2ab(wbout)], { type: 'application/octet-stream' })
  1011. fs.saveAs(blob, filename + '.xlsx')
  1012. },
  1013. s2ab (s) {
  1014. let buf
  1015. if (typeof ArrayBuffer !== 'undefined') {
  1016. buf = new ArrayBuffer(s.length)
  1017. const view = new Uint8Array(buf)
  1018. for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
  1019. return buf
  1020. } else {
  1021. buf = new Array(s.length)
  1022. for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF
  1023. return buf
  1024. }
  1025. },
  1026. async switchExportData (data) {
  1027. const deviceGroupSql = `select id_,wei_hu_gang_wei_ from t_sbwhgwpzb` // 岗位/分组信息
  1028. const supplierSql = `select id_,gong_ying_shang_m from t_gysxxb` // 供应商信息
  1029. const { variables: { data: deviceGroupData }} = await this.$common.request('sql', deviceGroupSql)
  1030. const { variables: { data: gysData }} = await this.$common.request('sql', supplierSql)
  1031. const exportData = JSON.parse(JSON.stringify(data))
  1032. for (let i = 0; i < exportData.length; i++) {
  1033. const item = exportData[i]
  1034. item.bianZhiBuMen = this.switchIdToDept(item.bianZhiBuMen.split(',')[0])
  1035. item.guanLiRen = this.switchIdToUserName(item.guanLiRen.split(',')[0])
  1036. // item.biXuDeHuanJin = this.switchIdToUserName(item.biXuDeHuanJin.split(',')[0])
  1037. item.weiHuFangShi = this.switchDeviceIdToName(item.weiHuFangShi, deviceGroupData)
  1038. item.shiYongKeShi = this.switchGYSIdToName(item.shiYongKeShi, gysData)
  1039. if (this.stateList[item.sheBeiZhuangTa]) {
  1040. item.sheBeiZhuangTa = this.stateList[item.sheBeiZhuangTa]
  1041. }
  1042. if (this.typeList[item.sheBeiLeiXing]) {
  1043. item.sheBeiLeiXing = this.typeList[item.sheBeiLeiXing]
  1044. }
  1045. }
  1046. return exportData
  1047. },
  1048. // 岗位/分组id 转 岗位/分组名称
  1049. switchDeviceIdToName (val, deviceGroupList) {
  1050. const result = []
  1051. const valList = val?.split(',') || []
  1052. valList.forEach(item => result.push((deviceGroupList?.find(i => i.id_ === item)?.wei_hu_gang_wei_) || ''))
  1053. return result.join(',')
  1054. },
  1055. // 供应商id 转 供应商名称 检定/校准单位
  1056. switchGYSIdToName (val, gysList) {
  1057. const result = gysList.find(item => item.id_ === val)?.gong_ying_shang_m || ''
  1058. return result
  1059. },
  1060. // 部门id 转 部门名称
  1061. switchIdToDept (id) {
  1062. const { deptList } = this.$store.getters
  1063. const temp = deptList.find(item => item.positionId === id)
  1064. return temp ? temp.positionName : ''
  1065. },
  1066. // 部门名称 转 部门id
  1067. switchDeptToId (dep) {
  1068. const { deptList } = this.$store.getters
  1069. const temp = deptList.find(item => item.positionName === dep)
  1070. return temp ? temp.positionId : ''
  1071. },
  1072. // 人员id 转人员名称
  1073. switchIdToUserName (id) {
  1074. const { userList } = this.$store.getters
  1075. const temp = userList.find(item => item.userId === id)
  1076. return temp ? temp.userName : ''
  1077. },
  1078. // 人员名称 转 人员id
  1079. switchUserNameToId (name) {
  1080. const { userList } = this.$store.getters
  1081. const temp = userList.find(item => item.userName === name)
  1082. return temp ? temp.userId : ''
  1083. },
  1084. // 导出设备
  1085. async ExportDevice (selection, data = []) {
  1086. const exportData = await this.switchExportData(data)
  1087. this.xlsx(exportData, this.deviceColumns, '设备档案卡基本数据' + this.getTimeStamp())
  1088. this.$message.success('导出设备成功!')
  1089. },
  1090. // 导出维护项目
  1091. async ExportProject (selection = []) {
  1092. let exportData = []
  1093. console.log('导出维护项目')
  1094. if (selection.length > 0) {
  1095. const sql = `select b.yuan_she_bei_bian as yuanSheBeiBian,b.she_bei_ming_cheng_ as sheBeiMingCheng,a.parent_id_,a.wei_hu_xiang_mu_c as weiHuXiangMuC,a.wei_hu_ri_qi_ as weiHuRiQi,a.wei_hu_lei_xing_ as weiHuLeiXing,a.ri_qi_shu_zi_ as riQiShuZi from t_whzqjxm a,t_sbdj b where a.parent_id_=b.id_ and a.parent_id_ in (${selection.map(i => `'${i}'`).join(',')})`
  1096. const { variables: { data }} = await this.$common.request('sql', sql)
  1097. exportData = data
  1098. this.xlsx(exportData, this.projectColums, '设备维护项目数据' + this.getTimeStamp())
  1099. } else {
  1100. const attachmentId = 'device_maintainProject'
  1101. const res = await download({ attachmentId })
  1102. // 判断 ArrayBuffer 的大小,主要用于兼容没有文件的情况
  1103. if (res.data?.byteLength === 0) {
  1104. this.xlsx([], this.projectColums, '设备维护项目模板' + this.getTimeStamp())
  1105. } else {
  1106. // const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
  1107. const a = document.createElement('a')
  1108. a.style.display = 'none'
  1109. // a.href = URL.createObjectURL(blob)
  1110. a.href = res.request.responseURL
  1111. // a.download = '设备维护项目导入模板'
  1112. document.body.appendChild(a)
  1113. a.click()
  1114. document.body.removeChild(a)
  1115. }
  1116. }
  1117. this.$message.success('导出维护项目成功!')
  1118. },
  1119. // value 转 key
  1120. switchV2K (value, obj) {
  1121. const key = Object.keys(obj).find(key => obj[key] === value)
  1122. return key || ''
  1123. },
  1124. // 转换对象的key
  1125. switchDeviceObj (data, originalObj) {
  1126. const result = []
  1127. // data.forEach(item => {
  1128. // const obj = {}
  1129. // for (const key in item) {
  1130. // obj[this.switchV2K(key, originalObj)] = item[key]
  1131. // }
  1132. // result.push(obj)
  1133. // })
  1134. data.forEach(item => {
  1135. const obj = {}
  1136. for (const key in originalObj) {
  1137. // 对日期格式的数据做兼容处理
  1138. if (item[originalObj[key]] instanceof Date) {
  1139. obj[key] = dayjs(item[originalObj[key]]).add(8, 'hour').format('YYYY-MM-DD') || ''
  1140. } else {
  1141. obj[key] = String(item[originalObj[key]] || '')
  1142. }
  1143. }
  1144. result.push(obj)
  1145. })
  1146. return result
  1147. },
  1148. /* 读取文件 将文件转换为二进制 */
  1149. readFile (file) {
  1150. return new Promise(resolve => {
  1151. const reader = new FileReader()
  1152. reader.readAsBinaryString(file)
  1153. reader.onload = ev => {
  1154. resolve(ev.target.result)
  1155. }
  1156. })
  1157. },
  1158. checkDeviceRequiredFieldsIfEmpty (list, requiredMap) {
  1159. const msgList = []
  1160. list.forEach((item, index) => {
  1161. const invalidFieldNames = []
  1162. Object.entries(requiredMap).forEach(([field, name]) => {
  1163. if (item.weiHuLeiXing === '按需保养' && field === 'weiHuRiQi') {
  1164. console.log('按需pass1')
  1165. } else {
  1166. if (!item[field]) {
  1167. invalidFieldNames.push(name)
  1168. }
  1169. }
  1170. })
  1171. if (invalidFieldNames.length > 0) {
  1172. msgList.push({ row: index + 2, field: invalidFieldNames })
  1173. }
  1174. })
  1175. return msgList
  1176. },
  1177. /**
  1178. * 专门发送提示
  1179. * @param {*} allResult
  1180. * @returns
  1181. */
  1182. sendWarningMessages (allResult, mark = 'range') {
  1183. if (allResult.length < 1) {
  1184. return
  1185. }
  1186. console.log('%c Msg Obj %c', 'background:#FF5733; padding: 1px; border-radius: 0 3px 3px 0; color: #fff;', 'background:transparent', allResult)
  1187. const item = allResult[0]
  1188. switch (mark) {
  1189. case 'required':
  1190. this.$message.warning(`第${item.row}行,字段【${item.field.join(',')}】的值不能为空!`)
  1191. break
  1192. case 'range':
  1193. this.$message.warning(`第${item.row}行,字段【${item.field}】的值【${item.value}】不在限定范围内!`)
  1194. break
  1195. case 'dateFormat':
  1196. this.$message.warning(`第${item.row}行,字段【${item.field}】日期格式错误!格式支持【2024-01-01】、【2024/01/01】,请检查您的数据!`)
  1197. break
  1198. case 'duplicateOriginalDevice':
  1199. this.$message.warning(`${item.field}!`)
  1200. break
  1201. default:
  1202. throw new Error(`${mark}类型未定义!`)
  1203. }
  1204. },
  1205. /**
  1206. * 根据规则校验字段的限定范围
  1207. * @param {*} list
  1208. */
  1209. checkFieldsRange (list, rules) {
  1210. const msgList = []
  1211. for (const ruleKey in rules) {
  1212. const rule = rules[ruleKey]
  1213. const fieldName = ruleKey
  1214. list.forEach((item, index) => {
  1215. const fieldValue = item[rule.field]
  1216. if (fieldValue && !rule.range.includes(fieldValue)) {
  1217. msgList.push({ row: index + 2, field: fieldName, value: fieldValue })
  1218. }
  1219. })
  1220. }
  1221. return msgList
  1222. },
  1223. /**
  1224. * 校验日期字段填写的格式
  1225. * @param {*} list
  1226. * @returns
  1227. */
  1228. checkDateFields (list) {
  1229. const dateRegex = /^(\d{4})[-/](0[1-9]|1[0-2])[-/](0[1-9]|[12]\d|3[01])$/
  1230. for (let i = 0; i < list.length; i++) {
  1231. const row = list[i]
  1232. for (const field in this.dateFieldsMap) {
  1233. if (row[field] && !dateRegex.test(row[field])) {
  1234. console.error('error field:', row[field])
  1235. return [{ row: i + 2, field: this.dateFieldsMap[field] }]
  1236. }
  1237. }
  1238. }
  1239. return []
  1240. },
  1241. checkDuplicateOriginalDeviceNo (arr) {
  1242. const occurrences = {}
  1243. arr.forEach((item, index) => {
  1244. const key = item.yuanSheBeiBian
  1245. if (occurrences[key]) {
  1246. occurrences[key].push(index + 2)
  1247. } else {
  1248. occurrences[key] = [index + 2]
  1249. }
  1250. })
  1251. // 检查是否有重复项(数组长度大于1)
  1252. for (const [key, indices] of Object.entries(occurrences)) {
  1253. if (indices.length > 1) {
  1254. return [{ field: `发现重复的原设备编号:${key} 在第 ${indices.join(', ')} 行` }]
  1255. }
  1256. }
  1257. return []
  1258. },
  1259. /**
  1260. * 负责导入设备数据的第一部分校验,全部成功则返回true
  1261. * @param {*} data
  1262. * @returns
  1263. */
  1264. deviceInvalidPartOne (data) {
  1265. // 校验必填信息
  1266. const invalidResult = this.checkDeviceRequiredFieldsIfEmpty(data, this.requiredFieldMap)
  1267. if (invalidResult.length > 0) {
  1268. this.sendWarningMessages(invalidResult, 'required')
  1269. return false
  1270. }
  1271. // 根据规则校验字段的限定范围
  1272. const allResult = this.checkFieldsRange(data, this.validationRules)
  1273. if (allResult.length > 0) {
  1274. this.sendWarningMessages(allResult, 'range')
  1275. return false
  1276. }
  1277. // 校验日期字段是否符合要求
  1278. const dateResult = this.checkDateFields(data)
  1279. if (dateResult.length > 0) {
  1280. this.sendWarningMessages(dateResult, 'dateFormat')
  1281. return false
  1282. }
  1283. // 校验是否存在重复的原设备编号
  1284. const duplicateOriginalDeviceResult = this.checkDuplicateOriginalDeviceNo(data)
  1285. if (duplicateOriginalDeviceResult.length > 0) {
  1286. this.sendWarningMessages(duplicateOriginalDeviceResult, 'duplicateOriginalDevice')
  1287. return false
  1288. }
  1289. return true
  1290. },
  1291. /**
  1292. * 将日期字段信息格式化为 yyyy-MM-dd
  1293. * @param {*} list
  1294. * @returns
  1295. */
  1296. formatDateFieldsToReal (list) {
  1297. list.forEach(item => {
  1298. this.dateFieldRange.forEach(field => {
  1299. item[field] = item[field]?.replace(/\//g, '-')
  1300. })
  1301. })
  1302. return list
  1303. },
  1304. getNextAlias () {
  1305. return new Promise((resolve, reject) => {
  1306. this.$common.getNextIdByAlias({
  1307. 'alias': 'sbbh'
  1308. }).then(response => {
  1309. resolve(response.data)
  1310. }).catch((error) => {
  1311. reject(error)
  1312. })
  1313. })
  1314. },
  1315. /**
  1316. * 过滤出来excel 的原设备编号存在当前数据库中的数据
  1317. * @param {*} list 导入的数据
  1318. */
  1319. async filterOriginalDeviceNo (list, currentPosition) {
  1320. const uniqueArr = Array.from(new Set(list.map(i => i.yuanSheBeiBian.trim())))
  1321. const sql = `select id_,yuan_she_bei_bian from t_sbdj where find_in_set(yuan_she_bei_bian,'${uniqueArr.join(',')}')and di_dian_ = '${currentPosition}'`
  1322. const res = await this.$common.request('sql', sql)
  1323. const { data = [] } = res.variables || {}
  1324. const originalDeviceNoList = data.map(i => i.yuan_she_bei_bian.trim())
  1325. // 给要更新的数据加上id (接口需要!!!)
  1326. data.forEach(item => {
  1327. const temp = list.find(i => i.yuanSheBeiBian === item.yuan_she_bei_bian)
  1328. temp.id = item.id_
  1329. })
  1330. return originalDeviceNoList || ''
  1331. },
  1332. /**
  1333. *
  1334. * @param {*} list excel数据
  1335. * @param {*} currentTime 当前时间
  1336. * @param {*} currentApartment 当前部门ID
  1337. * @param {*} currentUser 当前用户ID
  1338. * @param {*} currentPosition 当前地点ID
  1339. */
  1340. async handleBasicData (list, currentTime, currentApartment, currentUser, currentPosition, deptList) {
  1341. // 使用map生成一个异步操作的数组
  1342. const promises = list.map(async (element) => {
  1343. element.bianZhiShiJian = currentTime
  1344. element.bianZhiRen = currentUser
  1345. element.diDian = currentPosition
  1346. element.shiFouGuoShen = '已完成'
  1347. const o = deptList?.find(i => i.positionName === element.bianZhiBuMen.trim())
  1348. const { positionId = currentApartment } = o || {}
  1349. element.bianZhiBuMen = positionId
  1350. if (!element.id) {
  1351. // 获取下一个编号
  1352. element.sheBeiShiBieH = await this.getNextAlias()
  1353. }
  1354. })
  1355. // 使用Promise.all并发执行所有异步操作
  1356. await Promise.all(promises)
  1357. },
  1358. /**
  1359. *
  1360. * @param {*} list excel数据
  1361. * @param {*} positionList 现有房间信息
  1362. * @param {*} supplierList 现有供应商信息
  1363. * @param {*} employeeList 现有人员信息
  1364. * @returns
  1365. */
  1366. handleExcelData (list, positionList, supplierList, employeeList, deviceGroupList) {
  1367. if (list.length < 1) {
  1368. return
  1369. }
  1370. this.handleSupplierInfo(list, supplierList)
  1371. this.handlePositionInfo(list, positionList)
  1372. this.handlePersonInfo(list, employeeList)
  1373. this.handleDeviceGroupInfo(list, deviceGroupList)
  1374. },
  1375. /**
  1376. *
  1377. * @param {*} list excel数据
  1378. * @param {*} supplierList 现有供应商信息
  1379. */
  1380. handleSupplierInfo (list, supplierList) {
  1381. list.forEach(element => {
  1382. if (element.gongYingShang.trim()) {
  1383. const supplier = supplierList.find(i => i.gong_ying_shang_m === element.gongYingShang.trim())
  1384. if (supplier) {
  1385. element.shiFouQiJianH = supplier.id_
  1386. } else {
  1387. element.shiFouQiJianH = ''
  1388. element.gongYingShang = ''
  1389. }
  1390. } else {
  1391. element.shiFouQiJianH = ''
  1392. }
  1393. if (element.shiYongKeShi.trim()) {
  1394. const supplier = supplierList.find(i => i.gong_ying_shang_m === element.shiYongKeShi.trim())
  1395. if (supplier) {
  1396. element.shiYongKeShi = supplier.id_
  1397. } else {
  1398. element.shiYongKeShi = ''
  1399. }
  1400. } else {
  1401. element.shiYongKeShi = ''
  1402. }
  1403. })
  1404. },
  1405. /**
  1406. *
  1407. * @param {*} list excel数据
  1408. * @param {*} positionList 现有房间信息
  1409. */
  1410. handlePositionInfo (list, positionList) {
  1411. list.forEach(element => {
  1412. if (element.cunFangDiDian !== '') {
  1413. const postion = positionList.find(i => (i.fang_jian_ming_ha.trim() || '') === element.cunFangDiDian.trim())
  1414. if (postion) {
  1415. const positionId = postion.id_
  1416. element.cunFangWeiZhi = positionId
  1417. } else {
  1418. element.cunFangWeiZhi = ''
  1419. element.cunFangDiDian = ''
  1420. }
  1421. } else {
  1422. element.cunFangWeiZhi = ''
  1423. }
  1424. })
  1425. },
  1426. handlePersonInfo (list, employeeList) {
  1427. list.forEach(element => {
  1428. // 处理保管人
  1429. if (element.guanLiRen !== '') {
  1430. const person = employeeList.find(i => i.userName === element.guanLiRen.trim())
  1431. if (person) {
  1432. const personId = person.userId
  1433. element.guanLiRen = personId
  1434. } else {
  1435. element.guanLiRen = ''
  1436. }
  1437. } else {
  1438. element.guanLiRen = ''
  1439. }
  1440. // 处理核查人
  1441. // if (element.biXuDeHuanJin !== '') {
  1442. // const checkPerson = employeeList.find(i => i.userName === element.biXuDeHuanJin.trim())
  1443. // if (checkPerson) {
  1444. // const checkPersonId = checkPerson.userId
  1445. // element.biXuDeHuanJin = checkPersonId
  1446. // } else {
  1447. // element.biXuDeHuanJin = ''
  1448. // }
  1449. // } else {
  1450. // element.biXuDeHuanJin = ''
  1451. // }
  1452. })
  1453. },
  1454. handleDeviceGroupInfo (list, deviceGroupList) {
  1455. list.forEach(element => {
  1456. const result = []
  1457. const { weiHuFangShi } = element
  1458. const valList = weiHuFangShi.trim()?.split(',')
  1459. valList.forEach(item => result.push((deviceGroupList?.find(i => i.wei_hu_gang_wei_ === item)?.id_) || ''))
  1460. element.weiHuFangShi = result.join(',')
  1461. })
  1462. },
  1463. async handleUploadChange1 (file) {
  1464. const dataBinary = await this.readFile(file.target.files[0])
  1465. file.target.value = null // 注意上传后要将input的值设为空
  1466. const workBook = xlsx.read(dataBinary, { type: 'binary', cellDates: true })
  1467. const workSheet = workBook.Sheets[workBook.SheetNames[0]]
  1468. const data = xlsx.utils.sheet_to_json(workSheet)
  1469. let importData = this.switchDeviceObj(data, { ...this.deviceColumns, t: '设备分组' }) // 这个t用于兼容老版本的模板
  1470. importData.forEach(i => {
  1471. delete i.sheBeiShiBieH // 设备编号需自动生成
  1472. // i.sheBeiZhuangTa = '合格'
  1473. const keyFound = Object.entries(this.stateList).find(([key, value]) => value === i.sheBeiZhuangTa)
  1474. if (keyFound) {
  1475. i.sheBeiZhuangTa = keyFound[0]
  1476. }
  1477. const keyFound2 = Object.entries(this.typeList).find(([key, value]) => value === i.sheBeiLeiXing)
  1478. if (keyFound2) {
  1479. i.sheBeiLeiXing = keyFound2[0]
  1480. }
  1481. })
  1482. const isNewVersion = importData.some(i => i.weiHuFangShi) // 判断是否是最新模板
  1483. if (isNewVersion) { // 使用岗位/分组
  1484. importData.forEach(i => {
  1485. delete i.t
  1486. })
  1487. } else { // 使用设备分组
  1488. importData.forEach(i => {
  1489. i.weiHuFangShi = i.t
  1490. delete i.t
  1491. })
  1492. }
  1493. const currentPosition = this.level
  1494. const { userList = [], deptList = [] } = this.$store.getters || {}
  1495. const positionSql = `select id_,fang_jian_ming_ha from t_jjqfjb where di_dian_ = ${currentPosition}` // 房间信息
  1496. const supplierSql = `select id_,gong_ying_shang_m from t_gysxxb where di_dian_ = ${currentPosition}` // 供应商信息
  1497. const deviceGroupSql = `select id_,suo_shu_bu_men_,wei_hu_gang_wei_ from t_sbwhgwpzb where di_dian_ = ${currentPosition}` // 岗位/分组信息
  1498. const currentTime = dayjs().format('YYYY-MM-DD HH:mm')
  1499. const currentApartment = this.$store.getters.userInfo.employee.positions.split(',').at(-1) || ''
  1500. const currentUser = this.userId
  1501. const partOneInvalidResult = this.deviceInvalidPartOne(importData)
  1502. if (!partOneInvalidResult) return
  1503. importData = this.formatDateFieldsToReal(importData)
  1504. console.log('%c partOne doCheck is completed! %c the result is %c', 'background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;', 'background:#FF5733; padding: 1px; border-radius: 0 3px 3px 0; color: #fff;', 'background:transparent', importData)
  1505. this.loading = true
  1506. Promise.all([this.$common.request('sql', positionSql), this.$common.request('sql', supplierSql), this.$common.request('sql', deviceGroupSql)]).then(async ([res1, res2, res3]) => {
  1507. const { data: positionList = [] } = res1.variables || {}
  1508. const { data: supplierList = [] } = res2.variables || {}
  1509. const { data: deviceGroupList = [] } = res3.variables || {}
  1510. // 根据原设备编号去重,检验原设备编号是否在数据库中存在
  1511. const originalDeviceNoList = await this.filterOriginalDeviceNo(importData, currentPosition)
  1512. await this.handleBasicData(importData, currentTime, currentApartment, currentUser, currentPosition, deptList)
  1513. this.handleExcelData(importData, positionList, supplierList, userList, deviceGroupList)
  1514. // 分离出 已存在的设备,和新设备
  1515. const newDeviceList = importData.filter(i => !originalDeviceNoList.includes(i.yuanSheBeiBian.trim()))
  1516. const existDeviceList = importData.filter(i => originalDeviceNoList.includes(i.yuanSheBeiBian.trim()))
  1517. console.log('%c new device %c', 'background:#FF5733; padding: 1px; border-radius: 0 3px 3px 0; color: #fff;', 'background:transparent', newDeviceList)
  1518. console.log('%c already exist device %c', 'background:#43f80c; padding: 1px; border-radius: 0 3px 3px 0; color: #fff;', 'background:transparent', existDeviceList)
  1519. this.loading = false
  1520. this.$confirm(`<span style="color:#f56c6c; font-size: 18px; font-weight: 600;">
  1521. 经系统判定</span><br>1.预期新导入设备的数量为 ${newDeviceList.length} 台!<br>
  1522. 2.预期更新已存在的设备数量为 ${existDeviceList.length} 台!<br>
  1523. <span style="color:#f56c6c;">Tips:请确认数据无误再点击确定进行导入</span><br><span style="color:#f56c6c; font-size: 18px; font-weight: 600;">请谨慎操作!</span>`, '提示', {
  1524. confirmButtonText: '确定',
  1525. cancelButtonText: '取消',
  1526. dangerouslyUseHTMLString: true,
  1527. type: 'warning'
  1528. }).then(async () => {
  1529. await this.doImportDevice(importData)
  1530. this.loading = true
  1531. setTimeout(() => {
  1532. this.loading = false
  1533. this.$message.success('设备数据导入成功!')
  1534. this.getDatas()
  1535. }, 1000)
  1536. }).catch(() => { })
  1537. }).catch(() => {
  1538. this.loading = false
  1539. })
  1540. },
  1541. async doImportDevice (existDeviceList, currentPosition) {
  1542. this.loading = true
  1543. const allRequests = []
  1544. for (let index = 0; index < existDeviceList.length; index++) {
  1545. const item = existDeviceList[index]
  1546. let params = {}
  1547. if (item.id) {
  1548. // 获取设备数据
  1549. const { data: itemData } = await getequipmentCard({ id: item.id })
  1550. params = { ...itemData, ...item } // 合并数据
  1551. } else {
  1552. params = item // 直接使用当前 item
  1553. }
  1554. console.log(params)
  1555. // 将每个 saveEquipmentCard 请求加入到 allRequests 数组中
  1556. allRequests.push(saveEquipmentCard(params))
  1557. }
  1558. // 等待所有异步请求完成
  1559. await Promise.all(allRequests)
  1560. this.loading = false
  1561. },
  1562. generateDayRule () {
  1563. const days = ['每周1', '每周2', '每周3', '每周4', '每周5', '每周6', '每周7']
  1564. let combinations = []
  1565. for (let length = 1; length <= days.length; length++) {
  1566. this.generateCombinations([], days, combinations)
  1567. }
  1568. combinations = combinations.map(comb => '每周' + comb.map(item => item.slice(2)).join(','))
  1569. combinations.push('每天')
  1570. return combinations
  1571. },
  1572. generateRule (num, prefix, suffix) {
  1573. return Array.from({ length: num }, (_, i) => prefix + `${i + 1}` + suffix)
  1574. },
  1575. generateCombinations (current, remaining, results) {
  1576. if (remaining.length === 0) {
  1577. results.push(current)
  1578. return
  1579. }
  1580. const first = remaining[0]
  1581. const rest = remaining.slice(1)
  1582. // 包括当前数字和不包括当前数字两种情况
  1583. this.generateCombinations(current.concat([first]), rest, results)
  1584. this.generateCombinations(current, rest, results)
  1585. },
  1586. /**
  1587. * 负责导入设备维护项目数据的第一部分校验,全部成功则返回true
  1588. * @param {*} data
  1589. * @returns
  1590. */
  1591. maintenanceInvalidPartOne (data) {
  1592. // 1、对数据进行清洗校验(设备编号不能为空,维护周期、维护项目亦不可为空)
  1593. const invalidResult = this.checkDeviceRequiredFieldsIfEmpty(data, this.maintenanceRequiredFieldMap)
  1594. if (invalidResult.length > 0) {
  1595. this.sendWarningMessages(invalidResult, 'required')
  1596. return false
  1597. }
  1598. // 根据规则校验字段的限定范围
  1599. const allResult = this.checkFieldsRange(data, this.maintenanceValidationRules)
  1600. if (allResult.length > 0) {
  1601. this.sendWarningMessages(allResult, 'range')
  1602. return false
  1603. }
  1604. // 根据规则校验维护周期对应的维护日期的限定范围
  1605. const result = this.checkMaintenanceDateRange(data, this.maintenanceDateValidationRules)
  1606. if (result.length > 0) {
  1607. this.sendWarningMessages(result, 'range')
  1608. return false
  1609. }
  1610. return true
  1611. },
  1612. /**
  1613. * 根据规则校验维护周期对应的维护日期的限定范围
  1614. */
  1615. checkMaintenanceDateRange (list, rules) {
  1616. const msgList = []
  1617. list.forEach(({ weiHuLeiXing: type, weiHuRiQi: exactDate }, index) => {
  1618. if (type === '按需保养') {
  1619. console.log('按需pass2')
  1620. } else {
  1621. if (!rules[type].includes(exactDate)) {
  1622. msgList.push({ row: index + 2, field: '维护日期', value: exactDate })
  1623. }
  1624. }
  1625. })
  1626. return msgList
  1627. },
  1628. async handleUploadChange2 (file) {
  1629. const dataBinary = await this.readFile(file.target.files[0])
  1630. file.target.value = null // 注意上传后要将input的值设为空
  1631. const workBook = xlsx.read(dataBinary, { type: 'binary', cellDates: true })
  1632. const workSheet = workBook.Sheets[workBook.SheetNames[0]]
  1633. const data = xlsx.utils.sheet_to_json(workSheet)
  1634. const importData = this.switchDeviceObj(data, this.projectColums)
  1635. console.log(importData)
  1636. importData.forEach(item => {
  1637. if (item.weiHuLeiXing === '按需保养') {
  1638. item.weiHuRiQi = '/'
  1639. }
  1640. })
  1641. const currentPosition = this.level
  1642. const { userList = [], deptList = [] } = this.$store.getters || {}
  1643. const positionSql = `select id_,fang_jian_ming_ha from t_jjqfjb where di_dian_ = ${currentPosition}` // 房间信息
  1644. const supplierSql = `select id_,gong_ying_shang_m from t_gysxxb where di_dian_ = ${currentPosition}` // 供应商信息
  1645. const deviceGroupSql = `select id_,suo_shu_bu_men_,wei_hu_gang_wei_ from t_sbwhgwpzb where di_dian_ = ${currentPosition}` // 岗位/分组信息
  1646. const currentTime = dayjs().format('YYYY-MM-DD HH:mm')
  1647. const currentApartment = this.$store.getters.userInfo.employee.positions
  1648. const currentUser = this.userId
  1649. const partOneInvalidResult = this.maintenanceInvalidPartOne(importData)
  1650. if (!partOneInvalidResult) return
  1651. // 2、根据原设备编号去重,检验原设备编号是否在数据库中存在,如有不存在的数据,不进行导入,并提示用户
  1652. const uniqueArr = Array.from(new Set(importData.map(i => i.yuanSheBeiBian.trim())))
  1653. /* 3、根据去重的设备编号去查对应的设备ID,然后拼接data数据,赋值设备ID*/
  1654. const sql = `select id_,yuan_she_bei_bian from t_sbdj where find_in_set(yuan_she_bei_bian,'${uniqueArr.join(',')}')and di_dian_ = ${currentPosition}`
  1655. this.$common.request('sql', sql).then(async res => {
  1656. const deviceNoWithIdlist = res.variables.data
  1657. console.log(deviceNoWithIdlist, ' <=> ', uniqueArr)
  1658. const deviceNoSet = new Set(deviceNoWithIdlist.map(i => i.yuan_she_bei_bian))
  1659. const missStr = uniqueArr.filter(i => !deviceNoSet.has(i)).join(',') || ''
  1660. if (missStr !== '') {
  1661. this.$message.error(`设备维护项目数据中包含不存在于设备档案的原设备编号!具体原设备编号为:${missStr}`)
  1662. return
  1663. }
  1664. importData.forEach(item => {
  1665. item.id = deviceNoWithIdlist.find(i => i.yuan_she_bei_bian === item.yuanSheBeiBian).id_
  1666. })
  1667. const resultList = []
  1668. importData.forEach(item => {
  1669. const flag = item.weiHuLeiXing === '日保养'
  1670. const match = item.weiHuRiQi?.match(/\d+/g)
  1671. const o = {
  1672. id: item.id,
  1673. weiHuLeiXing: item.weiHuLeiXing.trim(),
  1674. weiHuRiQi: item.weiHuRiQi?.trim() || '',
  1675. weiHuXiangMuC: item.weiHuXiangMuC.trim(),
  1676. riQiShuZi: match ? (flag ? match.join(',') : match[0]) : ''
  1677. }
  1678. if (o.weiHuLeiXing === '日保养' && o.weiHuRiQi === '每天') o.riQiShuZi = '1,2,3,4,5,6,7'
  1679. resultList.push(o)
  1680. })
  1681. // 4、根据用户选择 进行全量替换|增量添加
  1682. await this.doProjectImport(deviceNoWithIdlist, resultList, this.ImportDeviceType)
  1683. this.$message.success('维护项目数据' + this.ImportDeviceType + '成功!')
  1684. })
  1685. },
  1686. async doProjectImport (deviceNoWithIdlist, resultList, type) {
  1687. this.loading = true
  1688. const allRequests = []
  1689. deviceNoWithIdlist.forEach(async item => {
  1690. const { data: itemData } = await getequipmentCard({ id: item.id_ })
  1691. const temp = resultList.filter(i => i.id === item.id_).map(ii => {
  1692. delete ii.id
  1693. return ii
  1694. })
  1695. let params = {}
  1696. if (type === '增量添加') { // 增量
  1697. params = {
  1698. ...itemData,
  1699. maintenanceItemPoList: [...itemData.maintenanceItemPoList, ...temp]
  1700. }
  1701. } else if (type === '全量替换') { // 全量
  1702. params = {
  1703. ...itemData,
  1704. maintenanceItemPoList: temp
  1705. }
  1706. }
  1707. console.log('params', params)
  1708. allRequests.push(saveEquipmentCard(params))
  1709. })
  1710. await Promise.all(allRequests)
  1711. this.loading = false
  1712. }
  1713. }
  1714. }
  1715. </script>
  1716. <style lang="scss" scoped>
  1717. .icon-image{
  1718. width: 36px;
  1719. }
  1720. .device-image{
  1721. width: 152px;
  1722. height: 110px;
  1723. }
  1724. .title{
  1725. font-size: 12px;
  1726. font-weight: 900;
  1727. color: #333;
  1728. margin: 0 0 14px 20px;
  1729. }
  1730. .ctx{
  1731. margin: 0 0 0 20px;
  1732. .item{
  1733. .cusitem{
  1734. margin: -8px 0;
  1735. display: flex;
  1736. align-items: center;
  1737. }
  1738. .span{
  1739. min-width:60px
  1740. }
  1741. margin: 6px 0;
  1742. color: #999;
  1743. }
  1744. }
  1745. ::v-deep {
  1746. .el-form-item__label{
  1747. text-align: left;
  1748. font-size: 12px !important;
  1749. }
  1750. .el-form-item__ctx{
  1751. font-size: 12px !important;
  1752. }
  1753. }
  1754. </style>