_meter.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <script setup lang="ts" name="Meter">
  2. import apis from "@a"
  3. import message from "@@/utils/message"
  4. import dayjs from "dayjs"
  5. const props = withDefaults(defineProps<{ id: number }>(), { id: 0 })
  6. const { id: parentId } = toRefs(props)
  7. const protocolOptions = ref<any[]>([])
  8. const reportProtocolOptions = ref<any[]>([])
  9. const isAdd = ref(false)
  10. const tableRef = ref()
  11. const modalRef = ref()
  12. const opts = reactive<any>({
  13. columns: [
  14. { field: "id", name: "ID", width: 100, visible: false, isSort: false, tooltip: true },
  15. { field: "sn", name: "设备编码", width: "auto", isSort: true, visible: true },
  16. { field: "name", name: "表计名称", width: "auto", isSort: true, visible: true },
  17. // { field: "type", name: "设备类型", width: 100, isSort: true, visible: true },
  18. { field: "protocol", name: "表计协议", width: 200, isSort: true, visible: true },
  19. { field: "address", name: "表计串口地址", width: 130, isSort: false, visible: true },
  20. // { field: "mode", name: "设备模式", width: 180, isSort: false, visible: true },
  21. { field: "createdAt", name: "创建时间", width: 185, isSort: true, visible: true },
  22. { field: "actions", name: `操作`, width: 150 }
  23. ],
  24. queryParams: {
  25. parentId: parentId.value,
  26. sn: undefined,
  27. name: undefined,
  28. type: 2,
  29. dateRange: []
  30. },
  31. searchFormItems: [
  32. {
  33. field: "sn",
  34. label: "设备编码",
  35. class: "w-100",
  36. component: "I",
  37. listeners: {
  38. keyup: (e: any) => {
  39. if (e.code == "Enter") {
  40. handleQuery()
  41. }
  42. }
  43. }
  44. },
  45. {
  46. field: "name",
  47. label: "设备名称",
  48. class: "w-100",
  49. component: "I",
  50. listeners: {
  51. keyup: (e: any) => {
  52. if (e.code == "Enter") {
  53. handleQuery()
  54. }
  55. }
  56. }
  57. },
  58. {
  59. field: "dateRange",
  60. label: "创建时间",
  61. class: "w-100",
  62. component: "D",
  63. placeholder: "请选择创建时间",
  64. props: {
  65. type: "daterange",
  66. valueFormat: "YYYY-MM-DD",
  67. rangeSeparator: "-",
  68. startPlaceholder: "开始日期",
  69. endPlaceholder: "结束日期"
  70. },
  71. listeners: {
  72. change: (v: any) => {
  73. queryParams.value.dateRange = v
  74. }
  75. }
  76. }
  77. ] as any,
  78. permission: "",
  79. handleFuns: {},
  80. customBtns: [],
  81. tableListFun: apis.iot.deviceApi.listDevice,
  82. getEntityFun: apis.iot.deviceApi.getDevice,
  83. deleteEntityFun: apis.iot.deviceApi.delDevice,
  84. formItems: [
  85. {
  86. show: () => !isAdd.value,
  87. field: "sn",
  88. label: "设备编码",
  89. class: "w-100",
  90. component: "I",
  91. required: true,
  92. props: {
  93. disabled: true
  94. },
  95. span: 24
  96. },
  97. {
  98. show: false,
  99. field: "mode",
  100. label: "设备模式",
  101. class: "w-100",
  102. required: false,
  103. component: "Dict",
  104. props: {
  105. disabled: true,
  106. type: "radio",
  107. valueIsNumber: true,
  108. clearable: true,
  109. placeholder: "请选择设备模式",
  110. dictType: "iot_device_mode"
  111. },
  112. span: 24
  113. },
  114. {
  115. field: "name",
  116. label: "设备名称",
  117. class: "w-100",
  118. component: "I",
  119. required: true,
  120. span: 24
  121. },
  122. {
  123. field: "protocol",
  124. label: "表计协议",
  125. class: "w-100",
  126. required: true,
  127. component: "VS",
  128. placeholder: "请选择表计协议",
  129. data: () => protocolOptions.value,
  130. props: {
  131. type: "select",
  132. clearable: true
  133. },
  134. span: 12
  135. },
  136. {
  137. field: "address",
  138. label: "表计地址",
  139. class: "w-100",
  140. component: "I",
  141. type: "number",
  142. required: true,
  143. span: 12
  144. },
  145. {
  146. field: "dsn",
  147. label: "平台上报",
  148. class: "w-100",
  149. component: "slot",
  150. span: 24
  151. },
  152. {
  153. field: "bmYz",
  154. label: "编码因子",
  155. class: "w-100",
  156. component: "I",
  157. type: "textarea",
  158. required: false
  159. },
  160. {
  161. field: "description",
  162. label: "设备描述",
  163. class: "w-100",
  164. component: "I",
  165. type: "textarea",
  166. required: false
  167. }
  168. ] as any,
  169. modalTitle: "表计",
  170. resetForm: () => {
  171. form.value = emptyFormData.value
  172. },
  173. emptyFormData: {
  174. id: undefined,
  175. parentId: parentId.value,
  176. groupId: undefined,
  177. sn: undefined,
  178. name: undefined,
  179. type: 2,
  180. mode: undefined,
  181. reportConfig: [
  182. {
  183. host: "",
  184. protocol: "",
  185. st: "",
  186. mn: "",
  187. user: "",
  188. pwd: ""
  189. }
  190. ],
  191. protocol: undefined,
  192. address: undefined,
  193. bmYz: undefined,
  194. description: undefined
  195. }
  196. })
  197. const { queryParams, emptyFormData } = toRefs(opts)
  198. const form = ref<any>(Object.assign({}, emptyFormData.value))
  199. function handleCreate(parentId: number) {
  200. isAdd.value = true
  201. form.value.parentId = parentId
  202. form.value.reportConfig = [
  203. {
  204. host: "",
  205. protocol: "",
  206. st: "",
  207. mn: "",
  208. user: "",
  209. pwd: ""
  210. }
  211. ]
  212. modalRef.value.changePrefixTitle("添加")
  213. modalRef.value.show()
  214. }
  215. /** 修改按钮操作 */
  216. function handleUpdate(row: any) {
  217. isAdd.value = false
  218. tableRef.value.defaultHandleFuns.handleUpdate("", row)
  219. }
  220. /** 删除按钮操作 */
  221. function handleDelete(rows: any[]) {
  222. tableRef.value.defaultHandleFuns.handleDelete("", rows)
  223. }
  224. /** 提交按钮 */
  225. function submitForm() {
  226. if (form.value.id != undefined) {
  227. apis.iot.deviceApi.updateDevice(form.value).then(() => {
  228. message.msgSuccess("修改成功")
  229. handleQuery()
  230. })
  231. } else {
  232. apis.iot.deviceApi.addDevice(form.value).then(() => {
  233. message.msgSuccess("新增成功")
  234. handleQuery()
  235. })
  236. }
  237. }
  238. /** 查询按钮 */
  239. function handleQuery() {
  240. addDateRange(queryParams.value, queryParams.value.dateRange)
  241. tableRef.value?.search()
  242. }
  243. /** 查询重置按钮 */
  244. function resetQuery() {
  245. queryParams.value.dateRange = []
  246. addDateRange(queryParams.value, queryParams.value.dateRange)
  247. }
  248. function handelAddReportConfig() {
  249. form.value.reportConfig.push({
  250. host: "",
  251. protocol: "",
  252. st: "",
  253. mn: "",
  254. user: "",
  255. pwd: ""
  256. })
  257. }
  258. function handelRemoveReportConfig(index: number) {
  259. message.confirm("是否确认删除第" + (index + 1) + "条上报配置?", "删除配置").then(() => {
  260. form.value.reportConfig.splice(index, 1)
  261. })
  262. }
  263. function init() {
  264. apis.iot.deviceApi.getDeviceProtocols().then((res: any) => {
  265. protocolOptions.value = res.data.map((v: any) => {
  266. return {
  267. label: v,
  268. value: v
  269. }
  270. })
  271. })
  272. apis.iot.deviceApi.getReportProtocols().then((res: any) => {
  273. reportProtocolOptions.value = res.data.map((v: any) => {
  274. return {
  275. label: v,
  276. value: v
  277. }
  278. })
  279. })
  280. }
  281. function createMeter(id: number) {
  282. handleCreate(id)
  283. }
  284. onMounted(init)
  285. watch(
  286. () => props.id,
  287. (val: any) => {
  288. parentId.value = val
  289. queryParams.value.parentId = val
  290. handleQuery()
  291. }
  292. )
  293. defineExpose({
  294. createMeter
  295. })
  296. </script>
  297. <template>
  298. <div class="w-100 h-100">
  299. <VbDataTable
  300. ref="tableRef"
  301. style="height: 100%"
  302. :init-search="false"
  303. :show-right-toolbar="false"
  304. :show-search-bar="false"
  305. :show-toolbar="false"
  306. :page-size="5"
  307. :page-size-array="[5, 10, 25]"
  308. :handle-perm="opts.permission"
  309. :handle-funs="opts.handleFuns"
  310. :search-form-items="opts.searchFormItems"
  311. :columns="opts.columns"
  312. :custom-btns="opts.customBtns"
  313. :remote-fun="opts.tableListFun"
  314. :get-entity-fun="opts.getEntityFun"
  315. :delete-entity-fun="opts.deleteEntityFun"
  316. sortField="createdAt"
  317. sort-order="desc"
  318. :modal="modalRef"
  319. :reset-form-fun="opts.resetForm"
  320. v-model:form-data="form"
  321. :query-params="queryParams"
  322. :check-multiple="true"
  323. :has-checkbox="true"
  324. :reset-search-form-fun="resetQuery"
  325. :custom-search-fun="handleQuery">
  326. <template #groupId="{ row }">
  327. {{ row.group?.Name }}
  328. </template>
  329. <template #type="{ row }">
  330. <DictTag valueIsNumber :value="row.type" type="iot_device_type"></DictTag>
  331. </template>
  332. <template #mode="{ row }">
  333. <DictTag valueIsNumber :value="row.mode" type="iot_device_mode"></DictTag>
  334. </template>
  335. <template #createdAt="{ row }">
  336. <span>{{ dayjs(row.createdAt).format("YYYY-MM-DD HH:mm:ss") }}</span>
  337. </template>
  338. <template #actions="{ row }">
  339. <vb-tooltip content="修改" placement="top">
  340. <el-button
  341. link
  342. type="primary"
  343. @click="handleUpdate(row)"
  344. v-hasPermission="'iot:device:edit'">
  345. <template #icon>
  346. <VbIcon icon-name="notepad-edit" icon-type="duotone" class="fs-3"></VbIcon>
  347. </template>
  348. </el-button>
  349. </vb-tooltip>
  350. <vb-tooltip content="删除" placement="top">
  351. <el-button
  352. link
  353. type="primary"
  354. @click="handleDelete([row])"
  355. v-hasPermission="'iot:device:remove'">
  356. <template #icon>
  357. <VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
  358. </template>
  359. </el-button>
  360. </vb-tooltip>
  361. </template>
  362. </VbDataTable>
  363. <VbModal
  364. v-model:modal="modalRef"
  365. :title="opts.modalTitle"
  366. :form-items="opts.formItems as any"
  367. :form-data="form"
  368. @confirm="submitForm"
  369. append-to-body>
  370. <template #dsn_form="">
  371. <div
  372. class="w-100 px-5 mb-3"
  373. v-for="(item, index) in form.reportConfig"
  374. :key="index"
  375. style="border: 2px solid var(--bs-primary); border-radius: 10px">
  376. <div class="d-flex justify-content-between">
  377. <span class="text-danger fw-bold">配置 {{ index + 1 }}</span>
  378. <span>
  379. <vb-tooltip
  380. v-if="index === form.reportConfig.length - 1"
  381. type="primary"
  382. icon="ki-duotone ki-plus"
  383. content="添加上报配置"
  384. placement="top">
  385. <el-button link type="primary" @click="handelAddReportConfig()">
  386. <template #icon="">
  387. <VbIcon icon-name="plus-square" icon-type="duotone" class="fs-3"></VbIcon>
  388. </template>
  389. </el-button>
  390. </vb-tooltip>
  391. <vb-tooltip
  392. v-if="form.reportConfig.length > 1"
  393. content="删除上报配置"
  394. placement="top">
  395. <el-button link type="primary" @click="handelRemoveReportConfig(index)">
  396. <template #icon="">
  397. <VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
  398. </template>
  399. </el-button>
  400. </vb-tooltip>
  401. </span>
  402. </div>
  403. <el-row :gutter="10">
  404. <el-col :span="12">
  405. <el-form-item
  406. label="HOST"
  407. :prop="`reportConfig.${index}.host`"
  408. :rules="{ required: true, message: '请输入HOST(IP:端口)', trigger: 'blur' }">
  409. <el-input
  410. v-model="form.reportConfig[index].host"
  411. @change="console.log('change', form)"
  412. placeholder="请输入HOST(IP:端口)" />
  413. </el-form-item>
  414. </el-col>
  415. <el-col :span="12">
  416. <el-form-item
  417. label="协议"
  418. :prop="`reportConfig.${index}.protocol`"
  419. :rules="{ required: true, message: '请选择上报协议', trigger: 'blur' }">
  420. <el-select
  421. v-model="form.reportConfig[index].protocol"
  422. placeholder="请输入平台上报协议">
  423. <el-option
  424. v-for="(v, i) in reportProtocolOptions"
  425. :label="v.label"
  426. :value="v.value"
  427. :key="i"></el-option>
  428. </el-select>
  429. </el-form-item>
  430. </el-col>
  431. <el-col :span="12">
  432. <el-form-item
  433. label="指令(ST)"
  434. :prop="`reportConfig.${index}.st`"
  435. :rules="{ required: true, message: '请输入平台指令', trigger: 'blur' }">
  436. <el-input v-model="form.reportConfig[index].st" placeholder="请输入平台指令" />
  437. </el-form-item>
  438. </el-col>
  439. <el-col :span="12">
  440. <el-form-item
  441. label="编码(MN)"
  442. :prop="`reportConfig.${index}.mn`"
  443. :rules="{ required: true, message: '请输入表计编码', trigger: 'blur' }">
  444. <el-input v-model="form.reportConfig[index].mn" placeholder="请输入表计编码" />
  445. </el-form-item>
  446. </el-col>
  447. <el-col :span="12">
  448. <el-form-item label="用户" :prop="`reportConfig.${index}.user`">
  449. <el-input v-model="form.reportConfig[index].user" placeholder="请输入平台用户" />
  450. </el-form-item>
  451. </el-col>
  452. <el-col :span="12">
  453. <el-form-item label="密码" :prop="`reportConfig.${index}.pwd`">
  454. <el-input v-model="form.reportConfig[index].pwd" placeholder="请输入平台密码" />
  455. </el-form-item>
  456. </el-col>
  457. </el-row>
  458. </div>
  459. </template>
  460. </VbModal>
  461. </div>
  462. </template>