manage.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. <template>
  2. <StatisticsTemplate
  3. title="规则统计"
  4. :list="state.TaskCount"
  5. />
  6. <a-card style="margin-top: 20px;" >
  7. <a-row justify="space-between" >
  8. <a-col span="12" >
  9. <a-form layout="inline" >
  10. <a-form-item label="任务名称" >
  11. <a-input v-model:value="queryParamsState.taskLabel" placeholder="请输入任务名称"/>
  12. </a-form-item>
  13. <a-form-item label='任务状态' >
  14. <a-select
  15. style="width: 170px"
  16. v-model:value="queryParamsState.status"
  17. >
  18. <a-select-option
  19. v-for="item in statusList"
  20. :key="item.key"
  21. :value="item.key"
  22. >
  23. {{item.label}}
  24. </a-select-option>
  25. </a-select>
  26. </a-form-item >
  27. <a-form-item>
  28. <a-button type="primary" @click="getTaskPage">搜索</a-button>
  29. </a-form-item>
  30. </a-form>
  31. </a-col>
  32. <a-col span="12" >
  33. <a-row justify="end" >
  34. <a-col>
  35. <a-space>
  36. <a-button type="primary" @click="openModal('add')" >新增任务</a-button>
  37. </a-space>
  38. </a-col>
  39. </a-row>
  40. </a-col>
  41. </a-row>
  42. <a-table
  43. style="margin-top: 20px;"
  44. :columns="columns"
  45. :data-source="state.dataSource"
  46. :loading="state.loading"
  47. :pagination="queryParamsState"
  48. @change="changePage"
  49. >
  50. <template #bodyCell="{column, record}">
  51. <template v-if="column.key === 'id'" >
  52. <a @click="openModal('update', record.id)" >{{record.id}}</a>
  53. </template>
  54. <template v-if="column.key === 'status'" >
  55. <a-switch
  56. @click="changeStatus(record)"
  57. v-model:checked="record.status"
  58. checked-children="运行中"
  59. un-checked-children="已关闭"
  60. />
  61. </template>
  62. <template v-if="column.key === 'action'" >
  63. <a-space>
  64. <a @click="openModal('update', record.id)" >编辑</a>
  65. <a-popconfirm
  66. title="确实要删除吗?"
  67. ok-text="确定"
  68. cancel-text="取消"
  69. @confirm="delTask(record.id)"
  70. >
  71. <a>删除</a>
  72. </a-popconfirm>
  73. </a-space>
  74. </template>
  75. </template>
  76. </a-table>
  77. <modal-pro
  78. style="width: 1000px"
  79. :label="modalTitle"
  80. :visible="state.visible"
  81. destroyOnClose
  82. @cancel="state.visible = false"
  83. @ok="ok"
  84. >
  85. <a-form :label-col="{span: 4}" :wrapper-col="{span: 16}">
  86. <a-form-item label="任务名称" v-bind="validateInfos.taskLabel">
  87. <a-input v-model:value="modalRef.taskLabel" />
  88. </a-form-item>
  89. <a-form-item label="任务描述" v-bind="validateInfos.taskDescription">
  90. <a-input v-model:value="modalRef.taskDescription" />
  91. </a-form-item>
  92. <a-form-item label="cron表达式" v-bind="validateInfos.cornDescr">
  93. <cron-ant
  94. locale="zh"
  95. v-model="modalRef.cornDescr"
  96. :button-props="{ type: 'primary', shape: 'round'}"
  97. />
  98. </a-form-item>
  99. <a-form-item label="选择产品" v-bind="validateInfos.modelId">
  100. <a-select
  101. placeholder="请选择产品"
  102. v-model:value="modalRef.taskConfig.modelId"
  103. >
  104. <a-select-option
  105. v-for="model in state.modelList"
  106. :key="model.id"
  107. :value="model.id"
  108. >
  109. {{model.modelLabel}}
  110. </a-select-option>
  111. </a-select>
  112. </a-form-item>
  113. <a-form-item label="选择设备" v-bind="validateInfos.deviceId">
  114. <a-select
  115. placeholder="请选择产品"
  116. v-model:value="modalRef.taskConfig.deviceId"
  117. >
  118. <a-select-option
  119. v-for="device in state.deviceList"
  120. :key="device.id"
  121. :value="device.id"
  122. >
  123. {{device.deviceLabel}}
  124. </a-select-option>
  125. </a-select>
  126. </a-form-item>
  127. <a-form-item label="任务类型" v-bind="validateInfos.taskType">
  128. <a-select v-model:value="modalRef.taskConfig.taskType" >
  129. <a-select-option
  130. :value="item"
  131. v-for="item in TaskController.taskTypeList"
  132. :key="item"
  133. >
  134. {{TaskController.taskTypeMap.get(item)?.label }}
  135. </a-select-option>
  136. </a-select>
  137. </a-form-item>
  138. <span v-if="modalRef.taskConfig.taskType === 'DEVICE_CMD'" >
  139. <a-form-item label="选择命令" >
  140. <a-select
  141. style="width: 170px;"
  142. v-model:value="modalRef.taskConfig.cmdId"
  143. >
  144. <a-select-option
  145. v-for="cmdItem in state.cmdList"
  146. :key="cmdItem.id"
  147. :value="cmdItem.id"
  148. >
  149. {{cmdItem.cmdLabel}}
  150. </a-select-option>
  151. </a-select>
  152. </a-form-item>
  153. <a-form-item label="命令参数" >
  154. <div
  155. v-for="(item, index) in modalRef.taskConfig.cmdParameters"
  156. :key="index"
  157. style="margin-bottom: 10px;"
  158. >
  159. <a-input-group compact >
  160. <a-input placeholder="key" disabled v-model:value="item.paramLabel" style="width: 50%" />
  161. <a-input placeholder="value" v-model:value="item.dataUnit" style="width: 50%" />
  162. </a-input-group>
  163. </div>
  164. </a-form-item>
  165. </span>
  166. <span v-if="modalRef.taskConfig.taskType === 'DEVICE_MSG'" >
  167. <a-form-item label="主题" >
  168. <a-input v-model:value="modalRef.taskConfig.topic" />
  169. </a-form-item>
  170. <a-form-item label="消息名称" >
  171. <a-input v-model:value="modalRef.taskConfig.msgLabel" />
  172. </a-form-item>
  173. <a-form-item label="消息内容" >
  174. <a-textarea :auto-size="{ minRows: 2, maxRows: 5 }" v-model:value="modalRef.taskConfig.msgPayload" />
  175. </a-form-item>
  176. </span>
  177. <!-- @error="error=$event" -->
  178. </a-form>
  179. </modal-pro>
  180. </a-card>
  181. <modal-pro
  182. style="width: 700px;overflow: hidden;"
  183. label="选择设备"
  184. :visible="state.deviceModalVisible"
  185. @cancel="state.deviceModalVisible = false"
  186. @ok="selectDevice"
  187. >
  188. <SelectDevice
  189. ref="selectDeviceRef"
  190. />
  191. </modal-pro>
  192. </template>
  193. <script lang='ts' setup >
  194. import { TaskController } from '@/controller/iot/task'
  195. import { computed, onMounted, reactive, ref, toRefs, watch } from 'vue'
  196. import { Form } from 'ant-design-vue'
  197. import { DeviceContriller, ModelAttrController, ModelCmdController, ModelController } from '@/controller'
  198. import SelectDevice from '@/pages/iot/rule/components/selectDevice.vue'
  199. import StatisticsTemplate from '@/components/StatisticsTemplate/index.vue'
  200. const columns = [
  201. {
  202. title: 'id',
  203. dataIndex: 'id',
  204. key: 'id'
  205. },
  206. {
  207. title: '任务名称',
  208. dataIndex: 'taskLabel',
  209. key: 'taskLabel'
  210. },
  211. {
  212. title: '任务描述',
  213. dataIndex: 'taskDescription',
  214. key: 'taskDescription'
  215. },
  216. {
  217. title: 'corn',
  218. dataIndex: 'cornDescr',
  219. key: 'cornDescr'
  220. },
  221. {
  222. title: '任务状态',
  223. dataIndex: 'status',
  224. key: 'status'
  225. },
  226. {
  227. title: '操作',
  228. dataIndex: 'action',
  229. key: 'action'
  230. }
  231. ]
  232. const useForm = Form.useForm
  233. const statusList = [
  234. { key: true, label: '开启' },
  235. { key: false, label: '关闭' },
  236. { key: true, label: '' }
  237. ]
  238. const queryParamsState = reactive({
  239. page: 1,
  240. pageSize: 10,
  241. total: 0,
  242. taskLabel: '',
  243. status: ''
  244. })
  245. const modalTitle = computed(() => state.opraState === 'add' ? '新增任务' : '编辑任务')
  246. const state = reactive({
  247. dataSource: [],
  248. loading: false,
  249. opraState: 'add',
  250. visible: false,
  251. modelList: [],
  252. cmdList: [],
  253. attrList: [],
  254. deviceList: [],
  255. deviceModalVisible: false,
  256. taskId: '',
  257. TaskCount: []
  258. })
  259. const modalRef = reactive({
  260. taskLabel: '',
  261. taskDescription: '',
  262. cornDescr: '',
  263. taskConfig: {
  264. taskType: '',
  265. deviceId: '',
  266. deviceLabel: '',
  267. modelId: '',
  268. cmdLabel: '',
  269. cmdParameters: [],
  270. cmdId: '',
  271. msgLabel: '',
  272. msgPayload: '',
  273. topic: ''
  274. }
  275. })
  276. const selectDeviceRef = ref('')
  277. watch(
  278. () => modalRef.taskConfig.modelId,
  279. () => {
  280. getCmdList()
  281. getAttrList()
  282. }
  283. )
  284. watch(
  285. () => modalRef.taskConfig.cmdId,
  286. () => {
  287. if (modalRef.taskConfig.taskType === 'DEVICE_CMD') {
  288. const cmdDetail = state.cmdList.find(item => item.id === modalRef.taskConfig.cmdId)!
  289. console.log('cmdDetail:', state.cmdList, cmdDetail)
  290. if (cmdDetail && cmdDetail.cmdParams) {
  291. modalRef.taskConfig.cmdParameters = cmdDetail.cmdParams
  292. modalRef.taskConfig.cmdLabel = cmdDetail.cmdLabel
  293. }
  294. }
  295. }
  296. )
  297. const { resetFields, validate, validateInfos } = useForm(modalRef, reactive({
  298. taskLabel: [{ required: true, message: '请填写任务名称' }],
  299. taskDescription: [{ required: true, message: '请填写任务描述' }],
  300. cornDescr: [{ required: true, message: '请填写corn表达式' }],
  301. taskType: [{ required: true, message: '请选择任务类型' }],
  302. modelId: [{ required: true, message: '请选择产品' }],
  303. deviceId: [{ required: true, message: '请选择设备' }]
  304. }))
  305. const changeStatus = async (record) => TaskController.updateStatus(record.id, record.status)
  306. // 选择设备
  307. const selectDevice = () => {
  308. const _device = selectDeviceRef.value.getSelectDevice()
  309. modalRef.taskConfig.deviceId = _device.id
  310. modalRef.taskConfig.deviceLabel = _device.deviceLabel
  311. state.deviceModalVisible = false
  312. }
  313. const ok = () => {
  314. validate().then(async () => {
  315. const obj = {}
  316. if (modalRef.taskConfig.taskType === 'DEVICE_CMD') {
  317. modalRef.taskConfig.cmdParameters.forEach(item => {
  318. obj[item.paramLabel] = item.dataUnit
  319. })
  320. modalRef.taskConfig.cmdParameters = obj
  321. }
  322. console.log(modalRef)
  323. if (state.opraState === 'add') {
  324. await TaskController.add(modalRef)
  325. } else {
  326. await TaskController.update({ ...modalRef, id: state.taskId })
  327. }
  328. state.visible = false
  329. getTaskPage()
  330. })
  331. }
  332. const delTask = (id: string) => TaskController.del(id)
  333. const openModal = (opraState: 'add' | 'update', id = '') => {
  334. resetFields()
  335. state.opraState = opraState
  336. state.visible = true
  337. state.taskId = id
  338. if (opraState === 'update') {
  339. getTaskById(id)
  340. }
  341. }
  342. const getCmdList = async () => {
  343. const { data } = await ModelCmdController.list({ modelId: modalRef.taskConfig.modelId })
  344. state.cmdList = data
  345. }
  346. // 获取属性
  347. const getAttrList = async () => {
  348. const { data } = await ModelAttrController.list({ modelId: modalRef.taskConfig.modelId })
  349. state.attrList = data
  350. }
  351. const getModelList = async () => {
  352. const { data } = await ModelController.list()
  353. state.modelList = data
  354. }
  355. const getDeviceList = async () => {
  356. const { data } = await DeviceContriller.list()
  357. state.deviceList = data
  358. }
  359. const getStatistics = async () => {
  360. const { data } = await TaskController.statistics()
  361. state.TaskCount = Object.keys(data).map(key => {
  362. const item = TaskController.taskStatisticsMap.get(key)
  363. return {
  364. ...item,
  365. value: data[key]
  366. }
  367. })
  368. console.log('11', state.TaskCount)
  369. }
  370. const getTaskById = async (id: string) => {
  371. const { data } = await TaskController.byId(id)
  372. console.log('getTaskById:', data)
  373. if (data.taskConfig.taskType === 'DEVICE_CMD') {
  374. const cmdParameters = Object.keys(data.taskConfig.cmdParameters).map(key => {
  375. return { key, value: data.taskConfig.cmdParameters[key] }
  376. })
  377. data.taskConfig.cmdParameters = cmdParameters
  378. }
  379. resetFields(data)
  380. }
  381. const getTaskPage = async () => {
  382. state.loading = true
  383. const { data, sum } = await TaskController.page(queryParamsState)
  384. state.loading = false
  385. state.dataSource = data
  386. queryParamsState.total = sum
  387. }
  388. const changePage = ({ current }) => {
  389. queryParamsState.page = current
  390. getTaskPage()
  391. }
  392. onMounted(() => {
  393. getTaskPage()
  394. getModelList()
  395. getDeviceList()
  396. getStatistics()
  397. })
  398. </script>
  399. <style lang='less' scoped >
  400. </style>