index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <template>
  2. <div class="mainContentBox">
  3. <avue-crud
  4. ref="crudRef"
  5. v-model:search="search"
  6. v-model="form"
  7. :data="data"
  8. :option="option"
  9. v-model:page="page"
  10. @row-save="createRow"
  11. @row-update="updateRow"
  12. @row-del="deleteRow"
  13. :permission="permission"
  14. @search-change="searchChange"
  15. @search-reset="resetChange"
  16. @size-change="dataList"
  17. @current-change="dataList"
  18. @selection-change="selectionChange"
  19. >
  20. <!-- <template #collect="scope">
  21. <el-switch
  22. active-value="1"
  23. inactive-value="0"
  24. inline-prompt
  25. active-text="是"
  26. inactive-text="否"
  27. v-model="scope.row.collect"
  28. @click="changeItem($event,scope.row)"
  29. class="ml-2"
  30. style="&#45;&#45;el-switch-on-color: #13ce66; &#45;&#45;el-switch-off-color: #ff4949"
  31. />
  32. </template>-->
  33. <template #menu="{ size, row, index }">
  34. <el-button
  35. v-hasPerm="[buttonPermission.DEVICE.BTNS.instance_edit]"
  36. type="primary"
  37. link
  38. size="small"
  39. @click="showParamsPage(row)"
  40. >模型
  41. <template #icon>
  42. <svg-icon icon-class="moxing" />
  43. </template>
  44. </el-button>
  45. </template>
  46. <template #menu-left="{ size }">
  47. <el-button
  48. :disabled="toDeleteIds.length < 1"
  49. type="danger"
  50. icon="el-icon-delete"
  51. :size="size"
  52. v-hasPerm="[buttonPermission.DEVICE.BTNS.instance_del]"
  53. @click="multipleDelete"
  54. >删除</el-button
  55. >
  56. <!-- <el-button
  57. :disabled="toDeleteIds.length < 1"
  58. type="refresh"
  59. icon="el-icon-refresh"
  60. :size="size"
  61. @click="apsSync"
  62. >APS同步</el-button
  63. >-->
  64. </template>
  65. <template #menu-right="{}">
  66. <el-dropdown split-button
  67. >导入
  68. <template #dropdown>
  69. <el-dropdown-menu>
  70. <el-dropdown-item
  71. @click="downloadTemplate('/api/v1/device/template')"
  72. >
  73. <i-ep-download />下载模板
  74. </el-dropdown-item>
  75. <el-dropdown-item @click="importExcelData">
  76. <i-ep-top />导入数据
  77. </el-dropdown-item>
  78. </el-dropdown-menu>
  79. </template>
  80. </el-dropdown>
  81. <el-button class="ml-3" @click="exportData('/api/v1/device/export')">
  82. <template #icon> <i-ep-download /> </template>导出
  83. </el-button>
  84. </template>
  85. </avue-crud>
  86. <el-dialog
  87. v-model="dialog.visible"
  88. :title="dialog.title"
  89. width="30%"
  90. @close="dialog.visible = false"
  91. >
  92. <el-button
  93. type="primary"
  94. @click="addItem"
  95. icon="el-icon-plus"
  96. style="margin-left: 15px; width: 25px; height: 25px"
  97. circle
  98. />
  99. <el-table
  100. v-loading="loading"
  101. ref="ruleListRef"
  102. :data="pageData"
  103. style="height: 280px"
  104. >
  105. <el-table-column label="参数" prop="fieldCode">
  106. <template #default="{ row }">
  107. <el-input v-model="row.fieldCode" />
  108. </template>
  109. </el-table-column>
  110. <el-table-column label="参数名称" prop="fieldLabel">
  111. <template #default="{ row }">
  112. <el-input v-model="row.fieldLabel" />
  113. </template>
  114. </el-table-column>
  115. <el-table-column label="参数值" prop="fieldValue">
  116. <template #default="{ row }">
  117. <el-input v-model="row.fieldValue" />
  118. </template>
  119. </el-table-column>
  120. <el-table-column label="操作" align="center">
  121. <template #default="{ row }">
  122. <el-button
  123. type="danger"
  124. @click="minusItem(row)"
  125. icon="el-icon-minus"
  126. style="margin-left: 15px; width: 25px; height: 25px"
  127. circle
  128. />
  129. </template>
  130. </el-table-column>
  131. </el-table>
  132. <div class="dialog-footer" style="margin-top: 20px" align="center">
  133. <el-button type="primary" @click="handleSubmit">保 存</el-button>
  134. <el-button @click="dialog.visible = false">取消</el-button>
  135. </div>
  136. </el-dialog>
  137. <el-dialog
  138. v-model="dialog2.visible"
  139. :title="dialog2.title"
  140. width="70%"
  141. @close="dialog2.visible = false"
  142. >
  143. <choice-workshop-page @work-shop-info="workShopInfo" />
  144. </el-dialog>
  145. <el-dialog
  146. v-model="dialog3.visible"
  147. :title="dialog3.title"
  148. width="70%"
  149. @close="dialog3.visible = false"
  150. >
  151. <choice-station-page @station-info="stationInfo" />
  152. </el-dialog>
  153. <ExcelUpload ref="uploadRef" @finished="uploadFinished" />
  154. </div>
  155. <CommonTable
  156. ref="ctableRef"
  157. tableTitle="负责人选择"
  158. tableType="USERS"
  159. @selected-sure="onSelectedFinish"
  160. />
  161. </template>
  162. <script setup>
  163. import { ref, getCurrentInstance } from "vue";
  164. import { useCrud } from "@/hooks/userCrud";
  165. import buttonPermission from "@/common/configs/buttonPermission";
  166. import { configSave, configList, deviceUpdateCollect } from "@/api/device";
  167. import { syncAps } from "@/api/aps";
  168. import { useCommonStoreHook,useDictionaryStore } from "@/store";
  169. import ChoiceWorkshopPage from "../../plan/workOrder/components/choice-workshop-page.vue";
  170. import ChoiceStationPage from "./components/choice-station-page.vue";
  171. import dictDataUtil from "@/common/configs/dictDataUtil";
  172. import { checkPerm } from "@/directive/permission";
  173. import { ElMessage, ElMessageBox } from "element-plus";
  174. const { isShowTable, tableType } = toRefs(useCommonStoreHook());
  175. const test = () => {
  176. isShowTable.value = true;
  177. tableType.value = tableType.value == 1 ? 2 : 1;
  178. };
  179. const { dicts } = useDictionaryStore();
  180. const pageData = ref([]);
  181. const loading = ref(false); // 加载状态
  182. const addItem = () => {
  183. pageData.value.push({
  184. deviceType: clickRow.value.deviceType,
  185. deviceNo: clickRow.value.deviceNo,
  186. type: 1,
  187. });
  188. };
  189. const permission = reactive({
  190. delBtn: checkPerm(buttonPermission.DEVICE.BTNS.instance_del),
  191. addBtn: checkPerm(buttonPermission.DEVICE.BTNS.instance_add),
  192. editBtn: checkPerm(buttonPermission.DEVICE.BTNS.instance_edit),
  193. menu: true,
  194. });
  195. const minusItem = (row) => {
  196. pageData.value = pageData.value.filter(
  197. (item) => item.fieldCode !== row.fieldCode
  198. );
  199. };
  200. const changeItem = (obj, row) => {
  201. deviceUpdateCollect({
  202. id: row.id,
  203. collect: row.collect,
  204. deviceNo: row.deviceNo,
  205. }).then((data) => {
  206. if (data.code === "200") {
  207. ElMessage.success(data.msg);
  208. } else {
  209. ElMessage.error(data.msg);
  210. }
  211. });
  212. };
  213. const apsSync = () => {
  214. ElMessageBox.confirm("是否同步所选中数据?", "提示", {
  215. confirmButtonText: "确定",
  216. cancelButtonText: "取消",
  217. type: "warning",
  218. }).then(async () => {
  219. let param = { type: 1, codes: toDeleteIds.value };
  220. syncAps(param).then((data) => {
  221. if (data.code === "200") {
  222. ElMessage.success(data.msg);
  223. } else {
  224. ElMessage.error(data.msg);
  225. }
  226. });
  227. });
  228. };
  229. const clickRow = ref(null);
  230. const showParamsPage = (row) => {
  231. clickRow.value = row;
  232. configList({ deviceNo: row.deviceNo }).then((data) => {
  233. pageData.value = data.data;
  234. dialog.visible = true;
  235. });
  236. };
  237. const dialog = reactive({
  238. title: "模型设置",
  239. visible: false,
  240. });
  241. const handleSubmit = () => {
  242. //判断参数
  243. let errorData = pageData.value.filter((item) => !item.fieldCode);
  244. if (errorData.length > 0) {
  245. ElMessage.warning("请填写参数");
  246. return;
  247. }
  248. errorData = pageData.value.filter((item) => !item.fieldLabel);
  249. if (errorData.length > 0) {
  250. ElMessage.warning("请填写参数名");
  251. return;
  252. }
  253. errorData = pageData.value.filter((item) => !item.fieldValue);
  254. if (errorData.length > 0) {
  255. ElMessage.warning("请填写参数值");
  256. return;
  257. }
  258. configSave(pageData.value).then((data) => {
  259. if (data.code === "200") {
  260. ElMessage.success(data.msg);
  261. } else {
  262. ElMessage.error(data.msg);
  263. }
  264. });
  265. };
  266. // 传入一个url,后面不带/
  267. const { form, data, option, search, page, toDeleteIds, Methords, Utils } =
  268. useCrud({
  269. src: "/api/v1/device",
  270. });
  271. const { dataList, createRow, updateRow, deleteRow, searchChange, resetChange } =
  272. Methords; //增删改查
  273. const { selectionChange, multipleDelete } = Methords; //选中和批量删除事件
  274. const { checkBtnPerm, downloadTemplate, exportData } = Utils; //按钮权限等工具
  275. const crudRef = ref(null); //crudRef.value 获取avue-crud对象
  276. const workShopInfo = (value) => {
  277. form.value.workshop = value.name;
  278. dialog2.visible = false;
  279. };
  280. const ctableRef = ref(null);
  281. const onSelectedFinish = (selectedValue) => {
  282. form.value.head = selectedValue.userName;
  283. };
  284. const stationInfo = (value) => {
  285. form.value.station = value.name;
  286. dialog3.visible = false;
  287. };
  288. const dialog2 = reactive({
  289. title: "车间选择",
  290. visible: false,
  291. });
  292. const dialog3 = reactive({
  293. title: "工位选择",
  294. visible: false,
  295. });
  296. // 设置表格列或者其他自定义的option
  297. option.value = Object.assign(option.value, {
  298. delBtn: false,
  299. selection: true,
  300. labelWidth: 120,
  301. column: [
  302. {
  303. label: "设备编号",
  304. prop: "deviceNo",
  305. search: true,
  306. editDisabled: true,
  307. width: 160,
  308. overHidden: true,
  309. rules: [
  310. {
  311. required: true,
  312. message: "设备编号不能为空",
  313. trigger: "trigger",
  314. },
  315. ],
  316. },
  317. {
  318. label: "设备名称",
  319. prop: "deviceName",
  320. search: true,
  321. width: 160,
  322. overHidden: true,
  323. rules: [
  324. {
  325. required: true,
  326. message: "设备名称不能为空",
  327. trigger: "trigger",
  328. },
  329. ],
  330. },
  331. {
  332. label: "设备类型",
  333. prop: "deviceType",
  334. type: "select",
  335. width: 130,
  336. overHidden: true,
  337. search: true,
  338. dicUrl: dictDataUtil.request_url + dictDataUtil.TYPE_CODE.device_type,
  339. props: {
  340. label: "dictLabel",
  341. value: "dictValue",
  342. },
  343. rules: [
  344. {
  345. required: true,
  346. message: "设备类型不能为空",
  347. trigger: "trigger",
  348. },
  349. ],
  350. },
  351. {
  352. label: "设备状态",
  353. prop: "state",
  354. type: "select",
  355. width: 120,
  356. overHidden: true,
  357. search: true,
  358. dicUrl: dictDataUtil.request_url + dictDataUtil.TYPE_CODE.device_status,
  359. props: {
  360. label: "dictLabel",
  361. value: "dictValue",
  362. },
  363. rules: [
  364. {
  365. required: true,
  366. message: "设备状态不能为空",
  367. trigger: "trigger",
  368. },
  369. ],
  370. },
  371. {
  372. label: "在线状态",
  373. prop: "onlineState",
  374. width: 100,
  375. display: false,
  376. html: true,
  377. formatter: (val) => {
  378. if (val.onlineState === "1") {
  379. return '<b class="el-tag el-tag--success el-tag--light">在线</b>';
  380. } else {
  381. return '<b class="el-tag el-tag--warning el-tag--light">离线</b>';
  382. }
  383. },
  384. },
  385. /*{
  386. label: "连接状态",
  387. prop: "collectState",
  388. width: 100,
  389. display: false,
  390. html: true,
  391. formatter: (val) => {
  392. if (val.onlineState === "1") {
  393. return '<b class="el-tag el-tag--success el-tag--light">已连接</b>';
  394. } else {
  395. return '<b class="el-tag el-tag--warning el-tag--light">未连接</b>';
  396. }
  397. },
  398. },*/
  399. {
  400. label: "负责人",
  401. prop: "head",
  402. width: 120,
  403. overHidden: true,
  404. type: "select",
  405. dicData: dicts.user_name_list,
  406. props: {"label": "dictLabel","value":"dictValue"},
  407. rules: [
  408. {
  409. required: true,
  410. message: "负责人不能为空",
  411. trigger: "trigger",
  412. },
  413. ],
  414. click: ({ value, column }) => {
  415. ctableRef.value.startSelect();
  416. },
  417. },
  418. {
  419. label: "计量有效期",
  420. prop: "meteringDate",
  421. type: "date",
  422. width: 160,
  423. format: "YYYY-MM-DD",
  424. valueFormat: "YYYY-MM-DD",
  425. overHidden: true,
  426. rules: [
  427. {
  428. required: true,
  429. message: "计量有效期不能为空",
  430. trigger: "trigger",
  431. },
  432. ],
  433. },
  434. {
  435. label: "所属PAC",
  436. prop: "terminal",
  437. type: "select",
  438. width: 120,
  439. overHidden: true,
  440. search: true,
  441. dicUrl: import.meta.env.VITE_APP_BASE_API + "/api/v1/device/pacList",
  442. props: {
  443. label: "deviceName",
  444. value: "deviceNo",
  445. },
  446. },
  447. /*{
  448. label: "是否采集",
  449. prop: "collect",
  450. editDisplay: false,
  451. addDisplay: false,
  452. slot: true,
  453. width: 100,
  454. },*/
  455. {
  456. label: "供应厂商",
  457. prop: "manufacturer",
  458. width: 160,
  459. overHidden: true,
  460. },
  461. {
  462. label: "所属部门",
  463. prop: "deptId",
  464. width: 160,
  465. overHidden: true,
  466. type: "tree",
  467. dicUrl: dictDataUtil.dept_tree_url,
  468. props: {
  469. label: "deptName",
  470. value: "id",
  471. },
  472. },
  473. /*{
  474. label: "所在车间",
  475. prop: "workshop",
  476. width: 160,
  477. overHidden: true,
  478. click: ({ value, column }) => {
  479. if (column.boxType) {
  480. dialog2.visible = true;
  481. }
  482. },
  483. },
  484. {
  485. label: "所在工位",
  486. prop: "station",
  487. width: 160,
  488. overHidden: true,
  489. click: ({ value, column }) => {
  490. if (column.boxType) {
  491. /!*if(!form.value.workshop){
  492. ElMessage({
  493. message: "请先选择车间",
  494. type: "warning",
  495. });
  496. return;
  497. }*!/
  498. dialog3.visible = true;
  499. }
  500. },
  501. },*/
  502. {
  503. label: "设备位置",
  504. prop: "devicePosition",
  505. width: 160,
  506. overHidden: true,
  507. },
  508. {
  509. label: "规格",
  510. prop: "specifications",
  511. width: 160,
  512. overHidden: true,
  513. },
  514. {
  515. label: "品牌",
  516. width: 160,
  517. overHidden: true,
  518. prop: "brand",
  519. },
  520. ],
  521. });
  522. onMounted(() => {
  523. dataList();
  524. });
  525. /**
  526. * 上传excel相关
  527. */
  528. const uploadRef = ref(null);
  529. const uploadFinished = () => {
  530. // 上传完成后的刷新操作
  531. page.currentPage = 1;
  532. dataList();
  533. };
  534. const importExcelData = () => {
  535. if (uploadRef.value) {
  536. uploadRef.value.show("/api/v1/device/import");
  537. }
  538. };
  539. </script>