index.vue 64 KB

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