From 97dc174b26461df1395394c02401bb51dd6376bc Mon Sep 17 00:00:00 2001 From: bsw215583320 <baoshiwei121@163.com> Date: 星期一, 04 十二月 2023 08:03:53 +0800 Subject: [PATCH] 增加opc设备维护和控制功能 --- src/views/dashboard/control/api.ts | 14 src/views/dry/components/DryOpcDeviceModal.vue | 66 ++++ src/views/dry/DryOpcDeviceList.vue | 174 +++++++++++ src/assets/images/dry/control/light.png | 0 src/assets/images/dry/control/cam0.png | 0 src/views/dashboard/control/index.vue | 296 +++++++++++++++++++ src/views/dry/sql/DryOpcDevice_menu_insert.sql | 26 + src/assets/images/dry/control/light-close.png | 0 src/views/dry/api/DryOpcDevice.api.ts | 64 ++++ src/views/dry/components/DryOpcDeviceForm.vue | 70 ++++ src/views/dry/dataDefine/DryOpcDevice.data.ts | 109 +++++++ src/assets/images/dry/control/cam1.png | 0 src/views/dry/bigScreen/BigWorkShop.vue | 51 ++ src/assets/images/dry/control/cam.png | 0 src/assets/images/dry/control/cam-close.png | 0 15 files changed, 850 insertions(+), 20 deletions(-) diff --git a/src/assets/images/dry/control/cam-close.png b/src/assets/images/dry/control/cam-close.png new file mode 100644 index 0000000..0218b87 --- /dev/null +++ b/src/assets/images/dry/control/cam-close.png Binary files differ diff --git a/src/assets/images/dry/control/cam.png b/src/assets/images/dry/control/cam.png new file mode 100644 index 0000000..bb963f1 --- /dev/null +++ b/src/assets/images/dry/control/cam.png Binary files differ diff --git a/src/assets/images/dry/control/cam0.png b/src/assets/images/dry/control/cam0.png new file mode 100644 index 0000000..1f285b9 --- /dev/null +++ b/src/assets/images/dry/control/cam0.png Binary files differ diff --git a/src/assets/images/dry/control/cam1.png b/src/assets/images/dry/control/cam1.png new file mode 100644 index 0000000..c3a2695 --- /dev/null +++ b/src/assets/images/dry/control/cam1.png Binary files differ diff --git a/src/assets/images/dry/control/light-close.png b/src/assets/images/dry/control/light-close.png new file mode 100644 index 0000000..9c64966 --- /dev/null +++ b/src/assets/images/dry/control/light-close.png Binary files differ diff --git a/src/assets/images/dry/control/light.png b/src/assets/images/dry/control/light.png new file mode 100644 index 0000000..057ead2 --- /dev/null +++ b/src/assets/images/dry/control/light.png Binary files differ diff --git a/src/views/dashboard/control/api.ts b/src/views/dashboard/control/api.ts index 76a5c9f..703be84 100644 --- a/src/views/dashboard/control/api.ts +++ b/src/views/dashboard/control/api.ts @@ -2,6 +2,8 @@ enum Api { sendCommand = '/dry/real/sendCommand', + sendWriteCommand = '/dry/opc/sendWriteCommand', + listAll = '/dry/dryOpcDevice/listAll' } /** * 鍙戦�佸懡浠� @@ -9,3 +11,15 @@ */ export const sendCommand = (params) => defHttp.post({ url: Api.sendCommand, params },{ isTransformResponse: false }); +/** + * 鍙戦�丱PC鍐欐寚浠� + */ + +export const sendWriteCommand = (params) => defHttp.post({url: Api.sendWriteCommand, params},{isTransformResponse: false}) + +/** + * 鏌ヨ鎵�鏈塐PC璁惧 + */ + +export const listAll = (params) => defHttp.get({url:Api.listAll, params}) + diff --git a/src/views/dashboard/control/index.vue b/src/views/dashboard/control/index.vue index 5085e12..e9d321d 100644 --- a/src/views/dashboard/control/index.vue +++ b/src/views/dashboard/control/index.vue @@ -7,12 +7,125 @@ </a-modal> <div class="app"> - <a-card title="鎸囦护"> + <a-row> + <a-card title="鐓ф槑" style="width: 60%"> + <div class="light-box"> + <div v-for="item in lightList" :key="item.identifier" class="center"> + <!-- <a-button v-if="item.type == 0" type="primary" class="com-btn" + @click="deviceClick(item)"> + {{ item.name }} + </a-button> --> + <div v-if="item.type==0" @click="deviceClick(item)"> + <div :class="[ item.value?'lightOn':'lightOff' ,'device']"> + + + </div> + <div class="text-center">{{ item.name }}</div> + + </div> + </div> + + </div> + </a-card> + <a-card title="鐩戞帶" style="width: 35%; margin-left: 10px;"> + <div class="monitor-box"> + <div v-for="item in lightList" :key="item.identifier" class="center" > + <div v-if="item.type==1" @click="deviceClick(item)"> + <div :class="[ item.value?'camOn':'camOff' ,'device']"> + + + </div> + <div class="text-center">{{ item.name }}</div> + </div> + </div> + </div> + </a-card> + + </a-row> + + <a-card title="鎸囦护" style="margin-top: 10px"> <div class="com-box"> - <a-button v-for="item in comList" :key="item.id" type="primary" class="com-btn" + <!-- <a-button v-for="item in comList" :key="item.id" type="primary" class="com-btn" @click="comClick(item)"> {{ item.title }} + </a-button> --> + <div style="width: 500px;"> + + <a-row class="button-row"> + <a-button type="primary" @click="clickButton(1010, '骞茬嚗鍚姩')" class="com-btn"> + <div> <PlayCircleOutlined style="font-size: 20px;" /> </div> + <div> 骞茬嚗鍚姩 </div> + </a-button> + <!-- <a-button type="normal" @click="clickButton(1012)" class="com-btn"> + <div> <SplitCellsOutlined style="font-size: 20px;" /> </div> + <div> 鍚庨棬寮�鍏� </div> + + </a-button> --> + <a-button type="default" @click="clickButton(1003,'婊氱瓛鍗�')" class="com-btn w300"> + <div> <UpCircleOutlined style="font-size: 20px;" /> </div> + <div> 婊氱瓛鍗� </div> + + </a-button> + <a-button type="info" @click="clickButton(1014, '寮�闂ㄨ瀵�')" class="com-btn"> + <div> <SettingOutlined style="font-size: 20px;" /> </div> + <div> 寮�闂ㄨ瀵� </div> + + </a-button> + </a-row> + <a-row class="button-row"> + <a-button type="normal" @click="clickButton(1005,'婊氱瓛姝h浆')" class="com-btn h100"> + <div> <RedoOutlined style="font-size: 20px;" /> </div> + <div> 婊氱瓛姝h浆 </div> + </a-button> + <a-button type="danger" @click="clickButton(1007,'鍋滄')" class="com-btn h100 w300 " > + <div> <PauseCircleOutlined style="font-size: 20px;" /> </div> + <div> 鍋滄 </div> + </a-button> + <a-button type="normal" @click="clickButton(1006,'婊氱瓛鍙嶈浆')" class="com-btn h100"> + <div> <UndoOutlined style="font-size: 20px;" /> </div> + <div> 婊氱瓛鍙嶈浆 </div> + </a-button> + </a-row> + <a-row class="button-row"> + <a-button type="success" @click="clickButton(1015,'鍑烘枡')" class="com-btn"> + <div> <DownloadOutlined style="font-size: 20px;" /> </div> + <div> 鍑烘枡 </div> + + </a-button> + <!-- <a-button type="normal" @click="clickButton(1010)" class="com-btn"> + <div> <SplitCellsOutlined style="font-size: 20px;" /> </div> + <div> 鍓嶉棬寮�鍏� </div> + </a-button> --> + <a-button type="normal" @click="clickButton(1004,'婊氱瓛闄�')" class="com-btn w300"> + <div> <DownCircleOutlined style="font-size: 20px;" /> </div> + <div> 婊氱瓛闄� </div> + </a-button> + <a-button type="normal" @click="clickButton(1013,'鐑鍚姩')" class="com-btn"> + <div> <FireOutlined style="font-size: 20px;" /> </div> + <div> 鐑鍚姩 </div> + + </a-button> + </a-row> + + </div> + <div style="margin-left: 100px;"> + <div> + <a-button type="warning" @click="clickButton(1017,'鎵嬪姩/鑷姩')" class="com-btn"> + <div> <SyncOutlined style="font-size: 20px;" /> </div> + <div> 鎵嬪姩/鑷姩 </div> + + </a-button> + </div> + <div> + <a-button type="normal" @click="clickButton(1016,'娓呴櫎')" class="com-btn"> + <div> <ClearOutlined style="font-size: 20px;" /> </div> + <div> 娓呴櫎 </div> + + </a-button> + </div> + </div> + </div> </a-card> <a-card title="鎺у埗鍙�" style="margin-top: 10px"> @@ -26,16 +139,28 @@ <script setup lang="ts"> import { ref, onMounted } from "vue"; -import { sendCommand } from "./api"; +import { sendCommand, sendWriteCommand, listAll } from "./api"; +import { useGlobSetting } from '/@/hooks/setting'; +import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket'; +import { useUserStore } from '/@/store/modules/user'; +import { RedoOutlined ,SettingOutlined, UndoOutlined,FireOutlined, SplitCellsOutlined, DownloadOutlined, PauseCircleOutlined,ClearOutlined, SyncOutlined,PlayCircleOutlined, SwapOutlined , UpCircleOutlined, DownCircleOutlined, LeftCircleOutlined, RightCircleOutlined} from '@ant-design/icons-vue'; + const visible = ref<boolean>(false); - + const glob = useGlobSetting(); interface Commant { id: number; title: string; icon: string; } +interface Device { + name: string; + identifier: string; + value: boolean; + sort_order: number; +} +const userStore = useUserStore(); const logList = ref<string[]>([]); const comList = ref<Commant[]>([ { @@ -88,6 +213,9 @@ icon: "caret-right-outlined" }]); + +const lightList = ref<Device[]>([]); +const monitorList = ref<Device[]>([]); function comClick(item) { addLog("鍙戦��", item.title); //鍙戦�佹寚浠� @@ -133,9 +261,81 @@ visible.value = false; }; +/** + * 鏌ヨ鐏拰鎽勫儚澶村垪琛� + */ +function queryDevice() { + listAll({}).then(res => { + console.log("ress000:",res); + lightList.value = res + }) + + +} + +function clickButton(cmd, msg) { + console.log("target::::",cmd); + var params = { msg: msg, code: cmd, tenantId: 1003, machineId: "GM001" }; + sendCommand(params).then(res => { + if (res.success) { + addLog("鍝嶅簲", res.message); + console.info(res); + } else { + console.info(res); + addLog("鍝嶅簲", res.message); + } + + }); +} + + + + +function deviceClick(item) { + //console.log("item===",item.value); + let params = {code: item.identifier, msg: !item.value} + sendWriteCommand(params).then(res => { + console.log("鍐欐寚浠ょ粨鏋滐細锛�", res) + if(res.success) { + lightList.value.forEach(device => { + if(device.identifier == item.identifier) { + device.value = !item.value + } + }) + } + }) + +} + + // 鍒濆鍖� WebSocket + function initWebSocket() { + + let user = userStore.getUserInfo; + let tenantId = user.loginTenantId; + + console.log(user); + // WebSocket涓庢櫘閫氱殑璇锋眰鎵�鐢ㄥ崗璁湁鎵�涓嶅悓锛寃s绛夊悓浜巋ttp锛寃ss绛夊悓浜巋ttps + let url = glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/drySocket/' + tenantId; + + connectWebSocket(url); + onWebSocket(onWebSocketMessage); + } + + function onWebSocketMessage(data) { + console.log("drysocket:data::",data) + lightList.value.forEach(item => { + if(item.identifier == data.identifier) { + item.value = data.value + } + }) + } + onMounted(() => { showModal(); + initWebSocket(); }); + +queryDevice() </script> @@ -146,23 +346,101 @@ } .com-box { - display: flex; - flex-wrap: wrap; + // margin-left: 200px; + display: flex; + + .com-btn { + border-radius: 5px; + width: 100px; margin: 10px; + height: 70px; } } +.button-row { + display: flex; justify-content: space-between; +} + .log-box { - min-height: 200px; - max-height: 300px; - overflow-y: scroll; + min-height: 150px; + max-height: 150px; + overflow-y: auto; } .indented-text { text-indent: 20px; font-size: 16px; } +.light-box { + display: flex; + justify-items: center; +justify-content: center; + flex-wrap: wrap; + +} +.center { + display: flex; +justify-items: center; +justify-content: center; +} + +.text-center { + text-align: center; +} + +.lightOn { + background-image: url(/src/assets/images/dry/control/light.png); + background-repeat: no-repeat; + background-size: 50px; + /* border-radius: 10px; */ + background-position: 48px 0px; + } + .lightOff { + background-image: url(/src/assets/images/dry/control/light-close.png); + background-repeat: no-repeat; + background-size: 50px; + /* border-radius: 10px; */ + background-position: 48px 0px; + } + + .camOn { + background-image: url(/src/assets/images/dry/control/cam1.png); + background-repeat: no-repeat; + background-size: 50px; + /* border-radius: 10px; */ + background-position: 48px 0px; + } + .camOff { + background-image: url(/src/assets/images/dry/control/cam0.png); + background-repeat: no-repeat; + background-size: 50px; + /* border-radius: 10px; */ + background-position: 48px 0px; + } + + +.device { + width: 150px; height: 60px; + +} + +.h100 { + height: 70px !important; +} + +.w300 { + width: 100px !important; +} + +.monitor-box { + display: flex; + justify-items: center; +justify-content: center; +flex-wrap: wrap; + +} + </style> diff --git a/src/views/dry/DryOpcDeviceList.vue b/src/views/dry/DryOpcDeviceList.vue new file mode 100644 index 0000000..f0b4892 --- /dev/null +++ b/src/views/dry/DryOpcDeviceList.vue @@ -0,0 +1,174 @@ +<template> + <div> + <!--寮曠敤琛ㄦ牸--> + <BasicTable @register="registerTable" :rowSelection="rowSelection"> + <!--鎻掓Ы:table鏍囬--> + <template #tableTitle> + <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 鏂板</a-button> + <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 瀵煎嚭</a-button> + <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">瀵煎叆</j-upload-button> + <a-dropdown v-if="selectedRowKeys.length > 0"> + <template #overlay> + <a-menu> + <a-menu-item key="1" @click="batchHandleDelete"> + <Icon icon="ant-design:delete-outlined"></Icon> + 鍒犻櫎 + </a-menu-item> + </a-menu> + </template> + <a-button>鎵归噺鎿嶄綔 + <Icon icon="mdi:chevron-down"></Icon> + </a-button> + </a-dropdown> + </template> + <!--鎿嶄綔鏍�--> + <template #action="{ record }"> + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/> + </template> + <!--瀛楁鍥炴樉鎻掓Ы--> + <template #htmlSlot="{text}"> + <div v-html="text"></div> + </template> + <!--鐪佸競鍖哄瓧娈靛洖鏄炬彃妲�--> + <template #pcaSlot="{text}"> + {{ getAreaTextByCode(text) }} + </template> + <template #fileSlot="{text}"> + <span v-if="!text" style="font-size: 12px;font-style: italic;">鏃犳枃浠�</span> + <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">涓嬭浇</a-button> + </template> + </BasicTable> + <!-- 琛ㄥ崟鍖哄煙 --> + <DryOpcDeviceModal @register="registerModal" @success="handleSuccess"></DryOpcDeviceModal> + </div> +</template> + +<script lang="ts" name="dry-dryOpcDevice" setup> + import {ref, computed, unref} from 'vue'; + import {BasicTable, useTable, TableAction} from '/@/components/Table'; + import {useModal} from '/@/components/Modal'; + import { useListPage } from '/@/hooks/system/useListPage' + import DryOpcDeviceModal from './components/DryOpcDeviceModal.vue' + import {columns, searchFormSchema} from './dataDefine/DryOpcDevice.data'; + import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './api/DryOpcDevice.api'; + import { downloadFile } from '/@/utils/common/renderUtils'; + const checkedKeys = ref<Array<string | number>>([]); + //娉ㄥ唽model + const [registerModal, {openModal}] = useModal(); + //娉ㄥ唽table鏁版嵁 + const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({ + tableProps:{ + title: 'dry_opc_device', + api: list, + columns, + canResize:false, + formConfig: { + //labelWidth: 120, + schemas: searchFormSchema, + autoSubmitOnEnter:true, + showAdvancedButton:true, + fieldMapToNumber: [ + ], + fieldMapToTime: [ + ], + }, + actionColumn: { + width: 120, + fixed:'right' + }, + }, + exportConfig: { + name:"dry_opc_device", + url: getExportUrl, + }, + importConfig: { + url: getImportUrl, + success: handleSuccess + }, + }) + + const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext + + /** + * 鏂板浜嬩欢 + */ + function handleAdd() { + openModal(true, { + isUpdate: false, + showFooter: true, + }); + } + /** + * 缂栬緫浜嬩欢 + */ + function handleEdit(record: Recordable) { + openModal(true, { + record, + isUpdate: true, + showFooter: true, + }); + } + /** + * 璇︽儏 + */ + function handleDetail(record: Recordable) { + openModal(true, { + record, + isUpdate: true, + showFooter: false, + }); + } + /** + * 鍒犻櫎浜嬩欢 + */ + async function handleDelete(record) { + console.log(record); + await deleteOne({id: record.id}, handleSuccess); + } + /** + * 鎵归噺鍒犻櫎浜嬩欢 + */ + async function batchHandleDelete() { + await batchDelete({ids: selectedRowKeys.value}, handleSuccess); + } + /** + * 鎴愬姛鍥炶皟 + */ + function handleSuccess() { + (selectedRowKeys.value = []) && reload(); + } + /** + * 鎿嶄綔鏍� + */ + function getTableAction(record){ + return [ + { + label: '缂栬緫', + onClick: handleEdit.bind(null, record), + } + ] + } + /** + * 涓嬫媺鎿嶄綔鏍� + */ + function getDropDownAction(record){ + return [ + { + label: '璇︽儏', + onClick: handleDetail.bind(null, record), + }, { + label: '鍒犻櫎', + popConfirm: { + title: '鏄惁纭鍒犻櫎', + confirm: handleDelete.bind(null, record), + } + } + ] + } + + +</script> + +<style scoped> + +</style> \ No newline at end of file diff --git a/src/views/dry/api/DryOpcDevice.api.ts b/src/views/dry/api/DryOpcDevice.api.ts new file mode 100644 index 0000000..21ed673 --- /dev/null +++ b/src/views/dry/api/DryOpcDevice.api.ts @@ -0,0 +1,64 @@ +import {defHttp} from '/@/utils/http/axios'; +import { useMessage } from "/@/hooks/web/useMessage"; + +const { createConfirm } = useMessage(); + +enum Api { + list = '/dry/dryOpcDevice/list', + save='/dry/dryOpcDevice/add', + edit='/dry/dryOpcDevice/edit', + deleteOne = '/dry/dryOpcDevice/delete', + deleteBatch = '/dry/dryOpcDevice/deleteBatch', + importExcel = '/dry/dryOpcDevice/importExcel', + exportXls = '/dry/dryOpcDevice/exportXls', +} +/** + * 瀵煎嚭api + * @param params + */ +export const getExportUrl = Api.exportXls; +/** + * 瀵煎叆api + */ +export const getImportUrl = Api.importExcel; +/** + * 鍒楄〃鎺ュ彛 + * @param params + */ +export const list = (params) => + defHttp.get({url: Api.list, params}); + +/** + * 鍒犻櫎鍗曚釜 + */ +export const deleteOne = (params,handleSuccess) => { + return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => { + handleSuccess(); + }); +} +/** + * 鎵归噺鍒犻櫎 + * @param params + */ +export const batchDelete = (params, handleSuccess) => { + createConfirm({ + iconType: 'warning', + title: '纭鍒犻櫎', + content: '鏄惁鍒犻櫎閫変腑鏁版嵁', + okText: '纭', + cancelText: '鍙栨秷', + onOk: () => { + return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => { + handleSuccess(); + }); + } + }); +} +/** + * 淇濆瓨鎴栬�呮洿鏂� + * @param params + */ +export const saveOrUpdate = (params, isUpdate) => { + let url = isUpdate ? Api.edit : Api.save; + return defHttp.post({url: url, params}); +} diff --git a/src/views/dry/bigScreen/BigWorkShop.vue b/src/views/dry/bigScreen/BigWorkShop.vue index 9c9db95..c5c59a1 100644 --- a/src/views/dry/bigScreen/BigWorkShop.vue +++ b/src/views/dry/bigScreen/BigWorkShop.vue @@ -19,12 +19,12 @@ <div style="display: flex; width: 120px"> <Icon style="color: #ba9853" icon="mdi:home-temperature-outline" :size="28" /> - <div style="font-size: 20px; line-height: 26px"> 26 鈩� </div> + <div style="font-size: 20px; line-height: 26px"> {{envTemp}} 鈩� </div> </div> <div style="display: flex"> <Icon style="color: #ba9853" icon="wi:humidity" :size="28" /> - <div style="font-size: 20px; line-height: 26px"> 53 %rh </div> + <div style="font-size: 20px; line-height: 26px"> {{envHum}} %rh </div> </div> </div> <div class="feed"> @@ -58,7 +58,7 @@ 鐢甸噺娑堣�� </div> <div class="stat_value"> - 462 + {{dianneng.toFixed(2)}} <span class="font16"> Kwh </span> @@ -79,7 +79,7 @@ 钂告苯娑堣�� </div> <div class="stat_value"> - 683 + {{zhengqi.toFixed(2)}} <span class="font16"> m鲁 </span> @@ -285,6 +285,7 @@ </div> </div> </div> + <div class="footer"> <div >{{ nowDate }}</div> @@ -311,6 +312,13 @@ const eqps = ref([] as dryEquipment[]) const title = ref("鍏版郸鏅鸿兘骞茬嚗杞﹂棿") const userStore = useUserStore() + const envHum = ref(); + const envTemp = ref(); + const zhengqi = ref(); + const dianneng = ref() + + const steam = ref(); + const watt = ref() console.log(userStore.dictItems.title) userStore.dictItems.title?.forEach(element => { if (element.value === "bigscreentitle") { @@ -343,18 +351,34 @@ function updateRealTime() { //console.log(`output->瀹氭椂鍒锋柊鏁版嵁`) - eqps.value.forEach((item) => { - queryRealTime(item) + zhengqi.value = 0; + dianneng.value = 0 + + new Promise(async function(resolve){ + + await eqps.value.forEach(async (item) => { + await queryRealTime(item) + }) + resolve() + + console.log("鎵ц瀹屾垚"); + }).then(()=>{ + console.log("then:::::" + dianneng.value,zhengqi.value ); + + steam.value = zhengqi.value + watt.value = dianneng.value }) + + } - function queryRealTime(eqp: dryEquipment) { - + async function queryRealTime(eqp: dryEquipment) { + console.log("sdkfjlasjdflkajsldfjlsd") let tenantId = userStore.getTenant let eqpCode = eqp.code let queryRealTimeUrl = '/dry/real/getRealTimeData' - defHttp.get({ url: queryRealTimeUrl, params: { tenantid: tenantId, machineid: eqpCode } }).then((res) => { - //console.log(`output->res`, res) + await defHttp.get({ url: queryRealTimeUrl, params: { tenantid: tenantId, machineid: eqpCode } }).then( async (res) => { + console.log(`output->res`, res) if (res && res.trendVo) { res.tempValue = [res.windTemp, 100] res.totalRemain = res.remain @@ -367,6 +391,11 @@ } res.percent = ((res.dryTime / (res.dryTime + res.totalRemain)) * 100).toFixed(2) + envHum.value = res.envHum + envTemp.value = res.envTemp + zhengqi.value += res.steam + dianneng.value += res.watt + console.log("zhengqi:::" , res.steam); } else { res = { tempValue: [0, 100], @@ -627,7 +656,7 @@ } .stat_value { - font-size: 32px + font-size: 28px } .herb_weight { diff --git a/src/views/dry/components/DryOpcDeviceForm.vue b/src/views/dry/components/DryOpcDeviceForm.vue new file mode 100644 index 0000000..fbd7533 --- /dev/null +++ b/src/views/dry/components/DryOpcDeviceForm.vue @@ -0,0 +1,70 @@ +<template> + <div style="min-height: 400px"> + <BasicForm @register="registerForm"></BasicForm> + <div style="width: 100%;text-align: center" v-if="!formDisabled"> + <a-button @click="submitForm" pre-icon="ant-design:check" type="primary">鎻� 浜�</a-button> + </div> + </div> +</template> + +<script lang="ts"> + import {BasicForm, useForm} from '/@/components/Form/index'; + import {computed, defineComponent} from 'vue'; + import {defHttp} from '/@/utils/http/axios'; + import { propTypes } from '/@/utils/propTypes'; + import {getBpmFormSchema} from '../dataDefine/DryOpcDevice.data'; + import {saveOrUpdate} from '../api/DryOpcDevice.api'; + + export default defineComponent({ + name: "DryOpcDeviceForm", + components:{ + BasicForm + }, + props:{ + formData: propTypes.object.def({}), + formBpm: propTypes.bool.def(true), + }, + setup(props){ + const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({ + labelWidth: 150, + schemas: getBpmFormSchema(props.formData), + showActionButtonGroup: false, + baseColProps: {span: 24} + }); + + const formDisabled = computed(()=>{ + if(props.formData.disabled === false){ + return false; + } + return true; + }); + + let formData = {}; + const queryByIdUrl = '/dry/dryOpcDevice/queryById'; + async function initFormData(){ + let params = {id: props.formData.dataId}; + const data = await defHttp.get({url: queryByIdUrl, params}); + formData = {...data} + //璁剧疆琛ㄥ崟鐨勫�� + await setFieldsValue(formData); + //榛樿鏄鐢� + await setProps({disabled: formDisabled.value}) + } + + async function submitForm() { + let data = getFieldsValue(); + let params = Object.assign({}, formData, data); + console.log('琛ㄥ崟鏁版嵁', params) + await saveOrUpdate(params, true) + } + + initFormData(); + + return { + registerForm, + formDisabled, + submitForm, + } + } + }); +</script> \ No newline at end of file diff --git a/src/views/dry/components/DryOpcDeviceModal.vue b/src/views/dry/components/DryOpcDeviceModal.vue new file mode 100644 index 0000000..96d8c7c --- /dev/null +++ b/src/views/dry/components/DryOpcDeviceModal.vue @@ -0,0 +1,66 @@ +<template> + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit"> + <BasicForm @register="registerForm"/> + </BasicModal> +</template> + +<script lang="ts" setup> + import {ref, computed, unref} from 'vue'; + import {BasicModal, useModalInner} from '/@/components/Modal'; + import {BasicForm, useForm} from '/@/components/Form/index'; + import {formSchema} from '../dataDefine/DryOpcDevice.data'; + import {saveOrUpdate} from '../api/DryOpcDevice.api'; + // Emits澹版槑 + const emit = defineEmits(['register','success']); + const isUpdate = ref(true); + //琛ㄥ崟閰嶇疆 + const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({ + //labelWidth: 150, + schemas: formSchema, + showActionButtonGroup: false, + baseColProps: {span: 24} + }); + //琛ㄥ崟璧嬪�� + const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => { + //閲嶇疆琛ㄥ崟 + await resetFields(); + setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter}); + isUpdate.value = !!data?.isUpdate; + if (unref(isUpdate)) { + //琛ㄥ崟璧嬪�� + await setFieldsValue({ + ...data.record, + }); + } + // 闅愯棌搴曢儴鏃剁鐢ㄦ暣涓〃鍗� + setProps({ disabled: !data?.showFooter }) + }); + //璁剧疆鏍囬 + const title = computed(() => (!unref(isUpdate) ? '鏂板' : '缂栬緫')); + //琛ㄥ崟鎻愪氦浜嬩欢 + async function handleSubmit(v) { + try { + let values = await validate(); + setModalProps({confirmLoading: true}); + //鎻愪氦琛ㄥ崟 + await saveOrUpdate(values, isUpdate.value); + //鍏抽棴寮圭獥 + closeModal(); + //鍒锋柊鍒楄〃 + emit('success'); + } finally { + setModalProps({confirmLoading: false}); + } + } +</script> + +<style lang="less" scoped> + /** 鏃堕棿鍜屾暟瀛楄緭鍏ユ鏍峰紡 */ + :deep(.ant-input-number){ + width: 100% + } + + :deep(.ant-calendar-picker){ + width: 100% + } +</style> \ No newline at end of file diff --git a/src/views/dry/dataDefine/DryOpcDevice.data.ts b/src/views/dry/dataDefine/DryOpcDevice.data.ts new file mode 100644 index 0000000..ccb1c0d --- /dev/null +++ b/src/views/dry/dataDefine/DryOpcDevice.data.ts @@ -0,0 +1,109 @@ +import {BasicColumn} from '/@/components/Table'; +import {FormSchema} from '/@/components/Table'; +import { rules} from '/@/utils/helper/validator'; +import { render } from '/@/utils/common/renderUtils'; +//鍒楄〃鏁版嵁 +export const columns: BasicColumn[] = [ + { + title: '鍚嶇О', + align:"center", + dataIndex: 'name' + }, + { + title: '鐐逛綅鏍囪瘑', + align:"center", + dataIndex: 'identifier' + }, + { + title: '鎺掑簭', + align:"center", + dataIndex: 'sortOrder' + }, + { + title: '绫诲瀷', + align:"center", + dataIndex: 'type_dictText' + }, +]; +//鏌ヨ鏁版嵁 +export const searchFormSchema: FormSchema[] = [ + { + label: "鍚嶇О", + field: 'name', + component: 'Input', + colProps: {span: 6}, + }, + { + label: "绫诲瀷", + field: 'type', + component: 'JDictSelectTag', + componentProps:{ + dictCode:"device_type" + }, + colProps: {span: 6}, + }, +]; +//琛ㄥ崟鏁版嵁 +export const formSchema: FormSchema[] = [ + { + label: '鍚嶇О', + field: 'name', + component: 'Input', + dynamicRules: ({model,schema}) => { + return [ + { required: true, message: '璇疯緭鍏ュ悕绉�!'}, + ]; + }, + }, + { + label: '鐐逛綅鏍囪瘑', + field: 'identifier', + component: 'Input', + dynamicRules: ({model,schema}) => { + return [ + { required: true, message: '璇疯緭鍏ョ偣浣嶆爣璇�!'}, + ]; + }, + }, + { + label: '鎺掑簭', + field: 'sortOrder', + component: 'InputNumber', + dynamicRules: ({model,schema}) => { + return [ + { required: true, message: '璇疯緭鍏ユ帓搴�!'}, + ]; + }, + }, + { + label: '绫诲瀷', + field: 'type', + component: 'JDictSelectTag', + componentProps:{ + dictCode:"device_type" + }, + dynamicRules: ({model,schema}) => { + return [ + { required: true, message: '璇疯緭鍏ョ被鍨�!'}, + ]; + }, + }, + // TODO 涓婚敭闅愯棌瀛楁锛岀洰鍓嶅啓姝讳负ID + { + label: '', + field: 'id', + component: 'Input', + show: false + }, +]; + + + +/** +* 娴佺▼琛ㄥ崟璋冪敤杩欎釜鏂规硶鑾峰彇formSchema +* @param param +*/ +export function getBpmFormSchema(_formData): FormSchema[]{ + // 榛樿鍜屽師濮嬭〃鍗曚繚鎸佷竴鑷� 濡傛灉娴佺▼涓厤缃簡鏉冮檺鏁版嵁锛岃繖閲岄渶瑕佸崟鐙鐞唂ormSchema + return formSchema; +} \ No newline at end of file diff --git a/src/views/dry/sql/DryOpcDevice_menu_insert.sql b/src/views/dry/sql/DryOpcDevice_menu_insert.sql new file mode 100644 index 0000000..c30a1b8 --- /dev/null +++ b/src/views/dry/sql/DryOpcDevice_menu_insert.sql @@ -0,0 +1,26 @@ +-- 娉ㄦ剰锛氳椤甸潰瀵瑰簲鐨勫墠鍙扮洰褰曚负views/dry鏂囦欢澶逛笅 +-- 濡傛灉浣犳兂鏇存敼鍒板叾浠栫洰褰曪紝璇蜂慨鏀箂ql涓璫omponent瀛楁瀵瑰簲鐨勫�� + + +INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) +VALUES ('2023112802425240080', NULL, 'dry_opc_device', '/dry/dryOpcDeviceList', 'dry/DryOpcDeviceList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2023-11-28 14:42:08', NULL, NULL, 0); + +-- 鏉冮檺鎺у埗sql +-- 鏂板 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('2023112802425240081', '2023112802425240080', '娣诲姞dry_opc_device', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_opc_device:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-11-28 14:42:08', NULL, NULL, 0, 0, '1', 0); +-- 缂栬緫 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('2023112802425240082', '2023112802425240080', '缂栬緫dry_opc_device', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_opc_device:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-11-28 14:42:08', NULL, NULL, 0, 0, '1', 0); +-- 鍒犻櫎 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('2023112802425240083', '2023112802425240080', '鍒犻櫎dry_opc_device', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_opc_device:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-11-28 14:42:08', NULL, NULL, 0, 0, '1', 0); +-- 鎵归噺鍒犻櫎 +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('2023112802425240084', '2023112802425240080', '鎵归噺鍒犻櫎dry_opc_device', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_opc_device:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-11-28 14:42:08', NULL, NULL, 0, 0, '1', 0); +-- 瀵煎嚭excel +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('2023112802425240085', '2023112802425240080', '瀵煎嚭excel_dry_opc_device', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_opc_device:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-11-28 14:42:08', NULL, NULL, 0, 0, '1', 0); +-- 瀵煎叆excel +INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) +VALUES ('2023112802425240086', '2023112802425240080', '瀵煎叆excel_dry_opc_device', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_opc_device:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-11-28 14:42:08', NULL, NULL, 0, 0, '1', 0); \ No newline at end of file -- Gitblit v1.9.3