干燥机配套车间生产管理系统/云平台前端
baoshiwei
2 天以前 82008a07191354da957173b9ec9ce11ca789f9aa
feat(bigScreen): 新增大屏展示页面

- 添加 BigWorkShop-tjt 和 BigEqp-tjt 组件用于大屏展示
- 更新路由配置,增加大屏相关路径
- 修改权限守卫,允许免登录访问大屏页面
已添加10个文件
已修改5个文件
3351 ■■■■■ 文件已修改
src/assets/images/dry/bg/223.png 补丁 | 查看 | 原始文档 | blame | 历史
src/enums/pageEnum.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/guard/permissionGuard.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/routes/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/bigScreen/BigEqp-tjt.vue 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/bigScreen/BigEqp.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/bigScreen/BigWorkShop-tjt.vue 736 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/bigScreen/BigWorkShop.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/bigScreen/EqpSplit.vue 1723 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/repair/DryRepairRecords.api.ts 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/repair/DryRepairRecords.data.ts 305 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/repair/DryRepairRecordsList.vue 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/repair/DryRepairRecords_menu_insert.sql 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/repair/components/DryRepairRecordsForm.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/repair/components/DryRepairRecordsModal.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/dry/bg/223.png
src/enums/pageEnum.ts
@@ -1,6 +1,10 @@
export enum PageEnum {
    // basic login path
    BASE_LOGIN = '/login',
  BIG_SCREEN = '/bigScreen',
  BIG_EQP = '/bigEqp',
    // basic home path
    BASE_HOME = '/dashboard/workshop',
    // error page path
src/router/guard/permissionGuard.ts
@@ -12,6 +12,10 @@
import { isOAuth2AppEnv } from '/@/views/sys/login/useLogin';
const LOGIN_PATH = PageEnum.BASE_LOGIN;
const BIG_SCREEN_PATH = PageEnum.BIG_SCREEN;
const BIG_EQP_PATH = PageEnum.BIG_EQP;
//auth2登录路由
const OAUTH2_LOGIN_PAGE_PATH = PageEnum.OAUTH2_LOGIN_PAGE_PATH;
@@ -22,7 +26,7 @@
//update-begin---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------
//update-begin---author:wangshuai ---date:20221111  for: [VUEN-2472]分享免登录------------
const whitePathList: PageEnum[] = [LOGIN_PATH, OAUTH2_LOGIN_PAGE_PATH,SYS_FILES_PATH];
const whitePathList: PageEnum[] = [LOGIN_PATH, OAUTH2_LOGIN_PAGE_PATH,SYS_FILES_PATH,BIG_SCREEN_PATH, BIG_EQP_PATH];
//update-end---author:wangshuai ---date:20221111  for: [VUEN-2472]分享免登录------------
//update-end---author:wangshuai ---date:20220629  for:[issues/I5BG1I]vue3不支持auth2登录------------
src/router/routes/index.ts
@@ -42,7 +42,7 @@
export const BigScreen: AppRouteRecordRaw = {
    path: '/bigScreen',
    name: 'BigScreen',
    component: () => import('/@/views/dry/bigScreen/BigWorkShop.vue'),
    component: () => import('/@/views/dry/bigScreen/BigWorkShop-tjt.vue'),
    meta: {
        title: t('big.screen.workshop'),
    },
@@ -58,7 +58,7 @@
export const BigEqp: AppRouteRecordRaw = {
    path: '/bigEqp',
    name: 'BigEqp',
    component: () => import('/@/views/dry/bigScreen/BigEqp.vue'),
    component: () => import('/src/views/dry/bigScreen/BigEqp-tjt.vue'),
    meta: {
        title: t('big.screen.eqp'),
    },
src/views/dry/bigScreen/BigEqp-tjt.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
<template>
    <dv-full-screen-container>
        <div class="eqpBox">
            <div class="eqpRow">
                <div class="eqpImage" :style="{ 'background-position': position + 'px' }">
          <eqp-split :num="eqpNum"></eqp-split>
          <div style="width: 10px"></div>
          <eqp-split :num="eqpNum2"></eqp-split>
                </div>
            </div>
        </div>
    </dv-full-screen-container>
</template>
<script setup lang="ts">
    import { useFullscreen } from '@vueuse/core'
    import { router } from '/@/router'
    import { onMounted, ref, onUnmounted } from 'vue'
    import { dryEquipment } from '../dataDefine/DryEquipment.data'
  import EqpSplit from "/@/views/dry/bigScreen/EqpSplit.vue";
    const domRef = ref<Nullable<HTMLElement>>(null)
    const { enter, toggle, exit, isFullscreen } = useFullscreen()
    const { toggle: toggleDom } = useFullscreen(domRef)
  const position = ref(1)
    const Timer2 = ref()
    console.log(`output->router.currentRoute.value.params.num `, router.currentRoute.value.query)
    const eqp = ref({} as dryEquipment)
    const eqpNum = ref(router.currentRoute.value.query.num || 0)
  const eqpNum2 = ref(parseInt(router.currentRoute.value.query.num) + 1 || 1)
  var move = true
  function moveImage() {
    if (move) {
      position.value -= 0.3
    } else {
      position.value += 0.3
    }
    if (position.value < -240) {
      move = false
    }
    if (position.value > -1) {
      move = true
    }
  }
    function back() {
        router.back()
    }
    //queryEqp()
    // DOM挂载完成后渲染图表
    onMounted(() => {
        Timer2.value = setInterval(moveImage, 50)
    })
    onUnmounted(() => {
        clearInterval(Timer2.value)
        Timer2.value = null
    })
</script>
<style scoped>
    .eqpBox {
        height: 100%;
    }
    .eqpRow {
    }
    .eqpImage {
        height: 1080px;
        width: 1920px;
        background-image: url(/src/assets/images/dry/bg.png);
        background-repeat: no-repeat;
        color: white;
        /*background-position: 160px 280px; */
        /* background-color: red; */
        background-size: 120%;
        padding: 10px;
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
    }
</style>
src/views/dry/bigScreen/BigEqp.vue
@@ -572,7 +572,7 @@
    import 'echarts-liquidfill'
    import { Icon, IconPicker, SvgIcon } from '/@/components/Icon/index'
    import { defHttp } from '/@/utils/http/axios'
    import { queryById, listAll } from '../api/DryEquipment.api'
    import { queryById } from '../api/DryEquipment.api'
    import { dryEquipment } from '../dataDefine/DryEquipment.data'
    import { useUserStore } from '/@/store/modules/user'
    import { getTenantId, getToken } from '/@/utils/auth'
@@ -1499,7 +1499,8 @@
    }
    function listAllEqp() {
        listAll({ enable: 'Y' })
    let tenantId = getTenantId()
    defHttp.get({ url: '/dry/real/queryAllEqps', params: { tenantId: tenantId,enable: 'Y'  } })
            .then((result) => {
                //console.log(`output->result`, result)
                eqps.value = result
src/views/dry/bigScreen/BigWorkShop-tjt.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,736 @@
<template>
    <dv-full-screen-container>
        <div class="fbg">
            <div class="bgImage">
                <div class="head">
                    <div style="width: 600px; height: 50px"> <dv-decoration-8 style="width: 500px; height: 50px" /></div>
                    <div class="title">
                        <span>{{ title }}</span>
                        <dv-decoration-5 :dur="20" style="margin-top: -40px; width: 700px; height: 80px" />
                    </div>
                    <div style="width: 600px; height: 50px; display: flex; justify-content: end">
                        <dv-decoration-8 :reverse="true" style="width: 500px; height: 50px"
                    /></div>
                </div>
                <div class="body">
                    <div class="humiture">
                        <div style="display: flex; width: 120px">
                            <Icon style="color: #ba9853" icon="mdi:home-temperature-outline" :size="28" />
                            &nbsp;
                            <div style="font-size: 20px; line-height: 26px"> {{ envTemp }} â„ƒ </div>
                        </div>
                        <div style="display: flex">
                            <Icon style="color: #ba9853" icon="wi:humidity" :size="28" />
                            &nbsp;
                            <div style="font-size: 20px; line-height: 26px"> {{ envHum }} %rh </div>
                        </div>
                    </div>
                    <div class="feed">
                        <div style="width: 700px; margin-left: 50px; display: flex; flex-direction: column; height: 950px; justify-content: space-between">
                            <div style="display: flex; flex-wrap: wrap; justify-content: space-between">
                                <dv-border-box7 style="width: 210px; height: 100px; padding: 10px">
                                    <div class="statistics putincolor">
                                        <div class="stat_label font16"> æ€»æŠ•料量 </div>
                                        <div class="stat_value">
                                            {{ originWeight?.toFixed(2) || 0 }}
                                            <span class="font16"> Kg </span>
                                        </div>
                                        <div class="stat_avg">
                                            <div> é¢„计产量 </div>
                                            <div> {{ totalYield?.toFixed(2) || 0 }} kg </div>
                                        </div>
                                    </div>
                                </dv-border-box7>
                                <dv-border-box7 style="width: 210px; height: 100px; padding: 10px">
                                    <div class="statistics putincolor">
                                        <div class="stat_label font16"> ç”µé‡æ¶ˆè€— </div>
                                        <div class="stat_value">
                                            {{ watt?.toFixed(2) || 0 }}
                                            <span class="font16"> Kwh </span>
                                        </div>
                                        <div class="stat_avg">
                                            <div> å¹³å‡ç”µè€— </div>
                                            <div> {{ wattAvg?.toFixed(2) || 0 }} Kwh/kg </div>
                                        </div>
                                    </div>
                                </dv-border-box7>
                                <dv-border-box7 style="width: 210px; height: 100px; padding: 10px">
                                    <div class="statistics putincolor">
                                        <div class="stat_label font16"> è’¸æ±½æ¶ˆè€— </div>
                                        <div class="stat_value">
                                            {{ steam?.toFixed(2) || 0 }}
                                            <span class="font16"> m³ </span>
                                        </div>
                                        <div class="stat_avg">
                                            <div> å¹³å‡æ±½è€— </div>
                                            <div> {{ steamAvg?.toFixed(2) || 0 }} m³/kg </div>
                                        </div>
                                    </div>
                                </dv-border-box7>
                                <!-- <div class="statistics putincolor">
                                    <div class="stat_label font16">预计产量</div>
                                    <div class="stat_value">3000</div>
                                    <div class="font16">
                                        <br/>
                                        Kg
                                    </div>
                                </div> -->
                            </div>
                            <div>
                                <!-- <div class="statistics electroncolor">
                                <div class="stat_label font16">电量消耗</div>
                                <div class="stat_value">500</div>
                                <div class="font16">
                                    <br/>
                                     Kwh
                                </div>
                            </div>
                            <div class="statistics steamcolor">
                                <div class="stat_label font16">蒸汽消耗</div>
                                <div class="stat_value">300</div>
                                <div class="font16">
                                    <br/>
                                    m³
                                </div>
                            </div>
                            <div class="statistics electroncolor">
                                <div class="stat_label font16">平均电耗</div>
                                <div class="stat_value">12</div>
                                <div class="font16">
                                    <br/>
                                    Kwh/kg
                                </div>
                            </div>
                            <div class="statistics steamcolor">
                                <div class="stat_label font16">平均汽耗</div>
                                <div class="stat_value">300</div>
                                <div class="font16">
                                    <br/>
                                    m³/kg
                                </div>
                            </div> -->
                            </div>
                        </div>
                        <!-- <div style="padding-right: 100px;">
                            <div class="statistics">
                                <div class="stat_label font16">干料产量</div>
                                <div class="stat_value">300</div>
                                <div class="font16">
                                    <br/>
                                    kg
                                </div>
                            </div>
                        </div> -->
                    </div>
                    <div class="up">
                        <div v-for="num in eqpNum" :key="num" :class="{ one: num === 1, two: num === 2, three: num === 3, four: num === 4 }">
                            <div class="eqpInfoup" @click="gotoeqp(num - 1)">
                                <div class="eqp-title">
                                    <div class="herb_weight">
                                        <div>{{ realTime.get(eqpCodes[num - 1])?.herbName || '暂无' }}</div>
                                        <div>{{ realTime.get(eqpCodes[num - 1])?.originWeight || 0 }} Kg</div>
                                    </div>
                                    <!-- <div class="eqp-name">{{ eqpMap.get(eqpCodes[num - 1])?.name || '预留' }}</div> -->
                                    <!-- <div class="process"> </div> -->
                                    <Progress
                                        :stroke-color="{
                                            from: '#108ee9',
                                            to: '#87d068',
                                        }"
                                        :percent="parseFloat(realTime.get(eqpCodes[num - 1])?.percent || '0')"
                                        status="active"
                                        trailColor="#2b2b2b2b"
                                        :show-info="false"
                                    />
                                    <div class="eqp-timer">
                                        <div
                                            ><Icon style="color: #1850b7" icon="ic:twotone-water-drop" :size="20" />
                                            {{ realTime.get(eqpCodes[num - 1])?.trendVo?.moisture?.toFixed(1) || '0' }} %
                                        </div>
                                        <div
                                            ><Icon style="color: #873853" icon="fluent:temperature-20-regular" :size="20" />
                                            {{ realTime.get(eqpCodes[num - 1])?.trendVo?.bellowsTemp?.toFixed(0) || '0' }} â„ƒ
                                        </div>
                                        <div
                                            ><Icon style="color: rgb(134 207 106)" icon="gg:sand-clock" :size="20" />
                                            {{ realTime.get(eqpCodes[num - 1])?.totalRemain || 0 }} min
                                        </div>
                                    </div>
                                </div>
                                <div class="eqp-info-up">
                                    <!-- <div class="herb">
                                        <div>{{ realTime.get(eqpCodes[num - 1])?.herbName || '暂无' }}</div>
                                    </div> -->
                                </div>
                                <!-- <div class="weight"><div class="herb">{{ realTime.get(eqpCodes[num - 1])?.originWeight || 0 }} Kg</div></div> -->
                                <div class="weight"
                                    ><div class="herb">
                                        {{ showInfo(realTime.get(eqpCodes[num - 1])) }}
                                    </div></div
                                >
                                <div class="water">
                                    <div class="eqp_num">{{ num }}</div>
                                    <!-- <div class="temp">
                                        <div style="line-height: 28px"><Icon style="color: #1850b7" icon="ic:twotone-water-drop" :size="28" /> </div>
                                        <div class="font">
                                            <span class="value"> {{ realTime.get(eqpCodes[num - 1])?.trendVo?.moisture || '0' }}</span> %
                                        </div>
                                    </div>
                                    <div class="temp">
                                        <div style="line-height: 28px"><Icon style="color: #873853" icon="fluent:temperature-20-regular" :size="30" /> </div>
                                        <div class="font">
                                            <span class="value">{{ realTime.get(eqpCodes[num - 1])?.trendVo?.bellowsTemp || '0' }} </span> â„ƒ
                                        </div>
                                    </div> -->
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="down">
                        <div v-for="num in eqpNum2" :key="num" :class="{ two: num === 1, three: num === 2, four_down: num === 3 }">
                            <div class="eqpInfodown" @click="gotoeqp(num + 3)">
                                <!-- <div class="eqp-info-down">
                                    <div class="herb">{{ realTime.get(eqpCodes[num + 3])?.herbName || '暂无' }}</div>
                                </div>
                                <div class="weight"><div class="herb">{{ realTime.get(eqpCodes[num + 3])?.originWeight || 0 }} Kg </div></div> -->
                                <div class="weight"
                                    ><div class="herb">{{ showInfo(realTime.get(eqpCodes[num + 3])) }}</div></div
                                >
                                <div class="water">
                                    <div class="eqp_num">{{ num - 2 * num + 3 * num + 1 }}</div>
                                    <!-- <div class="temp">
                                        <div style="line-height: 28px">
                                            <Icon style="color: #1850b7" icon="ic:twotone-water-drop" :size="28" />
                                        </div>
                                        <div class="font">
                                            <span class="value">{{ realTime.get(eqpCodes[num + 3])?.trendVo?.moisture || '0' }}</span> %
                                        </div>
                                    </div>
                                    <div class="temp">
                                        <div style="line-height: 28px"><Icon style="color: #873853" icon="fluent:temperature-20-regular" :size="30" /> </div>
                                        <div class="font">
                                            <span class="value">{{ realTime.get(eqpCodes[num + 3])?.trendVo?.bellowsTemp || '0' }}</span> â„ƒ
                                        </div>
                                    </div> -->
                                </div>
                                <div style="height: 40px"></div>
                                <div class="eqp-title">
                                    <div class="herb_weight">
                                        <div>{{ realTime.get(eqpCodes[num + 3])?.herbName || '暂无' }}</div>
                                        <div>{{ realTime.get(eqpCodes[num + 3])?.originWeight || 0 }} Kg</div>
                                    </div>
                                    <Progress
                                        :stroke-color="{
                                            from: '#108ee9',
                                            to: '#87d068',
                                        }"
                                        :percent="parseFloat(realTime.get(eqpCodes[num + 3])?.percent || '0')"
                                        status="active"
                                        trailColor="#2b2b2b2b"
                                        :show-info="false"
                                    />
                                    <!-- <div class="eqp-name">50%</div> -->
                                    <div class="eqp-timer">
                                        <div
                                            ><Icon style="color: #1850b7" icon="ic:twotone-water-drop" :size="20" />
                                            {{ realTime.get(eqpCodes[num + 3])?.trendVo?.moisture?.toFixed(1) || '0' }} %
                                        </div>
                                        <div
                                            ><Icon style="color: #873853" icon="fluent:temperature-20-regular" :size="20" />
                                            {{ realTime.get(eqpCodes[num + 3])?.trendVo?.bellowsTemp?.toFixed(0) || '0' }} â„ƒ
                                        </div>
                                        <!-- <div><Icon style="color: rgb(42 154 234)" icon="mdi:clock-outline" :size="20" />
                                             {{realTime.get(eqpCodes[num + 3])?.dryTime || 0}} min
                                        </div> -->
                                        <div
                                            ><Icon style="color: rgb(134 207 106)" icon="gg:sand-clock" :size="20" />
                                            {{ realTime.get(eqpCodes[num + 3])?.totalRemain || 0 }} min
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="footer">
                        <div>{{ nowDate }}</div>
                        <div>{{ nowTime }}</div>
                    </div>
                </div>
            </div>
        </div>
        <div style="position: absolute; width: 10px; height: 10px; border: 1px red solid; z-index: 1000"> </div>
    </dv-full-screen-container>
</template>
<script setup lang="ts">
    import { Progress } from 'ant-design-vue'
    import { onMounted, ref, onUnmounted } from 'vue'
    import { Icon, IconPicker, SvgIcon } from '/@/components/Icon/index'
    import { listAll } from '../api/DryEquipment.api'
    import { dryEquipment } from '../dataDefine/DryEquipment.data'
    import { router } from '/@/router'
    import { defHttp } from '/@/utils/http/axios'
    import { useUserStore } from '/@/store/modules/user'
    import { setAuthCache } from '/@/utils/auth'
    import { TENANT_ID } from '/@/enums/cacheEnum'
    const eqpNum = ref(4)
    const eqpNum2 = ref(3)
    const eqpMap = ref(new Map())
    const eqpCodes = ref(['GM001', 'GM002', 'GM003', 'GM004', 'GM005', 'GM006', 'GM007'])
    const eqps = ref([] as dryEquipment[])
    const title = ref('智能干燥车间')
    const userStore = useUserStore()
    const tenantId = ref(router.currentRoute.value.query.tenantId | userStore.getTenant)
    setAuthCache(TENANT_ID, tenantId.value)
    console.log('tenantId1', router.currentRoute.value.query.tenantId)
    console.log('tenantId2', userStore.getTenant)
    const envHum = ref(0)
    const envTemp = ref(0)
    const originWeight = ref(0)
    const totalYield = ref(0)
    const dryReduce = ref(0)
    const steam = ref(0)
    const watt = ref(0)
    const steamAvg = ref(0)
    const wattAvg = ref(0)
    console.log(userStore.dictItems.title)
    userStore.dictItems.title?.forEach((element) => {
        if (element.value === 'bigscreentitle') {
            title.value = element.text
        }
    })
    const Timer = ref()
    const realTime = ref(new Map())
    const nowTime = ref()
    const nowDate = ref()
    function listAllEqp() {
        defHttp
            .get({ url: '/dry/real/queryAllEqps', params: { tenantId: tenantId.value, enable: 'Y' } })
            .then((result) => {
                console.log(`output->result`, result)
                eqps.value = result
                result.forEach((item) => {
                    eqpMap.value.set(item.code, item)
                })
                updateRealTime()
            })
            .catch((err) => {
                console.log(`output->err`, err)
            })
    }
    function updateRealTime() {
        //console.log(`output->定时刷新数据`)
        queryWorkShopStatistics()
        eqps.value.forEach((item) => {
            queryRealTime(item)
        })
    }
    function queryWorkShopStatistics() {
        defHttp.get({ url: '/dry/real/workshopStatistics', params: { tenantid: tenantId.value } }).then((res) => {
            console.log(`output->res`, res)
            steam.value = res.steam
            watt.value = res.watt
            envHum.value = res.envHum
            envTemp.value = res.envTemp
            originWeight.value = res.originWeight
            totalYield.value = res.yield
            dryReduce.value = res.reduce
            if (res.reduce > 0) {
                steamAvg.value = res.steam / res.reduce
                wattAvg.value = res.watt / res.reduce
            }
        })
    }
    function queryRealTime(eqp: dryEquipment) {
        let eqpCode = eqp.code
        let queryRealTimeUrl = '/dry/real/getRealTimeData'
        defHttp.get({ url: queryRealTimeUrl, params: { tenantid: tenantId.value, machineid: eqpCode } }).then((res) => {
            if (res && res.trendVo) {
                res.tempValue = [res.windTemp, 100]
                res.totalRemain = res.remain
                if (res.detailList && res.detailList.length > 0) {
                    // å¹²ç‡¥å‰©ä½™æ—¶é—´=工单预计剩余-(当前干燥时间-最后一次记录干燥时间)
                    res.totalRemain = res.remain - (res.dryTime - res.detailList[res.detailList.length - 1].totalTime)
                } else {
                    res.totalRemain = res.remain - res.dryTime
                }
                if (res.totalRemain < 0) {
                    res.totalRemain = 0
                }
                res.percent = ((res.dryTime / (res.dryTime + res.totalRemain)) * 100).toFixed(2)
            } else {
                res = {
                    tempValue: [0, 100],
                    percent: 0,
                    mois: [],
                }
            }
            realTime.value.set(eqp.code, res)
        })
    }
    function gotoeqp(num) {
        console.log('跳转机台', num)
        if (num < eqpCodes.value.length) {
            router.push({ path: '/bigEqp', query: { num: num } })
        }
    }
    function getNowTime() {
        var date = new Date()
        nowDate.value =
            date.getFullYear() +
            '/' +
            (date.getMonth() < 9 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) +
            '/' +
            (date.getDay() < 10 ? '0' + date.getDay() : date.getDay())
        nowTime.value =
            '' +
            (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) +
            ':' +
            (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
    }
    function showInfo(data) {
        return data ? (data.fault ? data.fault : data.warning ? data.warning : data.level ? data.level : '空闲') : '空闲'
    }
    getNowTime()
    listAllEqp()
    onMounted(() => {
        Timer.value = setInterval(updateRealTime, 3000)
        setInterval(getNowTime, 10000)
    })
    onUnmounted(() => {
        clearInterval(Timer.value)
        Timer.value = null
    })
</script>
<style scoped>
    .fbg {
        height: 1080px;
        width: 1920px;
        background-image: url(/src/assets/images/dry/bg/bg5.png);
        background-repeat: no-repeat;
    }
    .bgImage {
        height: 1080px;
        width: 1920px;
        background-image: url(/src/assets/images/dry/bg/223.png);
        background-repeat: no-repeat;
        background-size: 104%;
        background-position: 0px 257px;
    }
    .head {
        display: flex;
        align-content: center;
        justify-content: center;
    }
    .body {
        height: 980px;
        width: 100%;
        margin-top: -100px;
        font-size: 20px;
    }
    .title {
        height: 200px;
        padding: 20px;
        font-size: 30px;
        font-weight: bold;
        text-align: center;
        color: white;
    }
    .humiture {
        height: 0px;
        justify-content: center;
        color: white;
        display: flex;
    }
    .feed {
        display: flex;
        height: 0px;
        color: gray;
        padding-top: 20px;
        justify-content: space-between;
    }
    .up {
        display: flex;
        align-content: center;
        justify-content: flex-start;
    }
    .down {
        padding-left: 554px;
        margin-top: -760px;
        display: flex;
        align-content: center;
        justify-content: flex-start;
    }
    .eqpInfoup {
        width: 304px;
        height: 400px;
    position: relative;
        display: flex;
        flex-direction: column;
    }
    .eqpInfodown {
        width: 300px;
        height: 430px;
    position: relative;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
    }
    .one {
        margin: 278px 10px;
    }
    .two {
        margin: 208px 23px;
    }
    .three {
        margin: 110px 158px;
    }
    .four {
        margin: 16px 10px;
    }
    .four_down {
        margin: 4px 74px;
    }
    .eqp-title {
        height: 125px;
        width: 100%;
        padding: 10px 20px;
    }
    .eqp-name {
        line-height: 30px;
        text-align: center;
        color: white;
        margin-top: -30px;
    }
    .eqp-timer {
        line-height: 30px;
        text-align: center;
        color: white;
        margin-top: 6px;
        justify-content: space-between;
        display: flex;
    }
    .eqp-name-down {
        line-height: 40px;
        text-align: center;
        color: white;
    }
    .process {
        width: 50%;
        height: 100%;
        overflow: hidden;
        border-radius: 20px;
        background: #3f4c6b;
    }
    .eqp-info-up {
        flex: 1;
        padding-top: 108px;
        display: flex;
    }
    .weight {
        flex: 1;
        display: flex;
        margin-left: 46px;
        font-size: 20px;
    }
    .eqp-info-down {
        flex: 1;
        padding-top: 70px;
        display: flex;
    }
    .herb {
        height: 32px;
        background: #3f4c6b;
        color: white;
        line-height: 30px;
        padding: 0 10px;
    }
    .water {
        height: 120px;
        width: 110px;
        margin: 58px 158px;
        display: flex;
        flex-wrap: wrap;
    }
    .temp {
        display: flex;
    }
    .font {
        line-height: 26px;
    }
    .footer {
        height: 160px;
        display: flex;
        padding: 10px 20px;
        font-size: 30px;
        flex-direction: column-reverse;
        align-items: flex-end;
        color: white;
        line-height: 40px;
        margin-top: -150px;
    }
    :deep() .progress {
        padding: 25px 25px;
        width: 360px;
        display: flex;
    }
    :deep() .ant-progress-bg {
        height: 25px !important;
    }
    :deep() .ant-progress-inner {
        background-color: rgb(197 197 197 / 84%) !important;
    }
    .statistics {
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
    }
    .stat_label {
        width: 45px;
    }
    .stat_value {
        font-size: 28px;
    }
    .herb_weight {
        padding: 0 10px;
        color: white;
        display: flex;
        justify-content: space-between;
    }
    .eqp_num {
        font-weight: bold;
        width: 40px;
        height: 40px;
        background: #a0782e;
        border-radius: 50px;
        /* text-align: center; */
        font-size: 23px;
        color: white;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .putincolor {
        color: antiquewhite;
    }
    .electroncolor {
        color: aquamarine;
    }
    .steamcolor {
        color: sandybrown;
    }
    .font16 {
        font-size: 16px;
    }
    .stat_avg {
        width: 100%;
        font-size: 16px;
        display: flex;
        color: rgb(176, 176, 176);
        justify-content: space-between;
        border-top: 1px solid;
        margin-top: 6px;
    }
  @keyframes flowLight {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
  }
  @keyframes flowLightUp {
    0% { background-position: -200% 0; }
    100% { background-position: 200% 0; }
  }
    .up .eqp-title::after {
    content: "";
    position: absolute;
    left: 90px;
    top: 34%;
    width: 65px;
    height: 6px;
    background: repeating-linear-gradient(90deg, #5596c7 0 5px, transparent 5px 10px);
    transform: rotate(105deg) translateY(-107%);
    background-size: 200% 100%;
    animation: flowLightUp 10s infinite linear;
    }
  .down .eqp-title::after {
    content: "";
    position: absolute;
    left: 99px;
    top: 57%;
    width: 128px;
    height: 6px;
    background: repeating-linear-gradient(90deg, #5596c7 0 5px, transparent 5px 10px);
    transform: rotate(105deg) translateY(-107%);
    background-size: 200% 100%;
    animation: flowLight 15s infinite linear;
  }
</style>
src/views/dry/bigScreen/BigWorkShop.vue
@@ -285,12 +285,19 @@
    import { router } from '/@/router'
    import { defHttp } from '/@/utils/http/axios'
    import { useUserStore } from '/@/store/modules/user'
  import {setAuthCache} from "/@/utils/auth";
  import {TENANT_ID} from "/@/enums/cacheEnum";
    const eqpNum = ref(4)
    const eqpMap = ref(new Map())
    const eqpCodes = ref(['GM001', 'GM002', 'GM003', 'GM004', 'GM005', 'GM006', 'GM007', 'GM008'])
    const eqps = ref([] as dryEquipment[])
    const title = ref('智能干燥车间')
    const userStore = useUserStore()
  const tenantId = ref(router.currentRoute.value.query.tenantId | userStore.getTenant)
  setAuthCache(TENANT_ID, tenantId.value)
  console.log('tenantId1', router.currentRoute.value.query.tenantId)
  console.log('tenantId2', userStore.getTenant)
    const envHum = ref(0)
    const envTemp = ref(0)
    const originWeight = ref(0)
@@ -314,7 +321,7 @@
    const nowDate = ref()
    function listAllEqp() {
        listAll({ enable: 'Y' })
    defHttp.get({ url: '/dry/real/queryAllEqps', params: { tenantId: tenantId.value,enable: 'Y'  } })
            .then((result) => {
                console.log(`output->result`, result)
                eqps.value = result
@@ -340,8 +347,8 @@
    }
    function queryWorkShopStatistics() {
        let tenantId = userStore.getTenant
        defHttp.get({ url: '/dry/real/workshopStatistics', params: { tenantid: tenantId } }).then((res) => {
        defHttp.get({ url: '/dry/real/workshopStatistics', params: { tenantid: tenantId.value } }).then((res) => {
            console.log(`output->res`, res)
            steam.value = res.steam
            watt.value = res.watt
@@ -358,17 +365,19 @@
    }
    function queryRealTime(eqp: dryEquipment) {
        let tenantId = userStore.getTenant
        let eqpCode = eqp.code
        let queryRealTimeUrl = '/dry/real/getRealTimeData'
        defHttp.get({ url: queryRealTimeUrl, params: { tenantid: tenantId, machineid: eqpCode } }).then((res) => {
        defHttp.get({ url: queryRealTimeUrl, params: { tenantid: tenantId.value, machineid: eqpCode } }).then((res) => {
            if (res && res.trendVo) {
                res.tempValue = [res.windTemp, 100]
                res.totalRemain = res.remain
                if (res.detailList) {
                if (res.detailList && res.detailList.length > 0) {
                    // å¹²ç‡¥å‰©ä½™æ—¶é—´=工单预计剩余-(当前干燥时间-最后一次记录干燥时间)
                    res.totalRemain = res.remain - (res.dryTime - res.detailList[res.detailList.length - 1].totalTime)
                }
                } else {
          res.totalRemain = res.remain - res.dryTime
        }
                if (res.totalRemain < 0) {
                    res.totalRemain = 0
                }
src/views/dry/bigScreen/EqpSplit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1723 @@
<template>
                    <div class="leftEqp">
                        <div class="leftTop">
              <dv-border-box-7 >
                <div style="display:flex;justify-content: center;flex-wrap: wrap;align-content: flex-start;">
              <div style="display: flex;">
                            <div class="leftTop0">
                <div>
                  <div class="mainInfo" style="padding-top: 20px;padding-left:80px;font-size: 26px">{{ eqp?.name }}</div>
                <dv-decoration-8 style="width:300px;height:50px;padding-top: 0px" />
                </div>
                <div style="display: flex; width: 500px; justify-content: space-between">
                <div style="padding-top: 20px; width: 150px; height: 160px">
                  <dv-border-box-7 style="padding: 10px">
                    <div style="display: flex; flex-direction: column;justify-content: space-between; height: 100%">
                  <div style="font-size: 20px">含水率</div>
                    <div style="font-size: 35px; text-align: center"> {{ realData?.trendVo?.moisture || 0 }} <span style="font-size: 20px">%</span></div>
                  <div style="font-size: 16px; display: flex;justify-content: space-between"> <div>{{ realData?.initial || 0  }} %</div> <div> -> </div> <div>{{ realData?.target || 0 }} %</div></div>
                    </div>
                  </dv-border-box-7>
                </div>
                <div style="padding-top: 20px; width: 150px; height: 160px">
                  <dv-border-box-7 style="padding: 10px; ">
                    <div style="display: flex; flex-direction: column;justify-content: space-between; height: 100%">
                  <div style="font-size: 20px">重量</div>
                  <div style="font-size: 35px; text-align: center"> {{ realData?.trendVo?.weight || 0 }} <span style="font-size: 20px">kg</span></div>
                  <div style="font-size: 16px"> åˆå§‹ {{ realData?.originWeight }} kg</div>
                    </div>
                  </dv-border-box-7>
                </div>
                  <div style="padding-top: 20px; width: 150px; height: 160px">
                    <dv-border-box-7 style="padding: 10px">
                      <div style="display: flex; flex-direction: column;justify-content: space-between; height: 100%">
                      <div style="font-size: 20px">热风</div>
                      <div style="font-size: 35px; text-align: center"> {{ realData?.trendVo?.bellowsTemp || 0 }} <span style="font-size: 20px">°C</span></div>
                      <div style="font-size: 16px"> è®¾ç½® {{ realData?.windTemp || 0 }} Â°C</div>
                      </div>
                    </dv-border-box-7>
                  </div>
                </div>
                <div class="eqp-title" style="width:500px; font-size: 24px;padding-top: 20px">
                  <div style="position: absolute; z-index: 999;font-size: 22px; padding-left: 26px; padding-top: 7px" > å¹²ç‡¥ {{  realData?.dryTime }} Min</div>
                  <Progress
                    :stroke-color="{
                                            from: '#108ee9',
                                            to: '#87d068',
                                        }"
                    :percent="parseFloat((realData?.dryTime/realData?.totalTime)*100 || '0')"
                    status="active"
                    trailColor="#2b2b2b2b"
                    :show-info="false"
                  />
                  <div class="eqp-timer" style="display: flex; justify-content: space-between">
                    <div>
                     é¢„计 {{  realData?.totalTime }} Min
                    </div>
                    <div>
                     å‰©ä½™ {{ realData?.totalRemain | 0 }} Min
                    </div>
                  </div>
                </div>
                                <div class="outDiv eqpStatus">
                                    <div
                                        style="
                                            font-size: 26px;
                                            color: white;
                                            background-color: #1595ea;
                                            width: 180px;
                                            line-height: 60px;
                                            text-align: center;
                                            border-radius: 10px;
                                            font-weight: bold;
                                        "
                                    >
                                    </div>
                                </div>
                            </div>
                <div style="width:420px; height: 400px; padding-top: 20px;padding-left: 20px">
                  <div :id="'moisChart'+props.num" style="width: 420px; height: 380px"></div>
                </div>
              </div>
              <dv-decoration-11 style="width:360px;height:70px;font-size: 26px;">{{ realData?.herbName || '暂无' }}</dv-decoration-11>
              <div style="width: 100%; height: 440px">
              <div class="ganzaoji" @click="showFault" :style="{ 'background-image': 'url(' + getStatusImageUrl(statusGif) + ')' }">
                <div v-show="zuoqianjiting" class="error-div" style=" top:309px; left:418px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style="width: 70px;">
                    &nbsp;&nbsp;左前急停
                  </div>
                </div>
                <div v-show="shebeijiting" class="error-div"  style=" top:111px; left:484px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 106px;">
                    &nbsp;&nbsp;设备急停(总)
                  </div>
                </div>
                <div v-show="chuliaojiting" class="error-div"  style=" top:300px; left:129px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 70px;">
                    &nbsp;&nbsp;出料急停
                  </div>
                </div>
                <div v-show="mianbanjiting" class="error-div"  style=" top:258px; left:659px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 70px;">
                    &nbsp;&nbsp;面板急停
                  </div>
                </div>
                <div v-show="fengxiangsheng" class="error-div"  style=" top:294px; left:517px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 86px;">
                    &nbsp;&nbsp;风箱升异常
                  </div>
                </div>
                <div v-show="fengxiangjiang" class="error-div"  style=" top:319px; left:517px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 86px;">
                    &nbsp;&nbsp;风箱降异常
                  </div>
                </div>
                <div v-show="fengjiguoliu" class="error-div"  style=" top:335px; left:655px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 70px;">
                    &nbsp;&nbsp;风机过流
                  </div>
                </div>
                <div v-show="guntongsheng" class="error-div"  style=" top:198px; left:517px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 86px;">
                    &nbsp;&nbsp;滚筒升异常
                  </div>
                </div>
                <div v-show="guntongjiang" class="error-div"  style=" top:223px; left:517px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 86px;">
                    &nbsp;&nbsp;滚筒降异常
                  </div>
                </div>
                <div v-show="guntongguoliu" class="error-div"  style=" top:209px; left:642px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 70px;">
                    &nbsp;&nbsp;滚筒过流
                  </div>
                </div>
                <div v-show="wendubaojing" class="error-div"  style=" top:234px; left:659px">
                  <div class="blingbling error-marker" ></div>
                  <div class="error-msg" style=" width: 70px;">
                    &nbsp;&nbsp;温度报警
                  </div>
                </div>
                <div v-show="zuoqianmen" class="error-div"  style=" top:388px; left:415px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 80px;">
                    &nbsp;&nbsp;左前门报警
                  </div>
                </div>
                <div v-show="zuohoumen" class="error-div"  style=" top:367px; left:587px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 80px;">
                    &nbsp;&nbsp;左后门报警
                  </div>
                </div>
                <div v-show="youqianmen" class="error-div"  style=" top:388px; left:284px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 80px;">
                    &nbsp;&nbsp;右前门报警
                  </div>
                </div>
                <div v-show="youhoumen" class="error-div"  style=" top:367px; left:478px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 80px;">
                    &nbsp;&nbsp;右后门报警
                  </div>
                </div>
                <div v-show="guntongbuzaigaowei" class="error-div"  style=" top:173px; left:517px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 100px;">
                    &nbsp;&nbsp;滚筒不在高位
                  </div>
                </div>
                <div v-show="fengxiangbuzaigaowei" class="error-div"  style=" top:269px; left:517px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 100px;">
                    &nbsp;&nbsp;风箱不在高位
                  </div>
                </div>
                <div v-show="fengxiangbuzaidiwei" class="error-div"  style=" top:343px; left:517px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 100px;">
                    &nbsp;&nbsp;风箱不在低位
                  </div>
                </div>
                <div v-show="jiareweichuanganqi" class="error-div"  style=" top:283px; left:642px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;加热位传感器报警
                  </div>
                </div>
                <div v-show="zuoqianfengxianggaowei" class="error-div"  style=" top:334px; left:362px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;左前风箱不在高位
                  </div>
                </div>
                <div v-show="zuoqianfengxiangdiwei" class="error-div"  style=" top:334px; left:362px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;左前风箱不在低位
                  </div>
                </div>
                <div v-show="zuohoufengxianggaowei" class="error-div"  style=" top:309px; left:642px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;左后风箱不在高位
                  </div>
                </div>
                <div v-show="zuohoufengxiangdiwei" class="error-div"  style=" top:309px; left:642px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;左后风箱不在低位
                  </div>
                </div>
                <div v-show="youqianfengxianggaowei" class="error-div"  style=" top:272px; left:300px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;右前风箱不在高位
                  </div>
                </div>
                <div v-show="youqianfengxiangdiwei" class="error-div"  style=" top:272px; left:300px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;右前风箱不在低位
                  </div>
                </div>
                <div v-show="youhoufengxianggaowei" class="error-div"  style=" top:246px; left:506px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;右后风箱不在高位
                  </div>
                </div>
                <div v-show="youhoufengxiangdiwei" class="error-div"  style=" top:246px; left:506px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;右后风箱不在低位
                  </div>
                </div>
                <div v-show="zuoqianguntongdiwei" class="error-div"  style=" top:175px; left:358px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;左前滚筒不在低位
                  </div>
                </div>
                <div v-show="zuohouguntongdiwei" class="error-div"  style=" top:158px; left:643px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;左后滚筒不在低位
                  </div>
                </div>
                <div v-show="youqianguntongdiwei" class="error-div"  style=" top:150px; left:268px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;右前滚筒不在低位
                  </div>
                </div>
                <div v-show="youhouguntongdiwei" class="error-div"  style=" top:135px; left:506px">
                  <div class="blingbling warn-marker" ></div>
                  <div class="warn-msg" style=" width: 126px;">
                    &nbsp;&nbsp;右后滚筒不在低位
                  </div>
                </div>
              </div>
              </div>
                  <div style="display: flex; justify-content: space-between; align-items: center; width: 100%; padding: 0 20px; font-size: 20px;">
                    <div>电能消耗: {{realData?.watt | 0}} Kwh</div>
              <dv-decoration-7 style="width:300px;height:80px;font-size: 26px;">{{ statusTxt }}</dv-decoration-7>
                    <div>蒸汽消耗: {{realData?.steam | 0}} m³</div>
                  </div>
                </div>
            </dv-border-box-7>
                        </div>
                    </div>
</template>
<script setup lang="ts">
    import { useFullscreen } from '@vueuse/core'
    import { BorderBox7 as DvBorderBox7 } from '@kjgl77/datav-vue3'
    import { router } from '/@/router'
    import { onMounted, ref, onUnmounted } from 'vue'
    import { Progress } from 'ant-design-vue'
    import * as echarts from 'echarts'
    import 'echarts-liquidfill'
    import { Icon, IconPicker, SvgIcon } from '/@/components/Icon/index'
    import { defHttp } from '/@/utils/http/axios'
    import { queryById, listAll } from '../api/DryEquipment.api'
    import { dryEquipment } from '../dataDefine/DryEquipment.data'
    import { useUserStore } from '/@/store/modules/user'
    import { getTenantId, getToken } from '/@/utils/auth'
  // å£°åä»Žä¸Šçº§ä¼ é€’的参数
  const props = defineProps({
    num: {
      type: Number,
      default: 0,
    },
  })
    const domRef = ref<Nullable<HTMLElement>>(null)
    const { enter, toggle, exit, isFullscreen } = useFullscreen()
    const { toggle: toggleDom } = useFullscreen(domRef)
    const Timer = ref()
  const isError = ref(false)
  const isWarning = ref(false)
    const eqps = ref([] as dryEquipment[])
    const eqp = ref({} as dryEquipment)
  console.log('props.num', props.num)
    const eqpNum = ref(props.num || 0)
    const userStore = useUserStore()
    const realData = ref({})
    const standard = ref({
        xiaolv: 220,
        xlMin: 200,
        zhengqi: 50,
        zqMin: 45,
        dian: 8,
        dMin: 7.5,
    })
    const position = ref(1)
    //realData.value.tempValue = [0, 100]
    realData.value.mois = [0.5, 0.35, 0.2]
    statusGif = 'tmrefeng2'
    realData.value.herbImage = 'yaocai1.png'
    var moisChart: echarts.ECharts
  //----------------error----------------
  const shebeijiting = ref(false)
  const chuliaojiting = ref(false)
  const zuoqianjiting = ref(false)
  const mianbanjiting = ref(false)
  const fengxiangsheng = ref(false)
  const fengxiangjiang = ref(false)
  const fengjiguoliu = ref(false)
  const guntongsheng = ref(false)
  const guntongjiang = ref(false)
  const guntongguoliu = ref(false)
  const wendubaojing = ref(false)
  //--------------warning------------
  const zuoqianmen = ref(false)
  const zuohoumen = ref(false)
  const youqianmen = ref(false)
  const youhoumen = ref(false)
  const guntongbuzaigaowei = ref(false)
  const fengxiangbuzaigaowei = ref(false)
  const fengxiangbuzaidiwei = ref(false)
  const jiareweichuanganqi = ref(false)
  const zuoqianfengxianggaowei = ref(false)
  const zuohoufengxianggaowei = ref(false)
  const youqianfengxianggaowei = ref(false)
  const youhoufengxianggaowei = ref(false)
  const zuoqianfengxiangdiwei = ref(false)
  const zuohoufengxiangdiwei = ref(false)
  const youqianfengxiangdiwei = ref(false)
  const youhoufengxiangdiwei = ref(false)
  const zuoqianguntongdiwei = ref(false)
  const zuohouguntongdiwei = ref(false)
  const youqianguntongdiwei = ref(false)
  const youhouguntongdiwei = ref(false)
    function initCharts() {
        let domId = 'moisChart'+props.num
        let chartDom: HTMLElement = document.getElementById(domId) as HTMLElement
        moisChart = echarts.init(chartDom)
        const option = {
            color: ['green', 'red'],
            title: {
                text: '含水率/温度趋势',
                textStyle: {
                    color: '#fff',
                    fontSize: 20,
                },
            },
            tooltip: {
                trigger: 'axis',
            },
            grid: {
                left: 50,
                right: 70,
                top: 50,
                bottom: 60,
            },
            legend: {
                right: 60,
                textStyle: {
                    color: '#fff',
          fontSize: 20,
                },
            },
            // toolbox: {
            //     show: true,
            //     feature: {
            //         dataZoom: {
            //             yAxisIndex: 'none',
            //         },
            //         dataView: { readOnly: false },
            //         magicType: { type: ['line', 'bar'] },
            //         restore: {},
            //         saveAsImage: {},
            //     },
            // },
            xAxis: {
                type: 'value',
                axisLabel: {
                    color: '#fff',
          fontSize: 17,
                },
                //boundaryGap: false,
                // data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
                min: 0,
                max: function (value) {
                    if (value.max < 100) {
                        return 100
                    } else {
                        return value.max
                    }
                },
                splitLine: {
                    lineStyle: {
                        type: 'dashed',
                        color: ['#8d8d8d'],
                    },
                },
            },
            yAxis: {
                type: 'value',
                boundaryGap: ['10%', '10%'],
                axisLabel: {
                    color: '#fff',
          fontSize: 17,
                },
                splitLine: {
                    lineStyle: {
                        type: 'dashed',
                        color: ['#8d8d8d'],
                    },
                },
                // min: 0,
                // max: function (value) {
                //     if (value.max < 100) {
                //         return 100
                //     } else {
                //         return value.max
                //     }
                // },
            },
            // yAxis: {
            //     type: 'value',
            //     axisLabel: {
            //         formatter: '{value} Â°C',
            //     },
            // },
            series: [
                {
                    name: '含水率',
                    type: 'line',
                    smooth: true,
                    symbol: 'none',
                    data: [
                    ],
                    lineStyle: {
                        width: 1,
                    },
                    markLine: {
                        data: [{ type: 'average', name: 'Avg' }],
                    },
                    areaStyle: {
                        opacity: 0.2,
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            {
                                offset: 0,
                                color: 'rgb(128, 255, 165)',
                            },
                            {
                                offset: 1,
                                color: 'rgb(1, 191, 236)',
                            },
                        ]),
                    },
                },
                {
                    name: '温度',
                    type: 'line',
                    smooth: true,
                    symbol: 'none',
                    data: [
                    ],
                    lineStyle: {
                        width: 1,
                    },
                    areaStyle: {
                        opacity: 0.2,
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            {
                                offset: 0,
                                color: 'rgb(255, 0, 135)',
                            },
                            {
                                offset: 1,
                                color: 'rgb(135, 0, 157)',
                            },
                        ]),
                    },
                    // markLine: {
                    //     data: [
                    //         { type: 'average', name: 'Avg' },
                    //         [
                    //             {
                    //                 symbol: 'none',
                    //                 x: '90%',
                    //                 yAxis: 'max',
                    //             },
                    //             {
                    //                 symbol: 'circle',
                    //                 label: {
                    //                     position: 'start',
                    //                     formatter: 'Max',
                    //                 },
                    //                 type: 'max',
                    //                 name: '最高点',
                    //             },
                    //         ],
                    //     ],
                    // },
                },
            ],
        }
        option && moisChart.setOption(option)
    }
    // åŠ¨æ€è¯»å–å›¾ç‰‡
    function getStatusImageUrl(name: string) {
    //
    if (isWarning.value || isError.value) {
      return new URL(`/src/assets/images/dry/ganzaoji-x.png`, import.meta.url).href
    } else if (name =='zanting') {
            return new URL(`/src/assets/images/dry/${name}.png`, import.meta.url).href
        } else {
            return new URL(`/src/assets/images/dry/${name}.gif`, import.meta.url).href
        }
    }
    function listAllEqp() {
    let tenantId = getTenantId()
    defHttp.get({ url: '/dry/real/queryAllEqps', params: { tenantId: tenantId,enable: 'Y'  } })
            .then((result) => {
                //console.log(`output->result`, result)
                eqps.value = result
                // result.forEach((item) => {
                //     eqpCodes.push(item.code)
                // })
                queryRealTime()
                setTimeout(initCharts, 500)
            })
            .catch((err) => {
                //console.log(`output->err`, err)
            })
    }
    var num = eqpNum.value
    function changeEqp() {
        //console.log("changeEqp::",eqps.value.length);
        num++
        if (eqps.value.length > 0) {
            var i = num % eqps.value.length
            //eqp.value = eqps.value[i]
            //  console.log("777",i);
            eqpNum.value = i
            //console.log("888",eqp.value);
            queryRealTime()
            //setTimeout(initCharts, 500)
        }
    }
    // function queryEqpsReal() {
    //     if (eqps.value.length > 0) {
    //         var i = num%eqps.value.length
    //         eqp.value = eqps[i]
    //         console.log("777",i);
    //         console.log("888",eqp.value);
    //         queryRealTime()
    //         //setTimeout(initCharts, 500)
    //     }
    //     num ++;
    // }
    var shangliaoFlag = false
    var statusGif = 'tmrefeng2'
    var statusTxt = '正在干燥'
    function chaiwangban() {
        statusGif = 'chaiwangban-1'
        setTimeout(shangliao, 7000)
    }
  function showFault () {
    console.log('showFault')
    router.push({ path: '/bigFault', query: {  num: num } })
  }
    function shangliao() {
        statusGif = 'shangliao-N'
        setTimeout(() => {
            statusGif = 'zhuangwangban'
            setTimeout(() => {
                statusGif = 'guanmen1'
                setTimeout(() => {
                    shangliaoFlag = false
                }, 4000)
            }, 7000)
        }, 15000)
    }
    function queryRealTime() {
        if (eqp.value) {
            eqp.value = eqps.value[eqpNum.value]
            // console.log("888",eqp.value);
            let tenantId = getTenantId()
            let eqpCode = eqp.value.code
            let queryRealTimeUrl = '/dry/real/getRealTimeData'
            defHttp.get({ url: queryRealTimeUrl, params: { tenantid: tenantId, machineid: eqpCode } }).then((res) => {
                if (res && res.trendVo) {
                    //console.log(`output->re11s`, res)
                    //    res.tempValue = [res.windTemp, 100]
                    //res.percent = ((res.dryTime / res.et) * 100).toFixed(2)
                    /**水滴图含水量 */
                    res.mois = [
                        (res.trendVo.moisture / 100).toFixed(2),
                        (res.trendVo.moisture / 100 / 1.5).toFixed(2),
                        (res.trendVo.moisture / 100 / 3).toFixed(2),
                    ]
                    /**温度环形图 */
                    /**风机频率环形图 */
                    // if (fanFreqChart) {
                    //     fanFreqChart.setOption({
                    //         series: [
                    //             {
                    //                 data: [
                    //                     {
                    //                         value: res.trendVo.fanFrequency,
                    //                     },
                    //                 ],
                    //             },
                    //         ],
                    //     })
                    // }
                    /**干燥进度、走势与阶段效率和阶段消耗 */
                    if (res && res.detailList) {
                        var progressSeries = []
                        var zhengQiXiaoHao = []
                        var dianNengXiaoHao = []
                        var ganZaoXiaoLv = []
                        var totalTime = 0
                        var beforeWeight = 0
                        res.moisList = []
                        beforeWeight = res.originWeight
                        //console.log(`output->res`, res)
                        res.detailList.forEach((item) => {
                            //console.log(`output->bef`, beforeWeight)
                            //console.log(`output->cur`, item.weight)
                            res.moisList.push([item.totalTime, item.moisture])
                            // console.log(`output->totalTime,item.totalTime`, totalTime, item.totalTime)
                            var curDryTime = item.totalTime - totalTime
                            if (curDryTime > 0) {
                                progressSeries.push({
                                    name: item.moisture,
                                    type: 'bar',
                                    stack: 'total',
                                    label: {
                                        show: true,
                                    },
                                    emphasis: {
                                        focus: 'series',
                                    },
                                    data: [item.totalTime - totalTime],
                                })
                                ganZaoXiaoLv.push([curDryTime / 2 + totalTime, (((beforeWeight - item.weight) / curDryTime) * 60).toFixed(1)])
                                totalTime = item.totalTime
                            }
                            beforeWeight = item.weight
                        })
                        if (res.remain) {
                            if (res.dryTime - totalTime > 0) {
                                progressSeries.push({
                                    name: '当前',
                                    type: 'bar',
                                    stack: 'total',
                                    label: {
                                        show: true,
                                    },
                                    emphasis: {
                                        focus: 'series',
                                    },
                                    data: [
                                        {
                                            value: res.dryTime - totalTime,
                                        },
                                    ],
                                })
                            }
                            // ganZaoXiaoLv.push([totalTime + res.remain,eqp.value.dryEfficiency])
                            // console.log(`output->res.remain`, res.remain)
                            // console.log(`output->res.dryTime`, res.dryTime)
                            // console.log(`output->totalTime`, totalTime)
                            // å¹²ç‡¥å‰©ä½™æ—¶é—´=工单预计剩余-(当前干燥时间-最后一次记录干燥时间)
                            res.totalRemain = res.remain - (res.dryTime - totalTime) > 0 ? res.remain - (res.dryTime - totalTime) : 0
                            progressSeries.push({
                                name: '剩余',
                                type: 'bar',
                                stack: 'total',
                                label: {
                                    show: true,
                                },
                                emphasis: {
                                    focus: 'series',
                                },
                                data: [
                                    {
                                        value: res.remain - (res.dryTime - totalTime),
                                        itemStyle: {
                                            color: '#c0c0c0',
                                        },
                                    },
                                ],
                            })
                        }
                        /**干燥进度 */
                        res.totalTime = totalTime + res.remain
                        console.log("efficAvg::",res.efficAvg);
                        /**干燥效率、消耗 */
                        res.moisList.push([res.dryTime, res.trendVo.moisture])
                    }
                    /**温度趋势 */
                    if (res && res.bellowsTemp) {
                        Array.from(Object.entries(res.bellowsTemp))
                        var arr = Object.keys(res.bellowsTemp)
                        var temArr = []
                        arr.forEach((item) => {
                            temArr.push([item * 1, res.bellowsTemp[item]])
                        })
                        //console.log(`output->arr` + JSON.stringify(temArr))
                        res.tempArr = temArr
                    }
                    /**干燥过程趋势 */
                    if (moisChart) {
                        //console.log(`output->更新chart`)
                        moisChart.setOption({
                            series: [
                                {
                                    data: res.moisList,
                                    markLine: {
                                        symbol: 'none',
                                        data: [
                                            {
                                                name: '目标',
                                                yAxis: res.target,
                                            },
                                        ],
                                        label: {
                                            formatter: '{b}\n{c}%',
                                            color: '#fff',
                      fontSize: 20,
                                        },
                                    },
                                },
                                {
                                    data: res.tempArr,
                                },
                            ],
                        })
                    }
                    let lastTrend = res.detailList[res.detailList.length-1]
                    /**效率对比图 */
                    if (res.originWeight - lastTrend.weight <= 0) {
                        res.xiaolv = 0
                    } else {
                        res.xiaolv = ((res.originWeight - lastTrend.weight) / lastTrend.totalTime) * 60
                    }
                    res.xiaolv = Number(res.xiaolv)
                    //eqp.value.dryEfficiency = Number(eqp.value.dryEfficiency)
                    if (res.xiaolv > res.efficAvg) {
                        console.log("xiaolv:",res , eqp);
                        res.xlgood = true
                        res.xlsHeight = (res.efficAvg / res.xiaolv) * 100 + '%'
                        res.xlrHeight = '100%'
                    } else if (res.xiaolv < res.efficAvg * 0.9) {
                        res.xlbad = true
                        res.xlsHeight = '100%'
                        res.xlrHeight = (res.xiaolv / res.efficAvg) * 100 + '%'
                    } else {
                        res.xlsHeight = '100%'
                        res.xlrHeight = (res.xiaolv / res.efficAvg) * 100 + '%'
                    }
                    /** è’¸æ±½æ¶ˆè€— */
                    if (res.originWeight - lastTrend.weight <= 0) {
                        res.zhengqi = 0
                    } else {
                        res.zhengqi = lastTrend.steam / (res.originWeight - lastTrend.weight)
                    }
                    res.zhengqi = Number(res.zhengqi)
                    //eqp.value.steamConsumption = Number(eqp.value.steamConsumption)
                    // res.zhengqi = eqp.value.steamConsumption - 3
                    // console.log(res);
                    // console.log('zhengqi:', res.zhengqi);
                    if (res.zhengqi > res.steamAvg) {
                        res.zqbad = true
                        res.zqsHeight = (res.steamAvg / res.zhengqi) * 100 + '%'
                        res.zqrHeight = '100%'
                    } else if (res.zhengqi < res.steamAvg * 0.9) {
                        res.zqgood = true
                        res.zqsHeight = '100%'
                        res.zqrHeight = (res.zhengqi / res.steamAvg) * 100 + '%'
                    } else {
                        res.zqsHeight = '100%'
                        res.zqrHeight = (res.zhengqi / res.steamAvg) * 100 + '%'
                    }
                    /** ç”µèƒ½æ¶ˆè€— */
                    if (res.originWeight - lastTrend.weight <= 0) {
                        res.dian = 0
                    } else {
                        res.dian = lastTrend.watt / (res.originWeight - lastTrend.weight)
                    }
                    // res.dian = eqp.value.powerConsumption - 1.5
                    res.dian = Number(res.dian)
                    //eqp.value.powerConsumption = Number(eqp.value.powerConsumption)
                    if (res.dian > res.wattAvg) {
                        console.log("dian::", res.dian,res.wattAvg )
                        res.dnbad = true
                        res.dnsHeight = (res.wattAvg / res.dian) * 100 + '%'
                        res.dnrHeight = '100%'
                    } else if (res.dian < res.wattAvg * 0.9) {
                        res.dngood = true
                        res.dnsHeight = '100%'
                        res.dnrHeight = (res.dian / res.wattAvg) * 100 + '%'
                    } else {
                        res.dnsHeight = '100%'
                        res.dnrHeight = (res.dian / res.wattAvg) * 100 + '%'
                    }
                    //console.log('state:::fan::', res.state_fan, 'roller::', res.state_roller, 'windbox::', res.state_windbox)
                    //console.log('===========================')
                    //console.log("state:::state_windbox::", res.state_windbox);
                    /**状态/gif动图 */
                    if (!shangliaoFlag) {
                        if (res.orderStatus == 0) {
                            statusGif = 'zanting'
                            statusTxt = '准备'
                        } else if (res.orderStatus == 1) {
              //todo å®žé™…生产点击一键干燥后才会有工单状态发上来,那时已经上完料,需要确认工单状态
                            shangliaoFlag = true
                            statusGif = 'kaimen1'
                            statusTxt = '上料'
                            setTimeout(chaiwangban, 4000)
                        } else if (res.orderStatus == 2) {
                            statusTxt = res.level
                            statusGif = 'zanting'
                            if (res.level === '准备阶段') {
                                console.log("准备阶段" + statusGif);
                                statusGif = 'zanting'
                            } else if (res.level === '干燥阶段' || res.level === '正在干燥') {
                                statusGif = 'tmrefeng2'
                            } else if (res.level === '翻料阶段') {
                                statusGif = 'fanliao-N'
                            } else if (res.level === '出料阶段') {
                                statusGif = 'chuliao-N'
                            }
                            // if (res.state_fan == 1) {
                            //     statusGif = 'tmrefeng2'
                            //     statusTxt = '正在干燥'
                            // }
                            // if (res.state_roller == 4) {
                            //     statusGif = 'fanliao-N'
                            //     statusTxt = '正在翻料'
                            // }
                            // if (res.state_roller == 5) {
                            //     statusGif = 'chuliao-N'
                            //     statusTxt = '正在出料'
                            // }
                            // if (res.state_windbox == 2 || res.state_windbox == 3) {
                            //     statusGif = 'fengxiangsheng-1'
                            //     statusTxt = '正在干燥'
                            // }
                        } else if (res.orderStatus == 3) {
                            statusGif = 'zanting'
                            statusTxt = '暂停'
                        } else if (res.orderStatus == 4) {
                            statusGif = 'zanting'
                            statusTxt = '干燥完成'
                        }
                    }
                    res.herbImage = 'yaocai1.png'
                    if (res.herbName == '白花蛇舌草') {
                        res.herbImage = 'baihuasheshecao.png'
                    } else if (res.herbName == '糥稻根') {
                        res.herbImage = 'nuodaogen.png'
                    } else if (res.herbName == '淫羊藿') {
                        res.herbImage = 'yinyanghuo.png'
                    } else if (res.herbName == '马齿苋') {
                        res.herbImage = 'machixian.png'
                    } else if (res.herbName == '墨旱莲') {
                        res.herbImage = 'mohanlian.png'
                    } else if (res.herbName == '桑白皮') {
                        res.herbImage = 'sangbaipi.png'
                    }
          if (res.fault) {
            res.isError = true
            res.errorMsg = res.fault;
            const faults = res.fault;
            console.log('errorMsg:', res.fault)
            if (faults.includes('急停报警')) {
              shebeijiting.value = true;
            } else {
              shebeijiting.value = false;
            }
            if (faults.includes('左前急停')) {
              zuoqianjiting.value = true;
            } else {
              zuoqianjiting.value = false;
            }
            if (faults.includes('面板急停')) {
              mianbanjiting.value = true;
            } else {
              mianbanjiting.value = false;
            }
            if (faults.includes('出料急停')) {
              chuliaojiting.value = true;
            } else {
              chuliaojiting.value = false;
            }
            if (faults.includes('温度失控')) {
              wendubaojing.value = true;
            } else {
              wendubaojing.value = false;
            }
            if (faults.includes('滚筒升')) {
              guntongsheng.value = true;
            } else {
              guntongjiang.value = false;
            }
            if (faults.includes('滚筒降')) {
              guntongjiang.value = true;
            } else {
              guntongjiang.value = false;
            }
            if (faults.includes('滚筒电机过流')) {
              guntongguoliu.value = true;
            } else {
              guntongguoliu.value = false;
            }
            if (faults.includes('风箱升')) {
              fengxiangsheng.value = true;
            } else {
              fengxiangsheng.value = false;
            }
            if (faults.includes('风箱降')) {
              fengxiangjiang.value = true;
            } else {
              fengxiangjiang.value = false;
            }
            if (faults.includes('风箱风机过流')) {
              fengjiguoliu.value = true;
            } else {
              fengjiguoliu.value = false;
            }
          }
          else {
            res.isError = false
             shebeijiting.value = false
             chuliaojiting.value = false
             zuoqianjiting.value = false
             mianbanjiting.value = false
             fengxiangsheng.value = false
             fengxiangjiang.value = false
             fengjiguoliu.value = false
             guntongsheng.value = false
             guntongjiang.value = false
             guntongguoliu.value = false
             wendubaojing.value = false
          }
          if (res.warning) {
            res.isWarning = true
            res.warnMsg = res.warning
            const warnings = res.warning;
            console.log('warnMsg:', res.warning)
            if (warnings.includes('左前门')) {
              zuoqianmen.value = true;
            } else {
              zuoqianmen.value = false;
            }
            if (warnings.includes('右前门')) {
              youqianmen.value = true;
            } else {
              youqianmen.value = false;
            }
            if (warnings.includes('左后门')) {
              zuohoumen.value = true;
            } else {
              zuohoumen.value = false;
            }
            if (warnings.includes('右后门')) {
              youhoumen.value = true;
            } else {
              youhoumen.value = false;
            }
            if (warnings.includes('滚筒不在高位')) {
              guntongbuzaigaowei.value = true;
            } else {
              guntongbuzaigaowei.value = false;
            }
            if (warnings.includes('风箱不在低位')) {
              fengxiangbuzaidiwei.value = true;
            } else {
              fengxiangbuzaidiwei.value = false;
            }
            if (warnings.includes('风箱不在高位')) {
              fengxiangbuzaigaowei.value = true;
            } else {
              fengxiangbuzaigaowei.value = false;
            }
            if (warnings.includes('加热位传感器')) {
              jiareweichuanganqi.value = true;
            } else {
              jiareweichuanganqi.value = false;
            }
            if (warnings.includes('左前风箱高位传感器')) {
              zuoqianfengxianggaowei.value = true;
            } else {
              zuoqianfengxianggaowei.value = false;
            }
            if (warnings.includes('右前风箱高位传感器')) {
              youqianfengxianggaowei.value = true;
            } else {
              youqianfengxianggaowei.value = false;
            }
            if (warnings.includes('左后风箱高位传感器')) {
              zuohoufengxianggaowei.value = true;
            } else {
              zuohoufengxianggaowei.value = false;
            }
            if (warnings.includes('右后风箱高位传感器')) {
              youhoufengxianggaowei.value = true;
            } else {
              youhoufengxianggaowei.value = false;
            }
            if (warnings.includes('左前风箱低位传感器')) {
              zuoqianfengxiangdiwei.value = true;
            } else {
              zuoqianfengxiangdiwei.value = false;
            }
            if (warnings.includes('右前风箱低位传感器')) {
              youqianfengxiangdiwei.value = true;
            } else {
              youqianfengxiangdiwei.value = false;
            }
            if (warnings.includes('左后风箱低位传感器')) {
              zuohoufengxiangdiwei.value = true;
            } else {
              zuohoufengxiangdiwei.value = false;
            }
            if (warnings.includes('右后风箱低位传感器')) {
              youhoufengxiangdiwei.value = true;
            } else {
              youhoufengxiangdiwei.value = false;
            }
            if (warnings.includes('左前滚筒低位传感器')) {
              zuoqianguntongdiwei.value = true;
            } else {
              zuoqianguntongdiwei.value = false;
            }
            if (warnings.includes('右前滚筒低位传感器')) {
              youqianguntongdiwei.value = true;
            } else {
              youqianguntongdiwei.value = false;
            }
            if (warnings.includes('左后滚筒低位传感器')) {
              zuohouguntongdiwei.value = true;
            } else {
              zuohouguntongdiwei.value = false;
            }
            if (warnings.includes('右后滚筒低位传感器')) {
              youhouguntongdiwei.value = true;
            } else {
              youhouguntongdiwei.value = false;
            }
          }
          else {
            res.isWarning = false
             zuoqianmen.value = false;
             zuohoumen.value = false;
             youqianmen.value = false;
             youhoumen.value = false;
             guntongbuzaigaowei.value = false;
             fengxiangbuzaigaowei.value = false;
             fengxiangbuzaidiwei.value = false;
             jiareweichuanganqi.value = false;
             zuoqianfengxianggaowei.value = false;
             zuohoufengxianggaowei.value = false;
             youqianfengxianggaowei.value = false;
             youhoufengxianggaowei.value = false;
             zuoqianfengxiangdiwei.value = false;
             zuohoufengxiangdiwei.value = false;
             youqianfengxiangdiwei.value = false;
             youhoufengxiangdiwei.value = false;
             zuoqianguntongdiwei.value = false;
             zuohouguntongdiwei.value = false;
             youqianguntongdiwei.value = false;
             youhouguntongdiwei.value = false;
          }
          isError.value = res.isError
          isWarning.value = res.isWarning
                } else {
                    res = {
                        mois: [],
                        gif: 'tmrefeng2',
                        herbImage: 'yaocai1.png',
                    }
                }
                // console.log(`output->res`, res.detailList[res.detailList.length-1])
                realData.value = res
            })
        }
    }
    function back() {
        router.back()
    }
    listAllEqp()
    //queryEqp()
    // DOM挂载完成后渲染图表
    onMounted(() => {
        Timer.value = setInterval(queryRealTime, 3000)
    })
    onUnmounted(() => {
        clearInterval(Timer.value)
        Timer.value = null
    })
</script>
<style scoped>
    .eqpBox {
        height: 100%;
    }
    .eqpRow {
    }
    .eqpImage {
        height: 1080px;
        width: 1920px;
        background-image: url(/src/assets/images/dry/bg.png);
        background-repeat: no-repeat;
        color: white;
        /*background-position: 160px 280px; */
        /* background-color: red; */
        background-size: 120%;
        padding: 10px;
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
    }
    .leftEqp {
        height: 1080px;
        width: 945px;
    border: 1px solid black;
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
        /* background-color: white;
        background-image: url(/src/assets/images/dry/shebei1.png);
        background-repeat: no-repeat;
        background-size: 125%;
        border-radius: 10px;
        background-position: -119px 293px; */
    }
    .leftTop {
        height: 990px;
        width: 945px;
        display: flex;
        justify-content: center;
        align-content: flex-start;
        //background-image: url(/src/assets/images/dry/ganzaoji-x.png);
        background-repeat: no-repeat;
        background-size: 79%;
        border-radius: 10px;
        flex-wrap: wrap;
        background-position: 85px 279px;
    }
    .leftMid {
        width: 850px;
        height: 300px;
        /* border: 1px solid; */
        margin-top: 10px;
        border-radius: 10px;
        /* background: white; */
    }
    .mainInfo {
        line-height: 33px;
        padding-left: 10px;
        font-size: 30px;
        color: white;
    }
    .subhead {
        color: #a19f9c;
        font-size: 16px;
        padding-left: 10px;
    }
    .mainInfo2 {
        line-height: 20px;
        padding-left: 0px;
        font-size: 16px;
    }
    .subhead2 {
        color: #a19f9c;
        font-size: 10px;
        padding-left: 0px;
    }
    .zhengqi {
        height: 180px;
        width: 200px;
        background-image: url(/src/assets/images/dry/liuliangji.png);
        background-repeat: no-repeat;
        background-size: 160px;
        /* border-radius: 10px; */
        background-position: 17px -6px;
    }
    .liuliangji {
    }
    .leftData {
        height: 250px;
        width: 120px;
    }
    .rightChart {
        height: 270px;
        width: 170px;
        margin-top: -30px;
    }
    .leftTop0 {
        height: 400px;
        width: 500px;
    padding-left: 10px;
        display: flex;
        justify-content: space-between;
        align-content: flex-start;
        flex-wrap: wrap;
    }
    .leftTop1 {
        width: 250px;
        height: 200px;
        text-align: center;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 30px;
        color: #727272;
    }
    .leftTop2 {
        width: 250px;
        height: 200px;
        text-align: center;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 30px;
        color: #727272;
    }
    .leftTop3 {
        width: 340px;
        height: 200px;
        /* background-image: url(/src/assets/images/dry/fanliao.gif); */
        background-repeat: no-repeat;
        background-position: 0px 20px;
        background-size: 300px;
        border-radius: 50px;
    }
  .ganzaoji {
    background-repeat: no-repeat;
    background-position: 110px 15px;
    background-size: 685px;
    width: 960px;
    height: 440px;
    position: absolute;
  }
    .eqpStatus {
        width: 960px;
    }
    .rightInfo {
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
        height: 1060px;
        width: 700px;
    }
    .rightTop {
        display: flex;
        height: 300px;
        padding-left: 10px;
    }
    .rightTwo {
        display: flex;
        flex-wrap: wrap;
    }
    .infoChart {
        width: 340px;
        height: 300px;
        /* background: white; */
        margin-left: 10px;
        margin-top: 10px;
        border-radius: 10px;
    }
    .chartTittle {
        width: 340px;
        height: 30px;
        font-size: 16px;
        display: flex;
        justify-content: space-between;
        padding: 15px 15px;
    }
    .chartInfo {
        width: 60px;
        height: 180px;
    }
    .compareBar {
        width: 55px;
        height: 140px;
    }
    .margintop-30 {
        margin-top: -30px;
    }
    .barTop {
        width: 55px;
        height: 30px;
    }
    .barBack {
        width: 30px;
        height: 100px;
        /* border: 1px solid black; */
        display: flex;
        flex-wrap: wrap;
        align-content: flex-end;
    }
    .barDiv {
        width: 100%;
        background-color: #1595ea;
    }
    .bad {
        background-color: #973535;
    }
    .rightLabel {
        width: 110px;
        display: flex;
        justify-content: space-between;
    }
    .label {
        color: white;
        text-align: center;
        width: 50px;
        border-radius: 4px;
        height: 20px;
        font-size: 10px;
        line-height: 21px;
    }
    .good {
        background-color: #0d6e24;
    }
    .mainInfo3 {
        font-size: 24px;
    }
    .herbInfo {
        width: 340px;
        height: 440px;
        color: #727272;
    }
    .curEqp {
        width: 340px;
        height: 170px;
        /* background: white;
        border-radius: 10px; */
    }
    .curHerb {
        margin-top: 10px;
        width: 340px;
        height: 260px;
        /* background: white;
        border-radius: 10px; */
        background-repeat: no-repeat;
        background-size: 200px;
        background-position: 0px 10px;
    }
    .tempMoisChart {
        width: 500px;
        height: 300px;
        /* background: white; */
        padding: 20px;
        border-radius: 10px;
    }
    .topLeft {
        margin: 20px 40px 60px 20px;
        padding: 15px;
        /* background: white; */
        border-radius: 10px;
        height: 325px;
        width: 440px;
        /* background-image: url(/src/assets/images/dry/yaocai.jpg); */
        background-repeat: no-repeat;
        background-size: 164px 132px;
        background-position: 239px 65px;
        display: flex;
    }
    .topMid {
        margin: 20px 20px 60px 40px;
        /* background: white; */
        border-radius: 10px;
        background-image: url(/src/assets/images/dry/fanliao.gif);
        background-repeat: no-repeat;
        background-position: 0px 20px;
        background-size: 400px;
        width: 400px;
        padding: 20px;
    }
    .topRight {
        margin: 20px 20px 60px 20px;
        /* background: white; */
        border-radius: 10px;
        width: 700px;
        padding: 20px;
    }
    .midLeft {
        height: 450px;
        width: 600px;
        display: flex;
        padding: 0 20px 20px 20px;
    }
    .midMid {
        width: 500px;
        padding-top: 50px;
    }
    .midRight {
        background-image: url(/src/assets/images/dry/fengjixz.gif);
        background-repeat: no-repeat;
        background-position: 150px 260px;
        background-size: 120px 120px;
        width: 600px;
    }
    .shangJianTou {
        margin-left: 140px;
        width: 70px;
        height: 100px;
        background-image: url(/src/assets/images/dry/shangjiantoutou.gif);
        background-repeat: no-repeat;
        background-position: 0px 0px;
        background-size: 70px 100px;
    }
    .zoujiantou {
        margin-left: 225px;
        margin-top: 30px;
        width: 100px;
        height: 70px;
        background-image: url(/src/assets/images/dry/zuojiantou.gif);
        background-repeat: no-repeat;
        background-position: 0px 0px;
        background-size: 100px 70px;
    }
    .fault {
        padding: 10px;
        height: 60px;
        font-size: 26px;
        width: 100%;
        text-align: right;
        color: red;
    }
    .eqpName {
        padding: 20px;
        height: 160px;
    }
    .formula {
        display: flex;
        width: 340px;
        height: 40px;
        padding: 0 20px;
        justify-content: space-around;
        justify-items: center;
    }
    .formulaItem {
        display: flex;
        justify-content: center;
        width: 85px;
        height: 40px;
    }
    .eqpInfoText {
        font-size: 18px;
        font-weight: bold;
    }
    :deep() .ant-slider-mark-text {
        padding-left: 15px;
        font-size: 10px;
    }
    :deep() .ant-slider-mark-text::before {
        content: '';
        display: block;
        width: 6px;
        height: 1px;
        background-color: #1890ff;
        position: absolute;
        top: 10px;
        left: 0px;
    }
    :deep() .ant-slider-rail {
        width: 10px !important;
        border-radius: 6px 6px 0 0;
        background: linear-gradient(to top, #ce0000 0%, #ce0000 40%, #ce0000 75%, rgb(160, 160, 160) 100%);
    }
    :deep() .ant-slider-track {
        background: rgb(216, 216, 216);
        height: 20px;
        width: 10px !important;
        border-radius: 6px 6px 0 0;
    }
    :deep() .ant-slider-track:hover {
    }
    :deep() .ant-slider-handle {
        display: none;
    }
    :deep() .ant-slider-dot {
        display: none;
    }
    :deep() .ant-slider-step {
        width: 10px !important;
    }
    :deep() .ant-slider-step > :first-child {
        display: block !important;
        width: 30px !important;
        height: 30px !important;
        bottom: -26px !important;
        left: -6px;
        border: none;
        background: #ce0000;
    }
    :deep() .progress {
        padding: 25px 25px;
        width: 360px;
        display: flex;
    }
    :deep() .ant-progress-bg {
        height: 25px !important;
    }
    .outDiv {
        display: flex;
        justify-content: center;
        justify-items: center;
    }
    .blingbling {
        -webkit-animation: scaleout 1.5s infinite ease-in-out;
        animation: scaleout 1.5s infinite ease-in-out;
    }
    .center {
        display: flex;
        justify-content: center;
        justify-items: center;
        align-items: center;
        flex-wrap: wrap;
        text-align: center;
    }
    .centerText {
        width: 100%;
        text-align: center;
    }
    @-webkit-keyframes scaleout {
        0% {
            -webkit-transform: scale(1);
        }
        100% {
            -webkit-transform: scale(1.1);
            opacity: 0;
        }
    }
    @keyframes scaleout {
        0% {
            transform: scale(1);
            -webkit-transform: scale(1);
        }
        100% {
            transform: scale(1.1);
            -webkit-transform: scale(1.1);
            opacity: 0;
        }
    }
  .error-div {
    position: absolute; display: flex; align-items: center;
  }
  .error-marker {
    width: 18px; height: 18px; background: red; border-radius: 50%;
  }
  .error-msg {
    margin-left: 6px;
    height: 24px;
    background: gray; border-radius: 5px; font-weight: bold; color: red
  }
  .warn-marker {
    width: 18px; height: 18px; background: orange; border-radius: 50%;
  }
  .warn-msg {
    margin-left: 6px;
    height: 24px;
    background: gray; border-radius: 5px; font-weight: bold; color: orange;
  }
  :deep() .progress {
    padding: 25px 25px;
    width: 360px;
    display: flex;
  }
  :deep() .ant-progress-bg {
    height: 36px !important;
  }
  :deep() .ant-progress-inner {
    background-color: rgb(197 197 197 / 84%) !important;
  }
</style>
src/views/dry/repair/DryRepairRecords.api.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
import {defHttp} from '/src/utils/http/axios';
import { useMessage } from "/src/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
  list = '/dry/dryRepairRecords/list',
  save='/dry/dryRepairRecords/add',
  edit='/dry/dryRepairRecords/edit',
  deleteOne = '/dry/dryRepairRecords/delete',
  deleteBatch = '/dry/dryRepairRecords/deleteBatch',
  importExcel = '/dry/dryRepairRecords/importExcel',
  exportXls = '/dry/dryRepairRecords/exportXls',
  generateRepairNo = '/dry/dryRepairRecords/generateRepairNo',
}
/**
 * å¯¼å‡º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});
}
/**
 * ç”Ÿæˆç»´ä¿®å•号
 */
export const generateRepairNo = () => defHttp.get({url: Api.generateRepairNo}, { successMessageMode: 'none' });
src/views/dry/repair/DryRepairRecords.data.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,305 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { rule } from 'postcss';
//列表数据
export const columns: BasicColumn[] = [
   {
    title: '维修单号',
    align:"center",
    dataIndex: 'orderNumber'
   },
   {
    title: '设备编号',
    align:"center",
    dataIndex: 'equId_dictText'
   },
   {
    title: '故障时间',
    align:"center",
    dataIndex: 'faultTime',
   },
   {
    title: '报修人',
    align:"center",
    dataIndex: 'reporter'
   },
   {
    title: '维修开始时间',
    align:"center",
    dataIndex: 'startTime',
   },
   {
    title: '维修结束时间',
    align:"center",
    dataIndex: 'endTime',
   },
   {
    title: '维修人员',
    align:"center",
    dataIndex: 'technician'
   },
   {
    title: '故障类型',
    align:"center",
    dataIndex: 'faultType',
    customRender: ({text}) => {
      const options = {
        '0': '机械故障',
        '1': '电气故障',
        '2': '其他故障'
      };
      return options[text] || text;
    }
   },
   {
    title: '故障描述',
    align:"center",
    dataIndex: 'description'
   },
   {
    title: '维修措施',
    align:"center",
    dataIndex: 'solution'
   },
   {
    title: '更换配件',
    align:"center",
    dataIndex: 'parts'
   },
   {
    title: '维修费用',
    align:"center",
    dataIndex: 'cost'
   },
   {
    title: '维修状态',
    align:"center",
    dataIndex: 'status',
    customRender: ({text}) => {
      const options = {
        '0': '待维修',
        '1': '维修中',
        '2': '已完成'
      };
      return options[text] || text;
    }
   },
];
//查询数据
export const searchFormSchema: FormSchema[] = [
    {
      label: "设备编号",
      field: 'equId',
      component: 'JDictSelectTag',
      componentProps:{
          dictCode:"dry_equipment,name,id"
      },
      colProps: {span: 6},
     },
    {
    label: '故障时间',
    field: 'faultTime',
    component: 'DatePicker',
    componentProps: {
       showTime: true,
       valueFormat: 'YYYY-MM-DD HH:mm:ss'
     },
  },
    {
      label: "报修人",
      field: 'reporter',
      component: 'Input',
      colProps: {span: 6},
     },
    {
      label: "维修人员",
      field: 'technician',
      component: 'Input',
      colProps: {span: 6},
     },
    {
      label: "故障类型",
      field: 'faultType',
      component: 'Select',
      componentProps:{
          options: [
            { label: '机械故障', value: '0' },
            { label: '电气故障', value: '1' },
            { label: '其他故障', value: '2' }
          ]
      },
      colProps: {span: 6},
     },
    {
      label: "维修状态",
      field: 'status',
      component: 'Select',
      componentProps:{
          options: [
            { label: '待维修', value: '0' },
            { label: '维修中', value: '1' },
            { label: '已完成', value: '2' }
          ]
      },
      colProps: {span: 6},
     },
];
//表单数据
export const formSchema: FormSchema[] = [
  {
    label: '维修单号',
    field: 'orderNumber',
    component: 'Input',
    dynamicDisabled:true
  },
  {
    label: '设备编号',
    field: 'equId',
    component: 'JDictSelectTag',
    componentProps:{
        dictCode:"dry_equipment,name,id"
     },
     rules: [{ required: true, message: '请选择设备编号' }],
  },
  {
    label: '故障时间',
    field: 'faultTime',
    component: 'DatePicker',
    componentProps: {
       showTime: true,
       valueFormat: 'YYYY-MM-DD HH:mm:ss'
     },
    rules: [{ required: true, message: '请选择故障时间' }],
  },
  {
    label: '报修人',
    field: 'reporter',
    component: 'Input',
  },
  {
    label: '维修时间',
    field: 'startTime',
   component: 'DatePicker',
    componentProps: {
       showTime: true,
       valueFormat: 'YYYY-MM-DD HH:mm:ss'
     },
     dynamicRules: ({values}) => {
      return [
        { required: true,
          validator: (_, value) => {
            const faultTime = values.faultTime;
            if (faultTime && value && new Date(value).getTime() < new Date(faultTime).getTime()) {
              return Promise.reject('维修开始时间不能早于故障时间');
            }
            return Promise.resolve();
          }
         }
      ]
    }
  },
  {
    label: '结束时间',
    field: 'endTime',
    component: 'DatePicker',
    componentProps: {
       showTime: true,
       valueFormat: 'YYYY-MM-DD HH:mm:ss'
     },
    dynamicRules: ({values}) => {
      return [
        { required: true,
          validator: (_, value) => {
            const startTime = values.startTime;
            if (startTime && value && new Date(value).getTime() < new Date(startTime).getTime()) {
              return Promise.reject('维修结束时间不能早于维修开始时间');
            }
            return Promise.resolve();
          }
         }
      ]
    }
  },
  {
    label: '维修人员',
    field: 'technician',
    component: 'Input',
    rules: [{ required: true, message: '请输入维修人员' }],
  },
  {
    label: '故障类型',
    field: 'faultType',
    component: 'Select',
    componentProps:{
        options: [
          { label: '机械故障', value: '0' },
          { label: '电气故障', value: '1' },
          { label: '其他故障', value: '2' }
        ]
     },
    rules: [{ required: true, message: '请选择故障类型' }],
  },
  {
    label: '故障描述',
    field: 'description',
    component: 'InputTextArea',
  },
  {
    label: '维修措施',
    field: 'solution',
    component: 'InputTextArea',
  },
  {
    label: '更换配件',
    field: 'parts',
    component: 'InputTextArea',
  },
  {
    label: '维修费用',
    field: 'cost',
    component: 'Input',
    rules: [{
      pattern: /^\d+(\.\d+)?$/,
      message: '请输入数字',
      trigger: 'blur'
    }],
  },
  {
    label: '维修状态',
    field: 'status',
    component: 'Select',
    componentProps:{
        options: [
          { label: '待维修', value: '0' },
          { label: '维修中', value: '1' },
          { label: '已完成', value: '2' }
        ]
     },
  },
    // TODO ä¸»é”®éšè—å­—段,目前写死为ID
    {
      label: '',
      field: 'id',
      component: 'Input',
      show: false
    },
];
/**
* æµç¨‹è¡¨å•调用这个方法获取formSchema
* @param param
*/
export function getBpmFormSchema(_formData): FormSchema[]{
  // é»˜è®¤å’ŒåŽŸå§‹è¡¨å•ä¿æŒä¸€è‡´ å¦‚果流程中配置了权限数据,这里需要单独处理formSchema
  return formSchema;
}
src/views/dry/repair/DryRepairRecordsList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,211 @@
<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 #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>
    <!-- è¡¨å•区域 -->
    <DryRepairRecordsModal @register="registerModal" @success="handleSuccess"></DryRepairRecordsModal>
  </div>
  <!--子表表格tab-->
  <a-tabs defaultActiveKey="1" style="margin: 10px">
    <a-tab-pane tab="使用备件列表" key="1" forceRender>
      <DrySpareStockLogListRepair />
    </a-tab-pane>
  </a-tabs>
  <!-- è¡¨å•区域 -->
  <DryRepairRecordsModal @register="registerModal" @success="handleSuccess"></DryRepairRecordsModal>
</template>
<script lang="ts" name="dry-dryRepairRecords" setup>
  import {ref, computed, unref, provide} from 'vue';
  import {BasicTable, useTable, TableAction} from '/@/components/Table';
  import {useModal} from '/@/components/Modal';
  import { useListPage } from '/@/hooks/system/useListPage'
  import DryRepairRecordsModal from './components/DryRepairRecordsModal.vue'
  import DrySpareStockLogListRepair from './DrySpareStockLogListRepair.vue';
  import {columns, searchFormSchema} from './DryRepairRecords.data';
  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './DryRepairRecords.api';
  import { downloadFile } from '/@/utils/common/renderUtils';
  const checkedKeys = ref<Array<string | number>>([]);
  const selectedRows = ref<Array<any>>([]); // æ–°å¢žï¼šç”¨äºŽå­˜å‚¨é€‰ä¸­çš„行数据
  //注册model
  const [registerModal, {openModal}] = useModal();
  //注册table数据
  const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
      tableProps:{
           title: '维修记录',
           api: list,
           columns,
           canResize:false,
           formConfig: {
              //labelWidth: 120,
              schemas: searchFormSchema,
              autoSubmitOnEnter:true,
              showAdvancedButton:true,
              fieldMapToNumber: [
              ],
              fieldMapToTime: [
              ],
            },
           actionColumn: {
               width: 120,
               fixed:'right'
            },
           rowSelection: {
             type: 'radio',
             onChange: (selectedRowKeyList: (string | number)[], selectedRowList: any[]) => {
               selectedRowKeys.value = selectedRowKeyList;
               selectedRows.value = selectedRowList; // æ›´æ–°é€‰ä¸­çš„行数据
             },
           },
           customRow: (record) => {
             return {
               onClick: () => {
                 if (selectedRowKeys.value.includes(record.id)) {
                   selectedRowKeys.value = [];
                   selectedRows.value = [];
                 } else {
                   selectedRowKeys.value = [record.id];
                   selectedRows.value = [record];
                 }
               },
             };
           }, // ç¡®ä¿ä¸»è¡¨æ˜¯å•选
      },
       exportConfig: {
            name:"维修记录",
            url: getExportUrl,
          },
          importConfig: {
            url: getImportUrl,
            success: handleSuccess
          },
  })
  const [registerTable, {reload, updateTableDataRecord},{ rowSelection, selectedRowKeys }] = tableContext
  const orderNumber = computed(() => (
     unref(selectedRows).length > 0 ? unref(selectedRows)[0].orderNumber : '1')) // ä¿®æ”¹ï¼šä¼ é€’orderNumber,如果为空则传递空字符串
  ;
  //下发 orderNumber,子组件接收
  provide('orderNumber', orderNumber);
   /**
    * æ–°å¢žäº‹ä»¶
    */
  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) {
     await deleteOne({id: record.id}, handleSuccess);
   }
   /**
    * æ‰¹é‡åˆ é™¤äº‹ä»¶
    */
  async function batchHandleDelete() {
     await batchDelete({ids: selectedRowKeys.value}, () => {
        selectedRowKeys.value = [];
        reload();
     });
   }
   /**
    * æˆåŠŸå›žè°ƒ
    */
  function handleSuccess() {
      (selectedRowKeys.value = []) && reload();
   }
   /**
      * æ“ä½œæ 
      */
  function getTableAction(record){
       return [
         {
           label: '编辑',
           onClick: handleEdit.bind(null, record),
         },
         {
           label: '删除',
           popConfirm: {
             title: '是否确认删除',
             confirm: handleDelete.bind(null, record),
           }
         }
       ]
   }
     /**
        * ä¸‹æ‹‰æ“ä½œæ 
        */
  function getDropDownAction(record){
       return [
         {
           label: '详情',
           onClick: handleDetail.bind(null, record),
         }
       ]
   }
</script>
<style scoped>
</style>
src/views/dry/repair/DryRepairRecords_menu_insert.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
-- æ³¨æ„ï¼šè¯¥é¡µé¢å¯¹åº”的前台目录为views/dry文件夹下
-- å¦‚果你想更改到其他目录,请修改sql中component字段对应的值
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 ('2025072104372230580', NULL, '维修记录', '/dry/dryRepairRecordsList', 'dry/maint/DryRepairRecordsList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2025-07-21 16:37:58', 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 ('2025072104372230581', '2025072104372230580', '添加维修记录', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_repair_records:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:37:58', 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 ('2025072104372230582', '2025072104372230580', '编辑维修记录', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_repair_records:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:37:58', 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 ('2025072104372230583', '2025072104372230580', '删除维修记录', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_repair_records:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:37:58', 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 ('2025072104372230584', '2025072104372230580', '批量删除维修记录', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_repair_records:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:37:58', 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 ('2025072104372230585', '2025072104372230580', '导出excel_维修记录', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_repair_records:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:37:58', 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 ('2025072104372230586', '2025072104372230580', '导入excel_维修记录', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_repair_records:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:37:58', NULL, NULL, 0, 0, '1', 0);
src/views/dry/repair/components/DryRepairRecordsForm.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 '../DryRepairRecords.data';
    import {saveOrUpdate} from '../DryRepairRecords.api';
    export default defineComponent({
        name: "DryRepairRecordsForm",
        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: 12}
            });
            const formDisabled = computed(()=>{
                if(props.formData.disabled === false){
                    return false;
                }
                return true;
            });
            let formData = {};
            const queryByIdUrl = '/dry/dryRepairRecords/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>
src/views/dry/repair/components/DryRepairRecordsModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
<template>
  <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="896" @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 '../DryRepairRecords.data';
    import {saveOrUpdate, generateRepairNo} from '../DryRepairRecords.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: 12}
    });
    //表单赋值
    const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
        //重置表单
        await resetFields();
        console.log("registerModal:::","repair")
        setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter});
        isUpdate.value = !!data?.isUpdate;
        if (unref(isUpdate)) {
            //表单赋值
            await setFieldsValue({
                ...data.record,
            });
        } else {
            // æ–°å¢žæ¨¡å¼ä¸‹è‡ªåŠ¨ç”Ÿæˆç»´ä¿®å•å·
            const res = await generateRepairNo();
            console.log("获取维修单号res::",res);
            await setFieldsValue({
                orderNumber: res
            });
        }
        // éšè—åº•部时禁用整个表单
       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>