index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. <template>
  2. <!-- 筛选条件 -->
  3. <div class="app-container">
  4. <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
  5. <el-form-item label="设备名" prop="equipmentName">
  6. <el-input v-model="queryParams.equipmentName" placeholder="请输入设备名" clearable @keyup.enter="handleQuery" />
  7. </el-form-item>
  8. <el-form-item label="标识码" prop="code">
  9. <el-input v-model="queryParams.code" placeholder="请输入标识码" clearable @keyup.enter="handleQuery" />
  10. </el-form-item>
  11. <el-form-item label="设备种类" prop="equipmentType">
  12. <el-select v-model="queryParams.equipmentType" placeholder="请选择设备种类" clearable style="width: 150px;">
  13. <el-option v-for="dict in equipment_type" :key="dict.value" :label="dict.label" :value="dict.value" />
  14. </el-select>
  15. </el-form-item>
  16. <el-form-item label="PLC选择" prop="plcId">
  17. <el-select v-model="queryParams.plcId" placeholder="请选择PLC" clearable style="width: 150px;">
  18. <el-option v-for="dict in plcOptions" :key="dict.plcId" :label="dict.plcName" :value="dict.plcId" />
  19. </el-select>
  20. </el-form-item>
  21. <el-form-item label="通讯协议" prop="protocolId">
  22. <el-select v-model="queryParams.protocolId" placeholder="请选择通讯协议" clearable style="width: 150px;">
  23. <el-option v-for="dict in commProtocolOptions" :key="dict.protocolId" :label="dict.protocolName"
  24. :value="dict.protocolId" />
  25. </el-select>
  26. </el-form-item>
  27. <el-form-item label="流程选择" prop="flowIds">
  28. <el-select v-model="queryParams.flowIds" placeholder="请选择对应流程" clearable style="width: 150px;">
  29. <el-option v-for="dict in flowOptions" :key="dict.flowId" :label="dict.flowName" :value="dict.flowId" />
  30. </el-select>
  31. </el-form-item>
  32. <el-form-item label="页面选择" prop="pageIds">
  33. <el-select v-model="queryParams.pageIds" placeholder="请选择对应页面" clearable style="width: 150px;">
  34. <el-option v-for="dict in pageOptions" :key="dict.pageId" :label="dict.pageName" :value="dict.pageId" />
  35. </el-select>
  36. </el-form-item>
  37. <el-form-item label="状态" prop="status">
  38. <el-select v-model="queryParams.status" placeholder="状态" clearable style="width: 150px">
  39. <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
  40. </el-select>
  41. </el-form-item>
  42. <el-form-item>
  43. <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
  44. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  45. </el-form-item>
  46. </el-form>
  47. <el-row :gutter="10" class="mb8">
  48. <el-col :span="1.5">
  49. <el-button type="primary" plain icon="Plus" @click="handleAdd"
  50. v-hasPermi="['hnyz:equipment:add']">新增</el-button>
  51. </el-col>
  52. <el-col :span="1.5">
  53. <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
  54. v-hasPermi="['hnyz:equipment:edit']">修改</el-button>
  55. </el-col>
  56. <el-col :span="1.5">
  57. <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
  58. v-hasPermi="['hnyz:equipment:remove']">删除</el-button>
  59. </el-col>
  60. <el-col :span="1.5">
  61. <el-button type="warning" plain icon="Download" @click="handleExport"
  62. v-hasPermi="['hnyz:equipment:export']">导出</el-button>
  63. </el-col>
  64. <el-col :span="1.5">
  65. <el-button type="info" plain icon="Upload" @click="handleImport" v-hasPermi="['system:user:import']">导入</el-button>
  66. </el-col>
  67. <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
  68. </el-row>
  69. <!-- 表单列表 -->
  70. <el-table v-loading="loading" :data="equipmentList" @selection-change="handleSelectionChange">
  71. <el-table-column type="selection" width="55" align="center" />
  72. <!-- <el-table-column label="设备id" align="center" prop="equipmentId" /> -->
  73. <el-table-column label="设备名" align="center" prop="equipmentName" />
  74. <el-table-column label="标题" align="center" prop="title" />
  75. <!-- <el-table-column label="流程归属" align="center" prop="flowName" :show-overflow-tooltip="true" /> -->
  76. <el-table-column label="页面归属" align="center" prop="pageName" :show-overflow-tooltip="true" />
  77. <el-table-column label="标识码" align="center" prop="code" />
  78. <el-table-column label="设备种类" align="center" prop="equipmentType">
  79. <template #default="scope">
  80. <dict-tag :options="equipment_type" :value="scope.row.equipmentType" />
  81. </template>
  82. </el-table-column>
  83. <!-- <el-table-column label="plc名称" align="center" prop="plcName" />
  84. <el-table-column label="通讯协议" align="center" prop="protocolName" /> -->
  85. <el-table-column label="启用状态" align="center" width="100">
  86. <template #default="scope">
  87. <el-switch v-model="scope.row.status" active-value="0" inactive-value="1"
  88. @change="handleStatusChange(scope.row)"></el-switch>
  89. </template>
  90. </el-table-column>
  91. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  92. <template #default="scope">
  93. <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
  94. v-hasPermi="['hnyz:equipment:edit']">修改</el-button>
  95. <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
  96. v-hasPermi="['hnyz:equipment:remove']">删除</el-button>
  97. <el-button link type="primary" icon="View" @click="toDetail(scope.row.code)">
  98. 详情
  99. </el-button>
  100. </template>
  101. </el-table-column>
  102. </el-table>
  103. <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
  104. v-model:limit="queryParams.pageSize" @pagination="getList" />
  105. <!-- 添加或修改设备管理对话框 -->
  106. <el-dialog :title="title" v-model="open" width="500px" append-to-body>
  107. <el-form ref="equipmentRef" :model="form" :rules="rules" label-width="80px">
  108. <el-form-item label="设备名" prop="equipmentName">
  109. <el-input v-model="form.equipmentName" placeholder="请输入设备名" />
  110. </el-form-item>
  111. <el-form-item label="标题名" prop="title">
  112. <el-input v-model="form.title" placeholder="请输入标题名" />
  113. </el-form-item>
  114. <el-form-item label="标识码" prop="code">
  115. <el-input v-model="form.code" placeholder="请输入标识码" />
  116. </el-form-item>
  117. <el-form-item label="设备种类" prop="equipmentType">
  118. <el-select v-model="form.equipmentType" placeholder="请选择设备种类" clearable>
  119. <el-option v-for="dict in equipment_type" :key="dict.value" :label="dict.label"
  120. :value="dict.value"></el-option>
  121. </el-select>
  122. </el-form-item>
  123. <el-form-item label="流程分配" prop="flowIds">
  124. <el-select v-model="form.flowIds" multiple placeholder="请选择对应流程" clearable>
  125. <el-option v-for="dict in flowOptions" :key="dict.flowId" :label="dict.flowName"
  126. :value="dict.flowId"></el-option>
  127. </el-select>
  128. </el-form-item>
  129. <el-form-item label="页面分配" prop="pageIds">
  130. <el-select v-model="form.pageIds" multiple placeholder="请选择对应页面" clearable>
  131. <el-option v-for="dict in pageOptions" :key="dict.pageId" :label="dict.pageName"
  132. :value="dict.pageId"></el-option>
  133. </el-select>
  134. </el-form-item>
  135. <el-form-item label="PLC" prop="plcId">
  136. <el-select v-model="form.plcId" placeholder="请选择plc" clearable>
  137. <el-option v-for="dict in plcOptions" :key="dict.plcId" :label="dict.plcName"
  138. :value="dict.plcId"></el-option>
  139. </el-select>
  140. </el-form-item>
  141. <el-form-item label="通讯协议" prop="protocolId">
  142. <el-select v-model="form.protocolId" placeholder="请选择通讯协议" clearable :disabled="form.plcId != null">
  143. <el-option v-for="dict in commProtocolOptions" :key="dict.protocolId" :label="dict.protocolName"
  144. :value="dict.protocolId"></el-option>
  145. </el-select>
  146. </el-form-item>
  147. <el-form-item label="通信地址" prop="ipAddress">
  148. <el-input v-model="form.ipAddress" placeholder="请输入通信地址" :disabled="form.plcId != null" />
  149. </el-form-item>
  150. <el-form-item label="通信端口" prop="port">
  151. <el-input v-model="form.port" placeholder="请输入通信端口" :disabled="form.plcId != null" />
  152. </el-form-item>
  153. <el-form-item label="备注" prop="remark">
  154. <el-input v-model="form.remark" placeholder="请输入备注" />
  155. </el-form-item>
  156. <el-form-item label="启用状态">
  157. <el-radio-group v-model="form.status">
  158. <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label
  159. }}</el-radio>
  160. </el-radio-group>
  161. </el-form-item>
  162. </el-form>
  163. <template #footer>
  164. <div class="dialog-footer">
  165. <el-button type="primary" @click="submitForm">确 定</el-button>
  166. <el-button @click="cancel">取 消</el-button>
  167. </div>
  168. </template>
  169. </el-dialog>
  170. <!-- 设备导入对话框 -->
  171. <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
  172. <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
  173. <el-icon class="el-icon--upload"><upload-filled /></el-icon>
  174. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  175. <template #tip>
  176. <div class="el-upload__tip text-center">
  177. <div class="el-upload__tip">
  178. <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的设备数据
  179. </div>
  180. <span>仅允许导入xls、xlsx格式文件。</span>
  181. <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
  182. </div>
  183. </template>
  184. </el-upload>
  185. <template #footer>
  186. <div class="dialog-footer">
  187. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  188. <el-button @click="upload.open = false">取 消</el-button>
  189. </div>
  190. </template>
  191. </el-dialog>
  192. </div>
  193. </template>
  194. <script setup name="Equipment">
  195. import { getToken } from "@/utils/auth";
  196. import { changeStatus, listEquipment, getEquipment, delEquipment, addEquipment, updateEquipment } from "@/api/hnyz/equipment";
  197. import { getFlowList } from "@/api/hnyz/flow";
  198. import { getPlcList } from "@/api/hnyz/plcInfo";
  199. import { getCommProtocolList } from "@/api/hnyz/commProtocol";
  200. import { getPageList } from '@/api/hnyz/pageControl'
  201. import { onMounted } from "vue";
  202. import { useRouter } from 'vue-router'
  203. /*** 设备导入参数 */
  204. const upload = reactive({
  205. // 是否显示弹出层(设备导入)
  206. open: false,
  207. // 弹出层标题(设备导入)
  208. title: "",
  209. // 是否禁用上传
  210. isUploading: false,
  211. // 是否更新已经存在的用户数据
  212. updateSupport: 0,
  213. // 设置上传的请求头部
  214. headers: { Authorization: "Bearer " + getToken() },
  215. // 上传的地址
  216. url: import.meta.env.VITE_APP_BASE_API + "/hnyz/equipment/importData"
  217. });
  218. /** 导入按钮操作 */
  219. function handleImport() {
  220. upload.title = "设备导入";
  221. upload.open = true;
  222. };
  223. /** 下载模板操作 */
  224. function importTemplate() {
  225. proxy.download("/hnyz/equipment/importTemplate", {
  226. }, `equipment_template_${new Date().getTime()}.xlsx`);
  227. };
  228. /**文件上传中处理 */
  229. const handleFileUploadProgress = (event, file, fileList) => {
  230. upload.isUploading = true;
  231. };
  232. /** 文件上传成功处理 */
  233. const handleFileSuccess = (response, file, fileList) => {
  234. upload.open = false;
  235. upload.isUploading = false;
  236. proxy.$refs["uploadRef"].handleRemove(file);
  237. proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
  238. getList();
  239. };
  240. /** 提交上传文件 */
  241. function submitFileForm() {
  242. proxy.$refs["uploadRef"].submit();
  243. };
  244. const router = useRouter()
  245. onMounted(() => {
  246. getOptions();
  247. });
  248. // 获取所有下拉树结构
  249. function getOptions() {
  250. getPageOptions();
  251. getFlowOptions();
  252. getPlcOptions();
  253. getCommProtocolOptions();
  254. }
  255. const flowOptions = ref([]);// 流程下拉树结构
  256. /** 获取流程列表 */
  257. function getFlowOptions() {
  258. const params = {
  259. // flowType: '1',// 1: 普通流程
  260. };
  261. getFlowList(params).then(response => {
  262. flowOptions.value = response.data;
  263. });
  264. }
  265. const pageOptions = ref([]);// 页面下拉树结构
  266. /** 获取页面列表 */
  267. function getPageOptions() {
  268. getPageList({}).then(response => {
  269. pageOptions.value = response.data;
  270. });
  271. }
  272. const plcOptions = ref([]);// plc下拉树结构
  273. /** 获取plc列表 */
  274. function getPlcOptions() {
  275. getPlcList().then(response => {
  276. plcOptions.value = response.data;
  277. });
  278. }
  279. const commProtocolOptions = ref([]);// 通讯协议下拉树结构
  280. /** 获取通讯协议列表 */
  281. function getCommProtocolOptions() {
  282. getCommProtocolList().then(response => {
  283. commProtocolOptions.value = response.data;
  284. });
  285. }
  286. const { proxy } = getCurrentInstance();
  287. const { equipment_type } = proxy.useDict('equipment_type');
  288. const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
  289. const equipmentList = ref([]);
  290. const open = ref(false);
  291. const loading = ref(true);
  292. const showSearch = ref(true);
  293. const ids = ref([]);
  294. const single = ref(true);
  295. const multiple = ref(true);
  296. const total = ref(0);
  297. const title = ref("");
  298. const data = reactive({
  299. form: {},
  300. queryParams: {
  301. pageNum: 1,
  302. pageSize: 10,
  303. equipmentName: null,
  304. flowIds: null,
  305. code: null,
  306. equipmentType: null,
  307. plcId: null,
  308. protocolId: null,
  309. status: null,
  310. remark: null
  311. },
  312. rules: {
  313. equipmentName: [
  314. { required: true, message: "请输入设备名", trigger: "blur" },
  315. { min: 1, max: 50, message: "长度在 1 到 50 个字符", trigger: "blur" }
  316. ],
  317. flowIds: [
  318. { required: true, message: "请选择对应流程", trigger: "blur" }
  319. ],
  320. code: [
  321. { required: true, message: "请输入标识码", trigger: "blur" },
  322. ],
  323. equipmentType: [
  324. { required: true, message: "请选择设备类型", trigger: "blur" }
  325. ],
  326. }
  327. });
  328. const { queryParams, form, rules } = toRefs(data);
  329. /** 查询设备管理列表 */
  330. function getList() {
  331. loading.value = true;
  332. listEquipment(queryParams.value).then(response => {
  333. equipmentList.value = response.rows;
  334. total.value = response.total;
  335. loading.value = false;
  336. });
  337. }
  338. // 取消按钮
  339. function cancel() {
  340. open.value = false;
  341. reset();
  342. }
  343. // 表单重置
  344. function reset() {
  345. form.value = {
  346. equipmentId: null,
  347. equipmentName: null,
  348. flowIds: null,
  349. pageIds: null,
  350. code: null,
  351. equipmentType: null,
  352. plcId: null,
  353. plcName: null,
  354. protocolId: null,
  355. status: "0",
  356. remark: null,
  357. };
  358. proxy.resetForm("equipmentRef");
  359. }
  360. /** 状态修改 */
  361. function handleStatusChange(row) {
  362. let text = row.status == "0" ? "启用" : "停用";
  363. proxy.$modal.confirm('确认要"' + text + '"设备名为"' + row.equipmentName + '"的数据项吗?').then(function () {
  364. return changeStatus(row.equipmentId, row.status);
  365. }).then(() => {
  366. proxy.$modal.msgSuccess(text + "成功");
  367. }).catch(function () {
  368. row.status = row.status == "0" ? "1" : "0";
  369. });
  370. }
  371. /** 搜索按钮操作 */
  372. function handleQuery() {
  373. queryParams.value.pageNum = 1;
  374. getList();
  375. }
  376. /** 重置按钮操作 */
  377. function resetQuery() {
  378. proxy.resetForm("queryRef");
  379. handleQuery();
  380. }
  381. // 多选框选中数据
  382. function handleSelectionChange(selection) {
  383. ids.value = selection.map(item => item.equipmentId);
  384. single.value = selection.length != 1;
  385. multiple.value = !selection.length;
  386. }
  387. /** 新增按钮操作 */
  388. function handleAdd() {
  389. reset();
  390. open.value = true;
  391. title.value = "添加设备管理";
  392. }
  393. /** 修改按钮操作 */
  394. function handleUpdate(row) {
  395. reset();
  396. const _equipmentId = row.equipmentId || ids.value
  397. getEquipment(_equipmentId).then(response => {
  398. form.value = response.data;
  399. //字符串转整型数组
  400. if (form.value.flowIds) {
  401. form.value.flowIds = form.value.flowIds.split(',').map(Number);
  402. }
  403. if (form.value.pageIds) {
  404. form.value.pageIds = form.value.pageIds.split(',').map(Number);
  405. }
  406. open.value = true;
  407. title.value = "修改设备管理";
  408. });
  409. }
  410. /** 提交按钮 */
  411. function submitForm() {
  412. proxy.$refs["equipmentRef"].validate(valid => {
  413. if (valid) {
  414. // 处理 flowIds:数组转字符串
  415. if (form.value.flowIds) {
  416. form.value.flowIds = form.value.flowIds.join(',');
  417. }
  418. // 处理 pageIds:数组转字符串
  419. if (form.value.pageIds) {
  420. form.value.pageIds = form.value.pageIds.join(',');
  421. }
  422. if (form.value.equipmentId != null) {
  423. updateEquipment(form.value).then(response => {
  424. proxy.$modal.msgSuccess("修改成功");
  425. open.value = false;
  426. getList();
  427. }).catch(error => {
  428. form.value.flowIds = form.value.flowIds.split(',').map(Number);
  429. form.value.pageIds = form.value.pageIds.split(',').map(Number);
  430. });
  431. } else {
  432. addEquipment(form.value).then(response => {
  433. proxy.$modal.msgSuccess("新增成功");
  434. open.value = false;
  435. getList();
  436. }).catch(error => {
  437. console.log(error);
  438. form.value.flowIds = form.value.flowIds.split(',').map(Number);
  439. form.value.pageIds = form.value.pageIds.split(',').map(Number);
  440. });
  441. }
  442. }
  443. });
  444. }
  445. /** 删除按钮操作 */
  446. function handleDelete(row) {
  447. const _equipmentIds = row.equipmentId || ids.value;
  448. proxy.$modal.confirm('是否确认删除设备管理编号为"' + _equipmentIds + '"的数据项?').then(function () {
  449. return delEquipment(_equipmentIds);
  450. }).then(() => {
  451. getList();
  452. proxy.$modal.msgSuccess("删除成功");
  453. }).catch(() => { });
  454. }
  455. /** 导出按钮操作 */
  456. function handleExport() {
  457. proxy.download('hnyz/equipment/export', {
  458. ...queryParams.value
  459. }, `equipment_${new Date().getTime()}.xlsx`)
  460. }
  461. // 详情按钮操作
  462. function toDetail(code) {
  463. console.log(code)
  464. router.push({
  465. path: '/index',
  466. query: { code }
  467. })
  468. }
  469. getList();
  470. </script>