IotDeviceForm1.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. <template>
  2. <ContentWrap v-loading="formLoading">
  3. <el-form
  4. ref="formRef"
  5. :model="formData"
  6. :rules="formRules"
  7. style="margin-right: 4em; margin-left: 0.5em"
  8. label-width="130px">
  9. <div class="title-div">
  10. <el-button @click="baseInfoClick" class="title-button">
  11. <Icon color="black" icon="ep:set-up" :size="18" class="cursor-pointer first-icon" />
  12. <span class="cursor-pointer">{{ t('deviceForm.basic') }}</span>
  13. <Icon
  14. color="black"
  15. :icon="baseIsExpanded ? 'fa-solid:angle-double-down' : 'fa-solid:angle-double-right'"
  16. :size="18"
  17. class="cursor-pointer" />
  18. </el-button>
  19. </div>
  20. <div class="base-expandable-content" :class="{ 'is-expanded': baseIsExpanded }">
  21. <el-row>
  22. <el-col :span="8">
  23. <el-form-item :label="t('iotDevice.yfClass')" prop="yfClass">
  24. <el-cascader
  25. :disabled="formType === 'update' && formData.yfDeviceCode"
  26. style="width: 100%"
  27. v-model="formData.yfClass"
  28. :options="yfclasses"
  29. :props="{ expandTrigger: 'hover' }"
  30. clearable
  31. filterable
  32. @change="handleYfClassChange" />
  33. </el-form-item>
  34. </el-col>
  35. <el-col :span="8">
  36. <el-form-item :label="t('iotDevice.yfCode')" prop="yfDeviceCode">
  37. <el-input
  38. v-model="formData.yfDeviceCode"
  39. :disabled="formData.yfDeviceCode"
  40. placeholder="请输入油服设备编码" />
  41. </el-form-item>
  42. </el-col>
  43. <el-col :span="8">
  44. <el-form-item :label="t('iotDevice.code')" prop="deviceCode">
  45. <el-input
  46. v-model="formData.deviceCode"
  47. :disabled="formType === 'update'"
  48. placeholder="请输入设备编码" />
  49. </el-form-item>
  50. </el-col>
  51. <el-col :span="8">
  52. <el-form-item :label="t('iotDevice.name')" prop="deviceName">
  53. <lang-input v-model="formData.deviceName" placeholder="请输入设备名称" />
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="8">
  57. <el-form-item :label="t('iotDevice.dept')" prop="deptId">
  58. <el-tree-select
  59. :disabled="formType === 'update'"
  60. v-model="formData.deptId"
  61. :data="deptList"
  62. :props="defaultProps"
  63. check-strictly
  64. node-key="id"
  65. filterable
  66. placeholder="请选择所在部门" />
  67. <!-- <el-tree-select-->
  68. <!-- v-model="formData.deptId"-->
  69. <!-- :data="deptList"-->
  70. <!-- :props="defaultProps"-->
  71. <!-- check-strictly-->
  72. <!-- node-key="id"-->
  73. <!-- placeholder="请选择归属部门"-->
  74. <!-- />-->
  75. </el-form-item>
  76. </el-col>
  77. <el-col :span="8">
  78. <el-form-item :label="t('deviceForm.category')" prop="assetClass">
  79. <el-tree-select
  80. :disabled="formType === 'update' && username !== '超级管理员'"
  81. v-model="formData.assetClass"
  82. :data="productClassifyList"
  83. :props="defaultProps"
  84. check-strictly
  85. node-key="id"
  86. :placeholder="t('deviceForm.categoryHolder')"
  87. @change="assetclasschange"
  88. filterable />
  89. </el-form-item>
  90. </el-col>
  91. <el-col :span="8">
  92. <el-form-item :label="t('iotDevice.status')" prop="deviceStatus">
  93. <el-select
  94. v-model="formData.deviceStatus"
  95. :placeholder="t('deviceForm.choose')"
  96. :disabled="formType === 'update'"
  97. clearable>
  98. <el-option
  99. v-for="dict in getStrDictOptions(DICT_TYPE.PMS_DEVICE_STATUS)"
  100. :key="dict.label"
  101. :label="dict.label"
  102. :value="dict.value" />
  103. </el-select>
  104. </el-form-item>
  105. </el-col>
  106. <el-col :span="8">
  107. <el-form-item :label="t('iotDevice.assets')" prop="assetProperty">
  108. <el-select v-model="formData.assetProperty" placeholder="请选择" clearable>
  109. <el-option
  110. v-for="dict in getStrDictOptions(DICT_TYPE.PMS_ASSET_PROPERTY)"
  111. :key="dict.id"
  112. :label="dict.label"
  113. :value="dict.value" />
  114. </el-select>
  115. </el-form-item>
  116. </el-col>
  117. <el-col :span="8">
  118. <el-form-item :label="t('iotDevice.brand')" prop="brandName">
  119. <el-select
  120. clearable
  121. v-model="formData.brandName"
  122. @clear="brandClear"
  123. :placeholder="t('iotDevice.brandHolder')"
  124. @click="openForm" />
  125. </el-form-item>
  126. </el-col>
  127. <el-col :span="8">
  128. <el-form-item label="车牌号" prop="carNo">
  129. <el-input clearable v-model="formData.carNo" placeholder="请输入车牌号" />
  130. </el-form-item>
  131. </el-col>
  132. <el-col :span="8">
  133. <el-form-item label="设备号" prop="deviceNo">
  134. <el-input clearable v-model="formData.deviceNo" placeholder="请输入设备号" />
  135. </el-form-item>
  136. </el-col>
  137. <el-col :span="8">
  138. <div style="display: flex; flex-direction: row">
  139. <el-form-item :label="t('deviceForm.model')" prop="model" style="width: 86%">
  140. <el-input
  141. clearable
  142. v-model="formData.model"
  143. :placeholder="t('deviceForm.modelHolder')" />
  144. </el-form-item>
  145. <el-button type="info" @click="openModelForm">请选择</el-button>
  146. </div>
  147. </el-col>
  148. <el-col :span="8">
  149. <el-form-item :label="t('deviceForm.useProject')" prop="useProject">
  150. <el-input v-model="formData.useProject" :disabled="isDetail" height="60px" />
  151. </el-form-item>
  152. </el-col>
  153. <el-col :span="8">
  154. <el-form-item :label="t('deviceForm.assetOwner')" prop="assetOwnership">
  155. <el-input v-model="formData.assetOwnership" :disabled="isDetail" height="60px" />
  156. </el-form-item>
  157. </el-col>
  158. <el-col :span="8">
  159. <el-form-item label="所在地点" prop="address">
  160. <el-input v-model="formData.address" height="60px" />
  161. </el-form-item>
  162. </el-col>
  163. <el-col :span="8">
  164. <el-form-item :label="t('deviceForm.picture')" prop="picUrl">
  165. <UploadImg v-model="formData.picUrl" :disabled="isDetail" height="60px" />
  166. </el-form-item>
  167. </el-col>
  168. <el-col :span="8">
  169. <el-form-item :label="t('deviceForm.remark')" prop="remark">
  170. <el-input
  171. v-model="formData.remark"
  172. type="textarea"
  173. :placeholder="t('deviceForm.remarkHolder')" />
  174. </el-form-item>
  175. </el-col>
  176. </el-row>
  177. </div>
  178. <div class="title-div">
  179. <el-button @click="zzInfoClick" class="title-button">
  180. <Icon color="black" icon="ep:set-up" :size="18" class="cursor-pointer first-icon" />
  181. <span class="cursor-pointer">{{ t('deviceForm.make') }}</span>
  182. <Icon
  183. color="black"
  184. :icon="zzIsExpanded ? 'fa-solid:angle-double-down' : 'fa-solid:angle-double-right'"
  185. :size="18"
  186. class="cursor-pointer" />
  187. </el-button>
  188. </div>
  189. <div class="zz-expandable-content" :class="{ 'is-expanded': zzIsExpanded }">
  190. <el-row>
  191. <el-col :span="8">
  192. <el-form-item :label="t('deviceForm.mfg')" prop="manufacturerId">
  193. <el-select
  194. clearable
  195. @clear="zzClear"
  196. v-model="formData.manufacturerName"
  197. :placeholder="t('deviceForm.mfgHolder')"
  198. @click="openCustomerZz" />
  199. </el-form-item>
  200. </el-col>
  201. <el-col :span="8">
  202. <el-form-item :label="t('deviceForm.pd')" prop="manDate">
  203. <el-date-picker
  204. style="width: 150%"
  205. v-model="formData.manDate"
  206. type="date"
  207. value-format="x"
  208. :placeholder="t('deviceForm.pdHolder')" />
  209. </el-form-item>
  210. </el-col>
  211. <el-col :span="8">
  212. <el-form-item :label="t('deviceForm.supplier')" prop="supplierId">
  213. <el-select
  214. clearable
  215. @clear="supplierClear"
  216. v-model="formData.supplierName"
  217. :placeholder="t('deviceForm.suppHolder')"
  218. @click="openCustomerSupplier" />
  219. </el-form-item>
  220. </el-col>
  221. <el-col :span="8">
  222. <el-form-item :label="t('deviceForm.warranty')" prop="expires">
  223. <el-date-picker
  224. style="width: 150%"
  225. v-model="formData.expires"
  226. type="date"
  227. value-format="x"
  228. :placeholder="t('deviceForm.warrHolder')" />
  229. </el-form-item>
  230. </el-col>
  231. <el-col :span="8">
  232. <el-form-item :label="t('deviceForm.enable')" prop="enableDate">
  233. <el-date-picker
  234. style="width: 150%"
  235. v-model="formData.enableDate"
  236. type="date"
  237. value-format="x"
  238. :placeholder="t('deviceForm.enableHolder')" />
  239. </el-form-item>
  240. </el-col>
  241. <el-col :span="8">
  242. <el-form-item :label="t('deviceForm.ni')" prop="nameplate">
  243. <el-input
  244. v-model="formData.nameplate"
  245. type="textarea"
  246. :placeholder="t('deviceForm.niHolder')" />
  247. </el-form-item>
  248. </el-col>
  249. </el-row>
  250. </div>
  251. <div class="title-div">
  252. <el-button @click="cwInfoClick" class="title-button">
  253. <Icon color="black" icon="ep:set-up" :size="18" class="cursor-pointer first-icon" />
  254. <span class="cursor-pointer">{{ t('deviceForm.finance') }}</span>
  255. <Icon
  256. color="black"
  257. :icon="cwIsExpanded ? 'fa-solid:angle-double-down' : 'fa-solid:angle-double-right'"
  258. :size="18"
  259. class="cursor-pointer" />
  260. </el-button>
  261. </div>
  262. <div class="cw-expandable-content" :class="{ 'is-expanded': cwIsExpanded }">
  263. <el-row>
  264. <el-col :span="8">
  265. <el-form-item
  266. :label="formData.assetProperty === 'zy' ? '采购价格' : '租赁价格'"
  267. prop="plPrice">
  268. <el-input
  269. v-model="formData.plPrice"
  270. @input="handleInput(formData.plPrice, 'plPrice')"
  271. :placeholder="
  272. formData.assetProperty === 'zy' ? '请输入采购价格' : '请输入租赁价格'
  273. " />
  274. </el-form-item>
  275. </el-col>
  276. <el-col :span="8">
  277. <el-form-item
  278. :label="formData.assetProperty === 'zy' ? '采购日期' : '租赁日期'"
  279. prop="plDate">
  280. <el-date-picker
  281. style="width: 150%"
  282. v-model="formData.plDate"
  283. type="date"
  284. value-format="x"
  285. :placeholder="
  286. formData.assetProperty === 'zy' ? '请输入采购日期' : '请输入租赁日期'
  287. " />
  288. </el-form-item>
  289. </el-col>
  290. <el-col :span="8">
  291. <el-form-item
  292. :label="formData.assetProperty === 'zy' ? '折旧年限' : '租赁年限'"
  293. prop="plYear">
  294. <el-input
  295. v-model="formData.plYear"
  296. type="number"
  297. :placeholder="
  298. formData.assetProperty === 'zy' ? '请输入折旧年限' : '请输入租赁年限'
  299. " />
  300. </el-form-item>
  301. </el-col>
  302. <el-col :span="8">
  303. <el-form-item
  304. :label="formData.assetProperty === 'zy' ? '折旧开始日期' : '租赁开始日期'"
  305. prop="plStartDate">
  306. <el-date-picker
  307. style="width: 150%"
  308. v-model="formData.plStartDate"
  309. type="date"
  310. value-format="x"
  311. :placeholder="
  312. formData.assetProperty === 'zy' ? '请选择折旧开始日期' : '请选择租赁开始日期'
  313. " />
  314. </el-form-item>
  315. </el-col>
  316. <el-col :span="8">
  317. <el-form-item
  318. :label="formData.assetProperty === 'zy' ? '已提折旧月数' : '已租赁月数'"
  319. prop="plMonthed">
  320. <el-input
  321. v-model="formData.plMonthed"
  322. type="number"
  323. :placeholder="
  324. formData.assetProperty === 'zy' ? '请输入已提折旧月数' : '请输入已租赁月数'
  325. " />
  326. </el-form-item>
  327. </el-col>
  328. <el-col :span="8">
  329. <el-form-item
  330. :label="formData.assetProperty === 'zy' ? '已提折旧金额' : '已租赁金额'"
  331. prop="plAmounted">
  332. <el-input
  333. v-model="formData.plAmounted"
  334. @input="handleInput(formData.plAmounted, 'plAmounted')"
  335. :placeholder="
  336. formData.assetProperty === 'zy' ? '请输入已提折旧金额' : '已租赁金额'
  337. " />
  338. </el-form-item>
  339. </el-col>
  340. <el-col :span="8">
  341. <el-form-item label="剩余金额" prop="remainAmount">
  342. <el-input
  343. v-model="formData.remainAmount"
  344. @input="handleInput(formData.remainAmount, 'remainAmount')"
  345. placeholder="请输入剩余金额" />
  346. </el-form-item>
  347. </el-col>
  348. <el-col :span="8">
  349. <el-form-item label="每月折旧金额" prop="monthAmount">
  350. <el-input
  351. v-model="formData.monthAmount"
  352. @input="handleInput(formData.monthAmount, 'monthAmount')"
  353. placeholder="请输入每月折旧金额" />
  354. </el-form-item>
  355. </el-col>
  356. <el-col :span="8">
  357. <el-form-item label="总折旧月份" prop="totalMonth">
  358. <el-input
  359. v-model="formData.totalMonth"
  360. @input="handleInput(formData.totalMonth, 'totalMonth')"
  361. placeholder="请输入总折旧月份" />
  362. </el-form-item>
  363. </el-col>
  364. <el-col :span="8">
  365. <el-form-item label="币种" prop="currency">
  366. <el-input v-model="formData.currency" placeholder="请输入币种" />
  367. </el-form-item>
  368. </el-col>
  369. </el-row>
  370. </div>
  371. <div class="title-div">
  372. <el-button @click="qtInfoClick" class="title-button">
  373. <Icon color="black" icon="ep:set-up" :size="18" class="cursor-pointer first-icon" />
  374. <span class="cursor-pointer">{{ t('deviceForm.other') }}</span>
  375. <Icon
  376. color="black"
  377. :icon="qtIsExpanded ? 'fa-solid:angle-double-down' : 'fa-solid:angle-double-right'"
  378. :size="18"
  379. class="cursor-pointer" />
  380. </el-button>
  381. </div>
  382. <div class="qt-expandable-content" :class="{ 'is-expanded': qtIsExpanded }">
  383. <el-row>
  384. <el-col v-for="field in list" :key="field.sort" :span="8">
  385. <el-form-item
  386. label-width="180px"
  387. :label="field.name"
  388. :prop="field.code"
  389. :rules="field.rules">
  390. <!-- 文本输入 -->
  391. <el-input
  392. v-if="field.type === 'text'"
  393. v-model="formData[field.code]"
  394. :placeholder="'请输入' + field.name"
  395. :type="field.type || 'text'" />
  396. <el-select
  397. v-else-if="field.type === 'enum'"
  398. v-model="formData[field.code]"
  399. :placeholder="'请输入' + field.name"
  400. clearable
  401. filterable>
  402. <el-option
  403. v-for="item in field.selectOptions.dataSpecsList"
  404. :key="item.name"
  405. :label="item.name"
  406. :value="item.name" />
  407. </el-select>
  408. <!-- 数字输入 -->
  409. <el-input
  410. v-else-if="field.type === 'int'"
  411. type="number"
  412. v-model="formData[field.code]"
  413. style="width: 150%" />
  414. <el-input
  415. v-else-if="field.type === 'double'"
  416. v-model="formData[field.code]"
  417. @input="handleInput(formData[field.code], field.code)"
  418. style="width: 150%" />
  419. <!-- 日期选择 -->
  420. <el-date-picker
  421. v-else-if="field.type === 'date'"
  422. v-model="formData[field.code]"
  423. :type="field.type || 'date'"
  424. :placeholder="'请输入' + field.name"
  425. value-format="YYYY-MM-DD"
  426. style="width: 150%" />
  427. </el-form-item>
  428. </el-col>
  429. </el-row>
  430. </div>
  431. </el-form>
  432. <el-form>
  433. <el-form-item style="float: right">
  434. <el-button type="success" @click="allzhankai">{{ t('deviceForm.expand') }}</el-button>
  435. <el-button type="info" @click="allshouqi">{{ t('deviceForm.close') }}</el-button>
  436. <el-button v-if="!isDetail" :loading="formLoading" type="warning" @click="submitForm">
  437. {{ t('deviceForm.save') }}
  438. </el-button>
  439. <el-button @click="close" type="primary">{{ t('deviceForm.return') }}</el-button>
  440. </el-form-item>
  441. </el-form>
  442. </ContentWrap>
  443. <BrandList ref="brandFormRef" @choose="brandChoose" />
  444. <ModelList ref="modelFormRef" @choose="modelChoose" :brand="formData.brand" />
  445. <CustomerList ref="customerZzFormRef" @choose="customerZzChoose" />
  446. <CustomerList ref="customerSupplierFormRef" @choose="customerSupplierChoose" />
  447. </template>
  448. <script setup lang="ts">
  449. import { IotDeviceApi, IotDeviceVO } from '@/api/pms/device'
  450. import BrandList from '@/views/pms/device/BrandList.vue'
  451. import ModelList from '@/views/pms/device/ModelList.vue'
  452. import CustomerList from '@/views/pms/device/CustomerList.vue'
  453. import { defaultProps, handleTree } from '@/utils/tree'
  454. import * as DeptApi from '@/api/system/dept'
  455. import * as ProductClassifyApi from '@/api/pms/productclassify'
  456. import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
  457. import { useTagsViewStore } from '@/store/modules/tagsView'
  458. import { DeviceAttrModelApi } from '@/api/pms/deviceattrmodel'
  459. import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
  460. import { IotYfClassifyApi } from '@/api/pms/yfclass'
  461. import { useRefreshStore } from '@/store/modules/pms/refreshStore'
  462. import { watch } from 'vue'
  463. /** 设备台账 表单 */
  464. defineOptions({ name: 'DeviceDetailAdd' })
  465. const baseIsExpanded = ref(true) // 控制表单是否展开的变量
  466. const zzIsExpanded = ref(true) // 控制表单是否展开的变量
  467. const cwIsExpanded = ref(true) // 控制表单是否展开的变量
  468. const qtIsExpanded = ref(true) // 控制表单是否展开的变量
  469. const username = ref('')
  470. const deptList = ref<Tree[]>([]) // 树形结构
  471. const productClassifyList = ref<Tree[]>([]) // 树形结构
  472. const { delView } = useTagsViewStore() // 视图操作
  473. const { params, name, query } = useRoute() // 查询参数
  474. const { currentRoute, push } = useRouter()
  475. const { wsCache } = useCache()
  476. const id = params.id
  477. const type = params.type
  478. const deptId = params.deptId
  479. const isDetail = params.isDetail
  480. const { t } = useI18n() // 国际化
  481. const message = useMessage() // 消息弹窗
  482. const dialogVisible = ref(false) // 弹窗的是否展示
  483. const dialogTitle = ref('') // 弹窗的标题
  484. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  485. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  486. const brandLabel = ref('') // 表单的类型:create - 新增;update - 修改
  487. const zzLabel = ref('') // 表单的类型:create - 新增;update - 修改
  488. const supplierLabel = ref('') // 表单的类型:create - 新增;update - 修改
  489. const yfclasses = ref([])
  490. const refreshStore = useRefreshStore()
  491. const formData = ref({
  492. id: undefined,
  493. yfClass: undefined,
  494. yfDeviceCode: undefined,
  495. enableDate: undefined,
  496. deviceCode: undefined,
  497. deviceName: undefined,
  498. brand: undefined,
  499. brandName: undefined,
  500. model: undefined,
  501. deptId: undefined,
  502. deviceStatus: undefined,
  503. assetProperty: undefined,
  504. picUrl: undefined,
  505. assetOwnership: undefined,
  506. remark: undefined,
  507. useProject: undefined,
  508. manufacturerId: undefined,
  509. manufacturerName: undefined,
  510. supplierId: undefined,
  511. supplierName: undefined,
  512. manDate: undefined,
  513. nameplate: undefined,
  514. expires: undefined,
  515. plPrice: undefined,
  516. plDate: undefined,
  517. plYear: undefined,
  518. plStartDate: undefined,
  519. plMonthed: undefined,
  520. plAmounted: undefined,
  521. remainAmount: undefined,
  522. infoId: undefined,
  523. infoType: undefined,
  524. infoName: undefined,
  525. infoRemark: undefined,
  526. infoUrl: undefined,
  527. templateJson: undefined,
  528. assetClass: undefined,
  529. carNo: undefined,
  530. deviceNo: undefined,
  531. address: undefined,
  532. monthAmount: undefined,
  533. totalMonth: undefined,
  534. currency: undefined
  535. })
  536. const formRules = reactive({
  537. yfClass: [
  538. {
  539. validator: (rule, value, callback) => {
  540. // 当资产性质为租赁('zl')时,yfClass非必填;否则必填
  541. if (formData.value.assetProperty === 'zl' || value) {
  542. callback() // 租赁资产或有值时通过验证
  543. } else {
  544. callback(new Error('编码类别不能为空')) // 非租赁资产且无值时失败
  545. }
  546. },
  547. trigger: 'blur'
  548. }
  549. ],
  550. yfDeviceCode: [{ required: true, message: '油服编码不能为空', trigger: 'blur' }],
  551. assetClass: [{ required: true, message: '资产类别不能为空', trigger: 'blur' }],
  552. deviceCode: [{ required: true, message: '设备编码不能为空', trigger: 'blur' }],
  553. deviceName: [{ required: true, message: '设备名称不能为空', trigger: 'blur' }],
  554. brandName: [{ required: true, message: '品牌不能为空', trigger: 'blur' }],
  555. deptId: [{ required: true, message: '所在部门不能为空', trigger: 'blur' }],
  556. deviceStatus: [{ required: true, message: '设备状态不能为空', trigger: 'blur' }],
  557. assetProperty: [{ required: true, message: '资产性质不能为空', trigger: 'blur' }],
  558. manufacturerId: [{ required: true, message: '制造商id不能为空', trigger: 'blur' }],
  559. manDate: [{ required: true, message: '生产日期不能为空', trigger: 'blur' }]
  560. })
  561. const list = ref([])
  562. const handleYfClassChange = async (value) => {
  563. console.log(value)
  564. const prefix = value.join('')
  565. const last = await IotDeviceApi.getMaxCode(prefix)
  566. formData.value.yfDeviceCode = prefix + last
  567. }
  568. const assetclasschange = () => {
  569. const assetClass = formData.value.assetClass
  570. DeviceAttrModelApi.getDeviceAttrModelListByDeviceCategoryId(assetClass).then((res) => {
  571. if (res) {
  572. res.forEach((item) => {
  573. if (item.requiredFlag) {
  574. const rule = { required: true, message: item.name + '不能为空', trigger: 'blur' }
  575. item.rules = []
  576. item.rules.push(rule)
  577. }
  578. })
  579. list.value = res
  580. } else {
  581. list.value = []
  582. }
  583. })
  584. }
  585. watch(
  586. () => formData.value.assetProperty,
  587. (newVal) => {
  588. nextTick(() => {
  589. if (formRef.value) {
  590. // 重新验证 yfClass 和 yfCode 字段
  591. formRef.value.validateField('yfClass')
  592. }
  593. })
  594. },
  595. { immediate: true }
  596. )
  597. const brandChoose = (row) => {
  598. formData.value.brand = row.id
  599. // brandLabel.value = row.value
  600. formData.value.brandName = row.label
  601. }
  602. const brandClear = () => {
  603. formData.value.brand = undefined
  604. formData.value.brandName = undefined
  605. }
  606. const modelChoose = (row) => {
  607. formData.value.model = row.name
  608. }
  609. const customerSupplierChoose = (row) => {
  610. formData.value.supplierId = row.id
  611. formData.value.supplierName = row.name
  612. // supplierLabel.value = row.name
  613. }
  614. const supplierClear = (row) => {
  615. formData.value.supplierId = undefined
  616. formData.value.supplierName = undefined
  617. }
  618. const customerZzChoose = (row) => {
  619. formData.value.manufacturerId = row.id
  620. // zzLabel.value = row.name
  621. formData.value.manufacturerName = row.name
  622. }
  623. const zzClear = () => {
  624. formData.value.manufacturerId = undefined
  625. formData.value.manufacturerName = undefined
  626. }
  627. /** 添加/修改操作 */
  628. const brandFormRef = ref()
  629. const openForm = () => {
  630. brandFormRef.value.open()
  631. }
  632. const modelFormRef = ref()
  633. const openModelForm = () => {
  634. modelFormRef.value.open()
  635. }
  636. const customerSupplierFormRef = ref()
  637. const openCustomerSupplier = () => {
  638. customerSupplierFormRef.value.open()
  639. }
  640. const customerZzFormRef = ref()
  641. const openCustomerZz = () => {
  642. customerZzFormRef.value.open()
  643. }
  644. const allshouqi = () => {
  645. baseIsExpanded.value = false
  646. zzIsExpanded.value = false
  647. cwIsExpanded.value = false
  648. qtIsExpanded.value = false
  649. }
  650. const allzhankai = () => {
  651. baseIsExpanded.value = true
  652. zzIsExpanded.value = true
  653. cwIsExpanded.value = true
  654. qtIsExpanded.value = true
  655. }
  656. const handleInput = (value, obj) => {
  657. // 1. 过滤非法字符(只允许数字和小数点)
  658. let filtered = value.replace(/[^\d.]/g, '')
  659. // 2. 处理多个小数点的情况
  660. filtered = filtered.replace(/\.{2,}/g, '.')
  661. // 3. 限制小数点后最多两位
  662. let decimalParts = filtered.split('.')
  663. if (decimalParts.length > 1) {
  664. decimalParts = decimalParts.slice(0, 2)
  665. filtered = decimalParts.join('.')
  666. }
  667. // 4. 处理以小数点开头的情况(自动补0)
  668. if (filtered.startsWith('.')) {
  669. filtered = '0' + filtered
  670. }
  671. // 5. 更新绑定值(同时处理连续输入多个0的情况)
  672. formData.value[obj] = filtered.replace(/^0+(?=\d)/, '')
  673. }
  674. const close = () => {
  675. delView(unref(currentRoute))
  676. push({ name: 'IotDevicePms', params: {} })
  677. // delView(unref(currentRoute))
  678. // push({
  679. // name: 'IotDevicePms',
  680. // query: {
  681. // date: new Date().getTime()
  682. // }
  683. // })
  684. }
  685. const baseInfoClick = () => {
  686. baseIsExpanded.value = !baseIsExpanded.value // 切换展开状态
  687. }
  688. const zzInfoClick = () => {
  689. zzIsExpanded.value = !zzIsExpanded.value // 切换展开状态
  690. }
  691. const cwInfoClick = () => {
  692. cwIsExpanded.value = !cwIsExpanded.value // 切换展开状态
  693. }
  694. const qtInfoClick = () => {
  695. qtIsExpanded.value = !qtIsExpanded.value // 切换展开状态
  696. }
  697. /** 提交表单 */
  698. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  699. const formRef = ref()
  700. const submitForm = async () => {
  701. // 校验表单
  702. await formRef.value.validate()
  703. // 提交请求
  704. formLoading.value = true
  705. try {
  706. if (list.value) {
  707. list.value = list.value.map((item) => ({
  708. ...item,
  709. value: formData.value[item.code] // 自定义属性生成逻辑
  710. }))
  711. formData.value.templateJson = JSON.stringify(list.value)
  712. }
  713. formData.value.yfClass = formData.value.yfClass.join(',')
  714. const data = formData.value as unknown as IotDeviceVO
  715. if (formType.value === 'create') {
  716. await IotDeviceApi.createIotDevice(data)
  717. message.success(t('common.createSuccess'))
  718. } else {
  719. await IotDeviceApi.updateIotDevice(data)
  720. message.success(t('common.updateSuccess'))
  721. }
  722. dialogVisible.value = false
  723. // 发送操作成功的事件
  724. //emit('success')
  725. const sourcePage = query.source as string
  726. // 如果有来源页面标识,触发原页面的刷新
  727. if (sourcePage) {
  728. refreshStore.triggerRefresh(sourcePage)
  729. }
  730. close()
  731. } finally {
  732. formLoading.value = false
  733. }
  734. }
  735. onMounted(async () => {
  736. const userInfo = wsCache.get(CACHE_KEY.USER)
  737. // NOTE: 是否需要像`setUserInfoAction`一样判断`userInfo != null`
  738. username.value = userInfo.user.nickname
  739. deptList.value = handleTree(await DeptApi.getSimpleDeptList())
  740. productClassifyList.value = handleTree(
  741. await ProductClassifyApi.IotProductClassifyApi.getSimpleProductClassifyList()
  742. )
  743. formData.value.assetProperty = 'zy'
  744. // 修改时,设置数据
  745. if (id) {
  746. formType.value = 'update'
  747. formLoading.value = true
  748. try {
  749. const iotDevice = await IotDeviceApi.getIotDevice(id)
  750. formData.value = iotDevice
  751. formData.value.brandName = iotDevice.brandName
  752. formData.value.manufacturerName = iotDevice.zzName
  753. formData.value.supplierName = iotDevice.supplierName
  754. formData.value.carNo = iotDevice.carNo
  755. formData.value.deviceNo = iotDevice.deviceNo
  756. formData.value.address = iotDevice.address
  757. if (iotDevice.yfClass) {
  758. formData.value.yfClass = iotDevice.yfClass.split(',')
  759. }
  760. list.value = JSON.parse(iotDevice.templateJson)
  761. list.value.forEach((item) => {
  762. formData.value[item.code] = item.value
  763. })
  764. } finally {
  765. formLoading.value = false
  766. }
  767. } else {
  768. if (deptId) {
  769. formData.value.deptId = Number(deptId)
  770. }
  771. formType.value = 'create'
  772. }
  773. await IotYfClassifyApi.getChildrenList().then((res) => {
  774. yfclasses.value = res
  775. })
  776. })
  777. /** 重置表单 */
  778. const resetForm = () => {
  779. formData.value = {
  780. id: undefined,
  781. deviceCode: undefined,
  782. deviceName: undefined,
  783. brand: undefined,
  784. model: undefined,
  785. deptId: undefined,
  786. deviceStatus: undefined,
  787. assetProperty: undefined,
  788. picUrl: undefined,
  789. remark: undefined,
  790. manufacturerId: undefined,
  791. supplierId: undefined,
  792. manDate: undefined,
  793. nameplate: undefined,
  794. expires: undefined,
  795. plPrice: undefined,
  796. plDate: undefined,
  797. plYear: undefined,
  798. plStartDate: undefined,
  799. plMonthed: undefined,
  800. plAmounted: undefined,
  801. remainAmount: undefined,
  802. infoId: undefined,
  803. infoType: undefined,
  804. infoName: undefined,
  805. infoRemark: undefined,
  806. infoUrl: undefined,
  807. templateJson: undefined,
  808. assetClass: undefined
  809. }
  810. formRef.value?.resetFields()
  811. }
  812. </script>
  813. <style scoped lang="scss">
  814. .base-expandable-content {
  815. max-height: 0; /* 初始高度为0 */
  816. overflow: hidden; /* 隐藏溢出的内容 */
  817. transition: max-height 0.3s ease; /* 平滑过渡效果 */
  818. }
  819. .base-expandable-content.is-expanded {
  820. min-height: 350px; /* 或者根据内容设定一个合适的最大高度 */
  821. }
  822. .zz-expandable-content {
  823. max-height: 0; /* 初始高度为0 */
  824. overflow: hidden; /* 隐藏溢出的内容 */
  825. transition: max-height 0.3s ease; /* 平滑过渡效果 */
  826. }
  827. .zz-expandable-content.is-expanded {
  828. min-height: 130px; /* 或者根据内容设定一个合适的最大高度 */
  829. }
  830. .cw-expandable-content {
  831. max-height: 0; /* 初始高度为0 */
  832. overflow: hidden; /* 隐藏溢出的内容 */
  833. transition: max-height 0.3s ease; /* 平滑过渡效果 */
  834. }
  835. .cw-expandable-content.is-expanded {
  836. max-height: 200px; /* 或者根据内容设定一个合适的最大高度 */
  837. }
  838. .qt-expandable-content {
  839. max-height: 0; /* 初始高度为0 */
  840. overflow: hidden; /* 隐藏溢出的内容 */
  841. transition: max-height 0.3s ease; /* 平滑过渡效果 */
  842. }
  843. .qt-expandable-content.is-expanded {
  844. max-height: 1200px; /* 或者根据内容设定一个合适的最大高度 */
  845. }
  846. .title-button {
  847. font-size: 18px;
  848. border: none;
  849. }
  850. .title-div {
  851. margin-bottom: 20px;
  852. margin-top: 10px;
  853. }
  854. .cursor-pointer {
  855. vertical-align: middle;
  856. }
  857. .first-icon {
  858. margin-bottom: 2px;
  859. }
  860. </style>