车间能级提升-智能设备管理系统
zhuguifei
2025-05-13 14681dfe7052cb76eefcc0c17d0a0d708e1ac9dd
完成移动端基本功能
已添加25个文件
已重命名1个文件
已修改28个文件
1341 ■■■■ 文件已修改
eims-ui-mobile/src/components/fg-tabbar/fg-tabbar.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages.json 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/equ/equ-list.vue 86 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/equ/index.vue 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/home/index.vue 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/inspect/insp-record.vue 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/inspect/insp-st.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/login/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/maint/maint-st.vue 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/my/index.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/repair/repair-add.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/repair/repair-fb.vue 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/repair/res-list.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/scan/index.vue 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/spare/index.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/pages/spare/spare-list.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/dict.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/equ.d.ts 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/equ.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/inspect.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/repair.d.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/repair.ts 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/spare.d.ts 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/service/spare.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico1.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico10.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico11.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico12.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico13.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico14.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico15.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico16.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico17.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico18.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico19.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico2.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico20.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico3.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico4.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico5.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico6.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico7.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico8.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/ico/ico9.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/static/images/cgq.png 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/style/index.scss 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/types/uni-pages.d.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/utils/RoleUtils.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsEquController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInspectStController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsRepairResBo.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInspectStService.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInspectStServiceImpl.java 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairResServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eims-ui-mobile/src/components/fg-tabbar/fg-tabbar.vue
@@ -62,13 +62,35 @@
  // scan特殊处理
  if (index === 2) {
    tabbarStore.setCurIdx(tabbarStore.lastIdx)
    // æ¨¡æ‹ŸæˆåŠŸ
    // uni.navigateTo({
    //   url: `/pages/scan/index?result=GPA2024NL025`,
    // })
    // return false
    // æ¨¡æ‹ŸæˆåŠŸ
    // åªå…è®¸é€šè¿‡ç›¸æœºæ‰«ç 
    uni.scanCode({
      onlyFromCamera: true,
      success: function (res) {
        console.log('条码类型:' + res.scanType)
        console.log('条码内容:' + res.result)
        if (res?.scanType !== 'QR_CODE') {
          uni.showToast({
            title: '请使用二维码进行扫码',
            icon: 'none',
          })
          return false
        }
        // ä½¿ç”¨split方法截取资产编号
        // const assetCode = res.result.split('资产编号:')[1].split(' ')[0]
        uni.navigateTo({
          url: `/pages/scan/index?result=${res.result}`,
        })
      },
      fail: function (res) {},
    })
  } else {
    tabbarStore.setCurIdx(index)
eims-ui-mobile/src/pages.json
@@ -78,7 +78,7 @@
      "layout": "tabbar",
      "needLogin": true,
      "style": {
        "navigationBarTitleText": "关于"
        "navigationBarTitleText": "设备"
      }
    },
    {
@@ -209,31 +209,6 @@
      }
    },
    {
      "path": "pages/repair/feedback",
      "type": "page",
      "layout": "default",
      "needLogin": true,
      "style": {
        "navigationBarTitleText": "维修评价",
        "app-plus": {
          "titleNView": {
            "buttons": [
              {
                "text": "提交",
                "fontSize": "14px",
                "color": "#FFFFFF"
              },
              {
                "text": "",
                "fontSize": "14px",
                "color": "#FFFFFF"
              }
            ]
          }
        }
      }
    },
    {
      "path": "pages/repair/repair-add",
      "type": "page",
      "layout": "default",
@@ -250,6 +225,31 @@
              {
                "text": "",
                "fontSize": "24px",
                "color": "#FFFFFF"
              }
            ]
          }
        }
      }
    },
    {
      "path": "pages/repair/repair-fb",
      "type": "page",
      "layout": "default",
      "needLogin": true,
      "style": {
        "navigationBarTitleText": "维修评价",
        "app-plus": {
          "titleNView": {
            "buttons": [
              {
                "text": "提交",
                "fontSize": "14px",
                "color": "#FFFFFF"
              },
              {
                "text": "",
                "fontSize": "14px",
                "color": "#FFFFFF"
              }
            ]
@@ -333,12 +333,25 @@
      }
    },
    {
      "path": "pages/scan/index",
      "type": "page"
    },
    {
      "path": "pages/spare/index",
      "type": "page",
      "layout": "tabbar",
      "needLogin": true,
      "style": {
        "navigationBarTitleText": "spare"
        "navigationBarTitleText": "备件"
      }
    },
    {
      "path": "pages/spare/spare-list",
      "type": "page",
      "layout": "default",
      "needLogin": true,
      "style": {
        "navigationBarTitleText": "备件列表"
      }
    }
  ],
eims-ui-mobile/src/pages/equ/equ-list.vue
@@ -11,8 +11,20 @@
  <z-paging ref="paging" v-model="dataList" @query="queryList" show-refresher-update-time>
    <template #top>
      <wd-drop-menu>
        <wd-drop-menu-item v-model="equTypeId" :options="typeList" @change="handleEquType" />
        <wd-drop-menu-item v-model="status" :options="statusList" @change="handleEquStatu" />
        <wd-drop-menu-item
          v-model="equTypeId"
          label-key="dictLabel"
          value-key="dictValue"
          :options="typeList"
          @change="handleEquType"
        />
        <wd-drop-menu-item
          v-model="status"
          label-key="dictLabel"
          value-key="dictValue"
          :options="statusList"
          @change="handleEquStatu"
        />
      </wd-drop-menu>
    </template>
@@ -23,15 +35,21 @@
            <view class="flex items-center menu-title-box">
              <view class="menu-indicator"></view>
              <text class="ml-1 text-xs">{{ item.assetNo }}</text>
              <wd-tag v-if="item.status === '0'" class="ml-2" bg-color="cyan">试用</wd-tag>
              <wd-tag v-else-if="item.status === '1'" class="ml-2" type="success">使用</wd-tag>
              <wd-tag v-else-if="item.status === '2'" class="ml-2" type="danger">停用</wd-tag>
              <wd-tag v-else-if="item.status === '3'" class="ml-2" bg-color="pink">报废</wd-tag>
              <wd-tag v-else-if="item.status === '4'" class="ml-2" type="warning">闲置</wd-tag>
              <wd-tag v-else-if="item.status === '5'" class="ml-2">新增</wd-tag>
            </view>
            <view>
            <view @click.stop="handleInfo">
              <text class="icon-color-base">详情</text>
              <wd-icon name="arrow-right" custom-class="icon-color-base"></wd-icon>
            </view>
          </view>
        </template>
        <view class="flex h-[80rpx] items-center" @click.stop="itemClick(item)">
        <view class="flex h-[90rpx] items-center" @click.stop="itemClick(item)">
          <image class="slot-img text-center" src="/static/images/camera.png" />
          <view class="flex-1">
            <view class="text-color-base">
@@ -43,11 +61,7 @@
            </view>
          </view>
          <view v-if="isSelectEqu">
            <wd-button
              size="small"
              icon="edit-outline"
              @click.stop="handleSelectEqu(item)"
            >
            <wd-button size="small" icon="edit-outline" @click.stop="handleSelectEqu(item)">
              é€‰ä¸­
            </wd-button>
          </view>
@@ -59,22 +73,24 @@
<script setup lang="ts">
import { onMounted, getCurrentInstance, ref } from 'vue'
import { getEquList } from '@/service/equ'
import { DICT_SYS_EQU_STATUS, getDictInfo } from '@/service/dict'
// è®¾å¤‡ç±»åž‹
const equTypeId = ref<number>(0)
const equTypeId = ref<number>(-1)
// è®¾å¤‡çŠ¶æ€
const status = ref<number>(0)
const status = ref<number>(-1)
const isSelectEqu = ref(false)
const typeList = ref<Record<string, any>[]>([{ label: '所有设备', value: 0 }])
const statusList = ref<Record<string, any>[]>([{ label: '所有状态', value: 0 }])
const typeList = ref<Record<string, any>[]>([{ dictLabel: '设备类型', dictValue: -1 }])
const statusList = ref<Record<string, any>[]>([{ dictLabel: '所有状态', dictValue: -1 }])
function handleEquType({ value }) {
  reloadData()
  console.log(value)
}
function handleEquStatu({ value }) {
  reloadData()
  console.log(value)
}
@@ -82,9 +98,19 @@
const dataList = ref([])
const queryList = (pageNum?: number, pageSize?: number) => {
  // è¿™é‡Œçš„pageNo和pageSize会自动计算好,直接传给服务器即可
  // è¿™é‡Œçš„请求只是演示,请替换成自己的项目的网络请求,并在网络请求回调中通过paging.value.complete(请求回来的数组)将请求结果传给z-paging
  getEquList({ pageNum, pageSize })
  const parmams = {
    pageNum,
    pageSize,
    equTypeId: equTypeId.value,
    status: status.value,
  }
  if (equTypeId.value === -1) {
    delete parmams.equTypeId
  }
  if (status.value === -1) {
    delete parmams.status
  }
  getEquList(parmams)
    .then((res: any) => {
      // è¯·å‹¿åœ¨ç½‘络请求回调中给dataList赋值!!只需要调用complete就可以了
      paging.value.completeByTotal(res.rows, res.total)
@@ -101,10 +127,13 @@
 * è®¾å¤‡æ¡ç›®ç‚¹å‡»äº‹ä»¶
 * @param item
 */
function itemClick(item: any) {
function itemClick(item: any) {}
function handleInfo() {
  uni.showToast({
    title: '功能开发中',
    icon: 'none',
  })
}
/**
 * å…¶å®ƒé¡µé¢é€‰æ‹©è®¾å¤‡
 * @param item
@@ -126,7 +155,6 @@
  })
}
const eventChannel = ref<any>()
onMounted(() => {
  const instance: any = getCurrentInstance().proxy
@@ -136,6 +164,19 @@
    isSelectEqu.value = true
    console.log('OnSelectEqu', data)
  })
})
function reloadData() {
  paging.value.reload()
}
async function initData() {
  const sList: any = await getDictInfo(DICT_SYS_EQU_STATUS)
  statusList.value.push(...sList)
}
onLoad(() => {
  initData()
})
</script>
@@ -163,4 +204,7 @@
:deep(.wd-card__footer) {
  padding: 10rpx !important;
}
:deep(.wd-card__title-content) {
  padding: 16rpx !important;
}
</style>
eims-ui-mobile/src/pages/equ/index.vue
@@ -3,31 +3,58 @@
  layout: 'tabbar',
  needLogin: true,
  style: {
    navigationBarTitleText: '关于',
    navigationBarTitleText: '设备',
  },
}
</route>
<template>
  <view
    class="bg-white overflow-hidden pt-2 px-4"
    :style="{ marginTop: safeAreaInsets?.top + 'px' }"
  >
    <view class="text-center text-3xl mt-8">
      é¸½å‹ä»¬å¥½ï¼Œæˆ‘是
      <text class="text-red-500">菲鸽</text>
    </view>
    <RequestComp />
    <UploadComp />
  <view class="bg-base" :style="{ marginTop: safeAreaInsets?.top + 'px' }">
    <wd-cell-group border>
      <wd-cell
        title="设备列表"
        is-link
        to="/pages/equ/equ-list"
        icon="list"
        custom-icon-class="icon-color-base"
      />
      <wd-cell
        title="重点设备"
        is-link
        icon="keywords"
        custom-icon-class="icon-color-base"
        @click="handleInfo"
      />
      <wd-cell
        title="添加设备"
        is-link
        icon="add"
        custom-icon-class="icon-color-base"
        @click="handleInfo"
      />
    </wd-cell-group>
    <wd-cell-group border class="mt-2">
      <wd-cell
        title="设备盘点"
        is-link
        icon="filter"
        custom-icon-class="icon-color-base"
        @click="handleInfo"
      />
    </wd-cell-group>
  </view>
</template>
<script lang="ts" setup>
import RequestComp from './components/request.vue'
import UploadComp from './components/upload.vue'
// èŽ·å–å±å¹•è¾¹ç•Œåˆ°å®‰å…¨åŒºåŸŸè·ç¦»
const { safeAreaInsets } = uni.getSystemInfoSync()
function handleInfo() {
  uni.showToast({
    title: '功能开发中',
    icon: 'none',
  })
}
</script>
<style lang="scss" scoped>
eims-ui-mobile/src/pages/home/index.vue
@@ -17,13 +17,13 @@
    <view class="bg-white h-[80rpx] px-2 flex items-center justify-between">
      <view class="flex items-center" @click="handleUserInfo">
        <wd-icon name="user" size="40rpx" class="icon-color-base"></wd-icon>
        <text class="ml-1 text-color-base">张三</text>
        <text class="ml-1 text-color-base">{{ realName }}</text>
      </view>
      <view class="flex items-center">
        <wd-icon name="notification" size="40rpx" class="icon-color-base mr-3"></wd-icon>
        <wd-icon name="tips" size="40rpx" class="icon-color-base mr-3"></wd-icon>
        <wd-icon name="app" size="40rpx" class="icon-color-base"></wd-icon>
        <wd-icon name="notification" size="40rpx" class="icon-color-base mr-3" @click="handleInfo"></wd-icon>
        <wd-icon name="tips" size="40rpx" class="icon-color-base mr-3" @click="handleInfo"></wd-icon>
        <wd-icon name="app" size="40rpx" class="icon-color-base" @click="handleInfo"></wd-icon>
      </view>
    </view>
@@ -65,20 +65,20 @@
        </view>
      </wd-card>
    </view>
    <view class="bg-white mt-2">
      <wd-card type="rectangle">
        <template #title>
          <view class="flex items-center menu-title-box">
            <view class="menu-indicator"></view>
            <view class="ml-1 text-xs">设备管理</view>
            <view class="ml-1 text-xs">快捷操作</view>
          </view>
        </template>
        <wd-grid :column="4">
          <wd-grid-item
            use-slot
            class="flex justify-center items-center"
            v-for="(item, index) in equMenu"
            v-for="(item, index) in commonMenu"
            :key="item.id"
            @click.stop="goItemPage(item.path)"
          >
            <image class="slot-img text-center" :src="item.icon" />
@@ -87,13 +87,12 @@
        </wd-grid>
      </wd-card>
    </view>
    <view class="bg-white mt-2">
      <wd-card type="rectangle">
        <template #title>
          <view class="flex items-center menu-title-box">
            <view class="menu-indicator"></view>
            <view class="ml-1 text-xs">设备点检</view>
            <view class="ml-1 text-xs">设备管理</view>
          </view>
        </template>
        <wd-grid :column="4">
@@ -110,15 +109,41 @@
        </wd-grid>
      </wd-card>
    </view>
    <view class="bg-white mt-2">
      <wd-card type="rectangle">
        <template #title>
          <view class="flex items-center menu-title-box">
            <view class="menu-indicator"></view>
            <view class="ml-1 text-xs">台账相关</view>
          </view>
        </template>
        <wd-grid :column="4">
          <wd-grid-item
            use-slot
            class="flex justify-center items-center"
            v-for="(item, index) in equMenu"
            @click.stop="goItemPage(item.path)"
          >
            <image class="slot-img text-center" :src="item.icon" />
            <text>{{ item.name }}</text>
          </wd-grid-item>
        </wd-grid>
      </wd-card>
    </view>
  </view>
</template>
<script lang="ts" setup>
import { getAllMenusApi } from '@/service/menu'
import { useUserStore } from '@/store'
import { tabbarStore } from '@/components/fg-tabbar/tabbar'
defineOptions({
  name: 'Home',
})
const userStore = useUserStore()
// èŽ·å–å±å¹•è¾¹ç•Œåˆ°å®‰å…¨åŒºåŸŸè·ç¦»
const { safeAreaInsets } = uni.getSystemInfoSync()
@@ -126,6 +151,12 @@
const getAllMenus = async () => {
  const menuList = await getAllMenusApi()
  console.error(menuList)
}
function handleInfo() {
  uni.showToast({
    title: '功能开发中',
    icon: 'none',
  })
}
const goItemPage = (path: string) => {
@@ -139,17 +170,27 @@
  // getAllMenus()
})
const commonMenu = reactive([
  {
    id: 1,
    name: '故障报修',
    icon: '/static/ico/ico20.png',
    path: 'pages/repair/repair-add',
  }
])
const equMenu = reactive([
  {
    id: 1,
    name: '设备管理',
    icon: '/static/menu/menu1.png',
    name: '设备列表',
    icon: '/static/ico/ico15.png',
    path: 'pages/equ/equ-list',
  },
  {
    id: 2,
    name: '工具管理',
    icon: '/static/menu/menu1.png',
    name: '工具列表',
    icon: '/static/ico/ico16.png',
    path: 'pages/fixture/fixture-list',
  },
])
@@ -164,32 +205,41 @@
  {
    id: 1,
    name: '点检汇总',
    icon: '/static/menu/menu4.png',
    icon: '/static/ico/ico17.png',
    path: 'pages/inspect/insp-st',
  },
  {
    id: 2,
    name: '保养汇总',
    icon: '/static/menu/menu3.png',
    icon: '/static/ico/ico11.png',
    path: 'pages/maint/maint-st',
  },
  {
    id: 3,
    name: '设备报修',
    icon: '/static/menu/menu1.png',
    name: '报修列表',
    icon: '/static/ico/ico18.png',
    path: 'pages/repair/req-list',
  },
  {
    id: 4,
    name: '设备维修',
    icon: '/static/menu/menu2.png',
    name: '维修列表',
    icon: '/static/ico/ico19.png',
    path: 'pages/repair/res-list',
  },
])
function handleUserInfo() {
  getAllMenus()
  goToMy()
}
function goToMy() {
  tabbarStore.setCurIdx(4)
  uni.switchTab({
    url: '/pages/my/index',
  })
}
const realName = computed(() => userStore?.userInfo?.realName)
</script>
<style lang="scss" scoped>
eims-ui-mobile/src/pages/inspect/insp-record.vue
@@ -24,7 +24,7 @@
}
</route>
<template>
  <z-paging ref="paging" v-model="dataList" @query="queryList" show-refresher-update-time>
  <z-paging ref="paging" v-model="dataList" :auto="false" @query="queryList" show-refresher-update-time>
    <template #top>
      <wd-card type="rectangle">
        <template #title>
@@ -66,9 +66,7 @@
                <text class="ml-1">进行中</text>
              </template>
            </view>
            <view class="text-color-gray text-xs mt-2 flex">
              åˆ›å»ºæ—¶é—´: {{inspSt.createTime}}
            </view>
            <view class="text-color-gray text-xs mt-2 flex">创建时间: {{ inspSt.createTime }}</view>
          </view>
        </view>
      </wd-card>
@@ -118,7 +116,13 @@
          </view>
        </wd-collapse-item>
      </wd-collapse>
      <view class="w-full h-[1rpx] bg-base"></view>
      <view class="w-full h-[24rpx]"></view>
      <wd-cell>
        <template #title>
          <text class="text-color-gray">其它</text>
        </template>
      </wd-cell>
      <view class="w-full h-[1px] bg-base"></view>
      <wd-textarea
        label="特记事项"
        label-width="200rpx"
@@ -137,7 +141,12 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useUserStore, useAccessStore, useSystemConfigStore } from '@/store'
import { getInspStRecordList, updateInspectSt, updateInspRecordBatch } from '@/service/inspect'
import {
  getInspStRecordList,
  getInspSt,
  updateInspectSt,
  updateInspRecordBatch,
} from '@/service/inspect'
import { useToast, useMessage } from 'wot-design-uni'
import type { CollapseInstance } from 'wot-design-uni/components/wd-collapse/types'
const message = useMessage()
@@ -145,6 +154,7 @@
const collapseRef = ref<CollapseInstance>()
const isAllExpanded = ref(false)
const viewMode = ref<string>('Day')
// å®šä¹‰æŽ¥å£
interface QueryParams {
@@ -255,7 +265,7 @@
  updateInspRecordBatch(params)
    .then((res: any) => {
      updateInspSt(resolve)
      toast.success("操作成功")
      toast.success('操作成功')
    })
    .catch((res) => {
      console.error(res)
@@ -291,16 +301,40 @@
  { deep: true },
)
onLoad((options) => {
  inspSt.id = options.id
  inspSt.inspCode = options.inspCode
  inspSt.equName = options.equName
  inspSt.assetNo = options.assetNo
  inspSt.planTimeStr = options.planTimeStr
  inspSt.createTime = options.createTime
  inspSt.specialNote = options?.specialNote
  inspSt.inspUser = userStore?.userInfo?.userId
  // inspSt.id = options.id
  // inspSt.inspCode = options.inspCode
  // inspSt.equName = options.equName
  // inspSt.assetNo = options.assetNo
  // inspSt.planTimeStr = options.planTimeStr
  // inspSt.createTime = options.createTime
  // inspSt.specialNote = options?.specialNote
  // inspSt.inspUser = userStore?.userInfo?.userId
  viewMode.value = options.viewMode
  initData(options.id)
})
function initData(id: any) {
  getInspSt(id)
    .then((res: any) => {
      if (res?.id) {
        const inspCode = `${res?.equId}_${res?.planTime}_${viewMode.value}`
        inspSt.inspCode = inspCode
        Object.assign(inspSt, res)
        reloadData()
      } else {
        uni.showToast({
          title: '数据查询失败,请联系管理员',
          icon: 'none',
        })
      }
    })
    .catch((res) => {
      console.error(res)
    })
}
function reloadData() {
  paging.value.reload()
}
const dataCount = computed(() => dataList.value.length)
const checkCount = computed(() => dataList.value.filter((item) => item.status === '1').length)
const normalNum = computed(() => dataList.value.filter((item) => item.inspResult === '1').length)
eims-ui-mobile/src/pages/inspect/insp-st.vue
@@ -112,9 +112,10 @@
}
function itemClick(item) {
  const inspCode = `${item.equId}_${item.planTime}_${viewMode.value}`
  // const inspCode = `${item.equId}_${item.planTime}_${viewMode.value}`
  uni.navigateTo({
    url: `/pages/inspect/insp-record?id=${item.id}&createTime=${item.createTime}&inspCode=${inspCode}&specialNote=${item.specialNote ?? ''}&equName=${item.equName ?? ''}&assetNo=${item.assetNo ?? ''}&planTimeStr=${item.planTimeStr ?? ''}`,
    // url: `/pages/inspect/insp-record?id=${item.id}&createTime=${item.createTime}&inspCode=${inspCode}&specialNote=${item.specialNote ?? ''}&equName=${item.equName ?? ''}&assetNo=${item.assetNo ?? ''}&planTimeStr=${item.planTimeStr ?? ''}`,
    url: `/pages/inspect/insp-record?id=${item.id}&viewMode=${viewMode.value}`,
  })
}
eims-ui-mobile/src/pages/login/index.vue
@@ -54,11 +54,10 @@
import { useToast } from 'wot-design-uni'
import { login, getUserInfo } from '@/service/login'
import type { UserInfo } from '@/service/login.d'
import { TestEnum } from '@/typings'
import { tabbarStore } from '@/components/fg-tabbar/tabbar'
const userStore = useUserStore()
const accessStore = useAccessStore()
const configStore = useSystemConfigStore()
const { success: showSuccess } = useToast()
const model = reactive<{
  username: string
@@ -127,6 +126,8 @@
  userStore.setUserInfo(userInfo)
  const { query } = currRoute()
  uni.switchTab({ url: '/pages/home/index' })
  tabbarStore?.setCurIdx(0)
  tabbarStore?.setLastIdx(0)
}
</script>
eims-ui-mobile/src/pages/maint/maint-st.vue
@@ -61,9 +61,7 @@
                <text class="ml-1">进行中</text>
              </template>
            </view>
            <view class="text-color-gray text-xs mt-2 flex">
              åˆ›å»ºæ—¶é—´: {{item.createTime}}
            </view>
            <view class="text-color-gray text-xs mt-2 flex">创建时间: {{ item.createTime }}</view>
          </view>
          <wd-button size="small" icon="edit-outline" @click.stop="itemClick(item)">明细</wd-button>
        </view>
@@ -76,13 +74,29 @@
import { ref } from 'vue'
import { getMaintStList } from '@/service/maint'
/**
 * å…¶ä»–页面传过来的数据
 * assetNo: èµ„产编号
 * from: æ˜¯å¦æ˜¯æ‰«ç è¿›æ¥çš„,如果是扫码进来,只能查询固定设备的数据
 */
interface PageParams {
  assetNo?: string
  from?: string
}
interface QueryParams {
  pageNum: number
  pageSize: number
  assetNo?: string
  equName?: string
  status?: string
}
// é¡µé¢å‚数,上个页面传递过来的参数
const option = reactive<PageParams>({
  assetNo: '',
  from: '',
})
const status = ref<string>('-1')
const equName = ref<string>('-1')
@@ -117,6 +131,10 @@
  if (status.value === '-1') {
    delete params.status
  }
  // å¦‚果是从扫码页面过来,只能查询固定设备的数据
  if (option?.from === 'scan') {
    params.assetNo = option.assetNo
  }
  getMaintStList(params)
    .then((res: any) => {
@@ -140,7 +158,8 @@
function reloadData() {
  paging.value.reload()
}
onLoad(() => {
onLoad((options) => {
  Object.assign(option, options)
  uni.$on('maint-st-refresh', reloadData)
})
onUnload(() => {
eims-ui-mobile/src/pages/my/index.vue
@@ -9,11 +9,57 @@
</route>
<template>
  <view class="pt-40 text-xl text-center text-green-500">我的页面</view>
  <view class="bg-base">
    <wd-cell-group border>
      <wd-cell title="登录用户" :value="realName" icon="user" is-link />
      <wd-cell title="角色" :value="loginRoleName()" icon="bags" is-link />
      <wd-cell title="人员管理" icon="usergroup" is-link @click="handleInfo" />
    </wd-cell-group>
    <wd-cell-group border class="mt-2">
      <wd-cell title="退出登录" icon="login" is-link @click="handleLogout" />
    </wd-cell-group>
  </view>
</template>
<script lang="ts" setup>
//
import { useUserStore, useAccessStore, useSystemConfigStore } from '@/store'
import { loginRoleName } from '@/utils/RoleUtils'
import { useMessage } from 'wot-design-uni'
const message = useMessage()
const userStore = useUserStore()
const accessStore = useAccessStore()
const configStore = useSystemConfigStore()
const realName = computed(() => userStore?.userInfo?.realName)
function handleLogout() {
  if (!isLogined()) {
    uni.navigateTo({ url: '/pages/login/index' })
    return false
  }
  message
    .confirm({
      msg: '提示',
      title: '确定退出登录吗?',
    })
    .then(() => {
      userStore.clearUserInfo()
      accessStore.clearAccessInfo()
      configStore.clearConfigInfo()
      uni.navigateTo({ url: '/pages/login/index' })
    })
    .catch(() => {})
}
const isLogined = () => {
  return accessStore.isLogined
}
function handleInfo() {
  uni.showToast({
    title: '功能开发中',
    icon: 'none',
  })
}
</script>
<style lang="scss" scoped>
eims-ui-mobile/src/pages/repair/repair-add.vue
@@ -35,6 +35,7 @@
          label="故障类型"
          v-model="model.reqType"
          @confirm="handleConfirmReqType"
          :disabled="reqTypeDis"
        />
      </wd-cell-group>
@@ -181,6 +182,25 @@
const toast = useToast()
const userStore = useUserStore()
/**
 * å…¶ä»–页面传过来的数据
 * assetNo: èµ„产编号
 * from: æ˜¯å¦æ˜¯æ‰«ç è¿›æ¥çš„,如果是扫码进来,只能查询固定设备的数据
 */
interface PageParams {
  equId?: string
  equName?: string
  from?: string
}
// é¡µé¢å‚数,上个页面传递过来的参数
const option = reactive<PageParams>({
  equId: '',
  equName: '',
  from: '',
})
const reqTypeDis = ref(false)
// æŠ¥ä¿®ç±»åž‹
const reqList = ref<any>([])
// æ•…障类别
@@ -228,6 +248,9 @@
 * é€‰æ‹©è®¾å¤‡
 */
function handleSelectEqu() {
  if(reqTypeDis.value){
    return false
  }
  uni.navigateTo({
    url: '/pages/equ/equ-list',
    events: {
@@ -294,7 +317,7 @@
function handleAddRepairReq() {
  // è¡¥å……必要字段
  model.status = '0'
  model.status = '0' // æŠ¥ä¿®åŽé»˜è®¤çŠ¶æ€ä¸ºå¾…æŽ¥å•
  model.reqTime = formatDate(new Date())
  model.reqDept = userStore?.userInfo?.deptId
  model.reqUser = userStore?.userInfo?.userId
@@ -397,6 +420,15 @@
})
onLoad((options) => {
  Object.assign(option, options)
  // æ‰«ç é¡µé¢è¿›å…¥çš„一些初始化
  if (option.from === 'scan') {
    model.equId = option?.equId
    model.equName = option?.equName
    // è®¾ç½®ç±»åž‹ä¸ºè®¾å¤‡ç±»åž‹
    model.reqType = '1'
    reqTypeDis.value = true
  }
  initData()
})
</script>
eims-ui-mobile/src/pages/repair/repair-fb.vue
ÎļþÃû´Ó eims-ui-mobile/src/pages/repair/feedback.vue ÐÞ¸Ä
@@ -46,7 +46,6 @@
            </view>
          </template>
        </wd-step>
      </wd-steps>
    </wd-card>
@@ -96,10 +95,18 @@
  </view>
</template>
<script setup lang="ts">
import { getRepairRes, getRepairFb, getRepairRecordList } from '@/service/repair'
import {
  getRepairRes,
  getRepairFb,
  getRepairRecordList,
  addRepairFb,
  updateRepairFb,
} from '@/service/repair'
import { reactive } from 'vue'
import { isLeader, isOperatorOrRepair } from '@/utils/RoleUtils'
import { RepairResVO, RepairFbVO, RepairRecordVO } from '@/service/repair.d'
const isUpdate = ref(false)
const repairRes = reactive<RepairResVO>({
  id: '',
  resCode: '',
@@ -118,6 +125,7 @@
const repairFb = reactive<RepairFbVO>({
  id: '',
  resId: '',
  resCode: '',
  fbResult: '',
  suggestions: '',
@@ -158,7 +166,6 @@
    .catch((res) => {})
}
function initRepairRes(id: any) {
  getRepairRes(id)
    .then((res: any) => {
@@ -174,14 +181,61 @@
function getFeedBack(id: any) {
  getRepairFb(id)
    .then((res: any) => {
      // åœ¨è¿™é‡Œè¿›è¡Œæ•°æ®ç±»åž‹è½¬æ¢
      res.repairSatisfaction = Number(res?.repairSatisfaction)
      res.repairTimeliness = Number(res?.repairTimeliness)
      res.serviceAttitude = Number(res?.serviceAttitude)
      res.repairSs = Number(res?.repairSs)
      Object.assign(repairFb, res)
    })
    .catch((res) => {})
}
async function initData(options: any) {
  initRepairRes(options.id)
function handleRepairFb() {
  if(isOperatorOrRepair()){
    uni.showToast({
      title: '无权限,请登录管理员账号操作',
      icon: 'none',
    })
    return false
}
  const id = repairFb.id
  isUpdate.value = !!id
  if (isUpdate.value) {
    updateRepairFb(repairFb)
      .then((res: any) => {
        if (res?.code === 200) {
          uni.showToast({
            title: '修改成功',
            icon: 'none',
          })
        }
      })
      .catch((res) => {})
  } else {
    addRepairFb(repairFb)
      .then((res: any) => {
        if (res?.code === 200) {
          uni.showToast({
            title: '评价成功',
            icon: 'none',
          })
        }
      })
      .catch((res) => {})
  }
}
async function initData(options: any) {
  repairFb.resId = options.id
  initRepairRes(options.id)
}
onNavigationBarButtonTap((e) => {
  if (e.index === 0) {
    handleRepairFb()
  }
})
onLoad((options) => {
  initData(options)
eims-ui-mobile/src/pages/repair/res-list.vue
@@ -140,9 +140,8 @@
                  size="small"
                  icon="edit-outline"
                  @click.stop="goToFeedBack(item)"
                  v-if="item.fbId === null"
                >
                  å†™è¯„ä»·
                  æŸ¥çœ‹è¯„ä»·
                </wd-button>
              </view>
            </template>
@@ -176,9 +175,8 @@
                  size="small"
                  icon="edit-outline"
                  @click.stop="goToFeedBack(item)"
                  v-if="item.fbId === null"
                >
                  å†™è¯„ä»·
                  {{ item.fbId == null ? '写评价' : '查看评价' }}
                </wd-button>
              </view>
            </template>
@@ -201,15 +199,32 @@
const message = useMessage()
const toast = useToast()
/**
 * å…¶ä»–页面传过来的数据
 * assetNo: èµ„产编号
 * from: æ˜¯å¦æ˜¯æ‰«ç è¿›æ¥çš„,如果是扫码进来,只能查询固定设备的数据
 */
interface PageParams {
  assetNo?: string
  from?: string
}
// é¡µé¢å‚数,上个页面传递过来的参数
const option = reactive<PageParams>({
  assetNo: '',
  from: '',
})
// ç»´ä¿®å•类型
const resTypeId = ref<number>(0)
const resTypeId = ref<number>(-1)
// ç»´ä¿®å•处理状态
const status = ref<number>(0)
const status = ref<number>(-1)
const isSelectRes = ref(false)
const resTypeList = ref<any>([{ dictLabel: '所有类型', dictValue: 0 }])
const statusList = ref<any>([{ dictLabel: '所有状态', dictValue: 0 }])
const resTypeList = ref<any>([{ dictLabel: '所有类型', dictValue: -1 }])
const statusList = ref<any>([{ dictLabel: '所有状态', dictValue: -1 }])
function handleResType({ value }) {
  reloadData()
}
@@ -221,19 +236,23 @@
const dataList = ref([])
const queryList = (pageNum?: number, pageSize?: number) => {
  const parmams = {
  const params: any = {
    pageNum,
    pageSize,
    reqType: resTypeId.value,
    status: status.value,
  }
  if (resTypeId.value === 0) {
    delete parmams.reqType
  if (resTypeId.value === -1) {
    delete params.reqType
  }
  if (status.value === 0) {
    delete parmams.status
  if (status.value === -1) {
    delete params.status
  }
  getRepairResList(parmams)
  // å¦‚果是从扫码页面过来,只能查询固定设备的数据
  if (option?.from === 'scan') {
    params.assetNo = option.assetNo
  }
  getRepairResList(params)
    .then((res: any) => {
      paging.value.completeByTotal(res.rows, res.total)
    })
@@ -308,7 +327,7 @@
function goToFeedBack(item) {
  uni.navigateTo({
    url: `/pages/repair/feedback?id=${item.id}`,
    url: `/pages/repair/repair-fb?id=${item.id}`,
  })
}
@@ -373,7 +392,8 @@
  const sList: any = await getDictInfo(DICT_REPAIR_RES_STATUS)
  statusList.value.push(...sList)
}
onLoad(() => {
onLoad((options) => {
  Object.assign(option, options)
  initData()
  uni.$on('res-list-refresh', reloadData)
})
eims-ui-mobile/src/pages/scan/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,215 @@
<template>
  <view class="bg-base">
    <view v-if="exist">
      <wd-cell>
        <template #title>
          <text class="text-color-gray">设备图片</text>
        </template>
      </wd-cell>
      <view class="h-[1px] bg-base"></view>
      <image class="equ-img" src="/static/images/cgq.png" />
      <wd-cell class="mt-2">
        <template #title>
          <text class="text-color-gray">设备信息</text>
        </template>
      </wd-cell>
      <wd-card type="rectangle">
        <template #title>
          <view class="flex justify-between items-baseline">
            <view class="flex items-center menu-title-box">
              <view class="menu-indicator"></view>
              <text class="ml-1 text-xs">{{ model.assetNo }}</text>
              <wd-tag v-if="model.status === '0'" class="ml-2" bg-color="cyan">试用</wd-tag>
              <wd-tag v-else-if="model.status === '1'" class="ml-2" type="success">使用</wd-tag>
              <wd-tag v-else-if="model.status === '2'" class="ml-2" type="danger">停用</wd-tag>
              <wd-tag v-else-if="model.status === '3'" class="ml-2" bg-color="pink">报废</wd-tag>
              <wd-tag v-else-if="model.status === '4'" class="ml-2" type="warning">闲置</wd-tag>
              <wd-tag v-else-if="model.status === '5'" class="ml-2">新增</wd-tag>
            </view>
            <view @click="handleInfo">
              <text class="icon-color-base">详情</text>
              <wd-icon name="arrow-right" custom-class="icon-color-base"></wd-icon>
            </view>
          </view>
        </template>
        <view class="flex h-[90rpx] items-center">
          <image class="slot-img text-center" src="/static/images/camera.png" />
          <view class="flex-1">
            <view class="text-color-base">
              {{ model.equName }}
              <text class="text-color-gray ml-2 text-mini">{{ model.modelNo }}</text>
            </view>
            <view class="text-color-gray text-xs mt-1">
              {{ model.location }} | {{ model.madeIn }}
            </view>
          </view>
        </view>
      </wd-card>
      <view class="mt-2">
        <wd-cell class="mt-2">
          <template #title>
            <text class="text-color-gray">操作</text>
          </template>
        </wd-cell>
        <view class="h-[1px] bg-base"></view>
        <view class="bg-white flex justify-around py-4">
          <wd-button icon="edit-outline" @click.stop="handleInsp">点检</wd-button>
          <wd-button icon="laptop" @click.stop="handMaint">保养</wd-button>
          <wd-button icon="tools" @click.stop="showActions">ç»´ä¿®</wd-button>
        </view>
      </view>
      <wd-action-sheet
        v-model="show"
        :actions="actions"
        @close="close"
        @select="select"
        cancel-text="取消"
      />
    </view>
    <view v-else>
      <wd-status-tip image="search" tip="当前搜索无结果" />
      <view class="w-full flex justify-center">{{ scanResult }}</view>
    </view>
  </view>
</template>
<script setup lang="ts">
import dayjs from 'dayjs'
import type { EquVO } from '@/service/equ.d'
import { useToast, useMessage } from 'wot-design-uni'
import { getEquByAssetNo } from '@/service/equ'
import { getInspStByStId } from '@/service/inspect'
const message = useMessage()
const toast = useToast()
const model = reactive<EquVO>({})
const scanResult = ref<string>('')
const show = ref<boolean>(false)
const exist = ref<boolean>(false)
const actions = ref([
  {
    name: '新增报修',
  },
  {
    name: '去维修',
  },
])
function initData(assetNo: any) {
  getEquByAssetNo(assetNo)
    .then((res: any) => {
      if (res.data) {
        Object.assign(model, res)
      } else {
        toast.error('未查询到该资产编号相关数据!')
      }
    })
    .catch((res) => {
      console.error(res)
      toast.error(res?.data?.msg || '请求失败')
    })
}
function handleInfo() {
  uni.showToast({
    title: '功能开发中',
    icon: 'none',
  })
}
function handleInsp() {
  // æ‹¼æŽ¥å‡ºst_id (由日期+设备id组成)
  const today = dayjs().format('YYYYMMDD')
  const stId = `${today}_${model.equId}`
  getInspStByStId(stId).then((res: any) => {
    if (res?.id) {
      uni.navigateTo({
        url: `/pages/inspect/insp-record?id=${res?.id}&viewMode=Day`,
      })
    } else {
      uni.showToast({
        title: '设备今天没有点检记录,请联系管理员!',
        icon: 'none',
      })
    }
  })
}
function handMaint() {
  if (!model?.assetNo) {
    uni.showToast({
      title: '未查询到设备,请联系管理员!',
      icon: 'none',
    })
    return false
  }
  uni.navigateTo({
    url: `/pages/maint/maint-st?assetNo=${model?.assetNo}&from=scan`,
  })
}
function showActions() {
  show.value = true
}
function close() {
  show.value = false
}
function select({ item, index }) {
  console.error(model?.equId)
  console.error(!model?.equId)
  if (!model?.equId) {
    uni.showToast({
      title: '未查询到设备,请联系管理员!',
      icon: 'none',
    })
    return false
  }
  switch (index) {
    case 0:
      uni.navigateTo({
        url: `/pages/repair/repair-add?equId=${model?.equId}&equName=${model?.equName}&from=scan`,
      })
      break
    case 1:
      uni.navigateTo({
        url: `/pages/repair/res-list?assetNo=${model?.assetNo}&from=scan`,
      })
      break
  }
}
onLoad((options) => {
  scanResult.value = options?.result
  initData(options?.result)
})
</script>
<style scoped lang="scss">
.equ-img {
  width: 100%;
  height: 300rpx;
}
.slot-img {
  width: 72rpx;
  height: 72rpx;
  margin-right: 24rpx;
}
.text-mini {
  font-size: 22rpx;
}
.menu-indicator {
  width: 6rpx;
  height: 22rpx;
  border-radius: 10rpx;
  background-color: $uni-color-primary;
}
:deep(.wd-card__footer) {
  padding: 10rpx !important;
}
:deep(.wd-card__title-content) {
  padding: 16rpx 0 !important;
}
</style>
eims-ui-mobile/src/pages/spare/index.vue
@@ -3,19 +3,79 @@
  layout: 'tabbar',
  needLogin: true,
  style: {
    navigationBarTitleText: 'spare',
    navigationBarTitleText: '备件',
  },
}
</route>
<template>
  <view class="pt-40 text-xl text-center text-green-500">备件</view>
  <view class="bg-base">
    <view class="flex px-4 py-3 bg-white">
      <div class="box-border h-[150rpx] flex-1 bg-tag rounded-sm mr-2 px-2 py-2">
        <wd-count-to
          :startVal="0"
          :endVal="0"
          :fontSize="24"
          color="text-color-base"
        ></wd-count-to>
        <view class="text-color-gray mt-1">库存不足</view>
      </div>
      <div class="box-border h-[150rpx] flex-1 bg-tag rounded-sm mr-2 px-2 py-2">
        <wd-count-to
          :startVal="0"
          :endVal="0"
          :fontSize="24"
          color="text-color-base"
        ></wd-count-to>
        <view class="text-color-gray mt-1">库存过量</view>
      </div>
    </view>
    <wd-cell-group border>
      <wd-cell
        title="备件列表"
        is-link
        to="/pages/spare/spare-list"
        icon="list"
        custom-icon-class="icon-color-base"
      />
      <wd-cell
        title="添加备件"
        is-link
        icon="add"
        custom-icon-class="icon-color-base"
        @click="handleInfo"
      />
    </wd-cell-group>
    <wd-cell-group border class="mt-2">
      <wd-cell
        title="添加出库"
        is-link
        icon="add-circle"
        custom-icon-class="icon-color-base"
        @click="handleInfo"
      />
      <wd-cell
        title="添加入库"
        is-link
        icon="add-circle"
        custom-icon-class="icon-color-base"
        @click="handleInfo"
      />
    </wd-cell-group>
  </view>
</template>
<script lang="ts" setup>
//
function handleInfo() {
  uni.showToast({
    title: '功能开发中',
    icon: 'none',
  })
}
</script>
<style lang="scss" scoped>
//
.bg-tag {
  background: #f5f8ff;
}
</style>
eims-ui-mobile/src/pages/spare/spare-list.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,156 @@
<route lang="json5" type="page">
{
  layout: 'default',
  needLogin: true,
  style: {
    navigationBarTitleText: '备件列表',
  },
}
</route>
<template>
  <z-paging ref="paging" v-model="dataList" @query="queryList" show-refresher-update-time>
    <template #top>
      <wd-drop-menu>
        <wd-drop-menu-item v-model="typeId" :options="typeList" @change="handleSpareType" />
        <wd-drop-menu-item v-model="status" :options="statusList" @change="handleSpareStatu" />
      </wd-drop-menu>
    </template>
    <view class="bg-base">
      <wd-card type="rectangle" v-for="(item, index) in dataList" :key="item.id">
        <template #title>
          <view class="flex justify-between items-baseline">
            <view class="flex items-center menu-title-box">
              <view class="menu-indicator"></view>
              <text class="ml-1 text-xs">{{ item.code }}</text>
            </view>
            <view>
              <text class="icon-color-base">详情</text>
              <wd-icon name="arrow-right" custom-class="icon-color-base"></wd-icon>
            </view>
          </view>
        </template>
        <view class="flex h-[80rpx] items-center" @click.stop="itemClick(item)">
          <image class="slot-img text-center" src="/static/images/camera.png" />
          <view class="flex-1">
            <view class="text-color-base">
              {{ item.name }}
              <text class="text-color-gray ml-2 text-mini">{{ item.modelNo }}</text>
            </view>
            <view class="text-color-gray text-xs mt-1">
              åº“å­˜: {{ item.actualStock }} | å•ä»·: {{ item.referPrice }}
            </view>
            <view class="text-color-gray text-xs mt-1">
              ä¾›åº”商: {{ item.supplier }}
            </view>
          </view>
          <view v-if="isSelectSpare">
            <wd-button size="small" icon="edit-outline" @click.stop="handleSelectSpare(item)">
              é€‰ä¸­
            </wd-button>
          </view>
        </view>
      </wd-card>
    </view>
  </z-paging>
</template>
<script setup lang="ts">
import { onMounted, getCurrentInstance, ref } from 'vue'
import { getSpareList } from '@/service/spare'
// å¤‡ä»¶ç±»åž‹
const typeId = ref<number>(-1)
// å¤‡ä»¶çŠ¶æ€
const status = ref<number>(-1)
const isSelectSpare = ref(false)
const typeList = ref<Record<string, any>[]>([{ label: '备件类型', value: -1 }])
const statusList = ref<Record<string, any>[]>([{ label: '所有状态', value: -1 }])
function handleSpareType({ value }) {
  console.log(value)
}
function handleSpareStatu({ value }) {
  console.log(value)
}
const paging = ref(null)
const dataList = ref([])
const queryList = (pageNum?: number, pageSize?: number) => {
  getSpareList({ pageNum, pageSize })
    .then((res: any) => {
      paging.value.completeByTotal(res.rows, res.total)
    })
    .catch((res) => {
      paging.value.complete(false)
    })
}
/**
 * å¤‡ä»¶æ¡ç›®ç‚¹å‡»äº‹ä»¶
 * @param item
 */
function itemClick(item: any) {}
/**
 * å…¶å®ƒé¡µé¢é€‰æ‹©å¤‡ä»¶
 * @param item
 */
function handleSelectSpare(item: any) {
  if (isSelectSpare.value) {
    emitSelectSpare(item)
    uni.navigateBack()
  }
}
/**
 * é€‰æ‹©å¤‡ä»¶å›žè°ƒ
 * @param spare
 */
function emitSelectSpare(spare: any) {
  eventChannel.value.emit('selectSpare', {
    data: spare,
  })
}
const eventChannel = ref<any>()
onMounted(() => {
  const instance: any = getCurrentInstance().proxy
  const event = instance.getOpenerEventChannel()
  eventChannel.value = event
  event.on('OnSelectSpare', function (data) {
    isSelectSpare.value = true
    console.log('OnSelectSpare', data)
  })
})
</script>
<style scoped lang="scss">
.menu-title-box {
  height: 30rpx;
  line-height: 30rpx;
}
.slot-img {
  width: 72rpx;
  height: 72rpx;
  margin-right: 24rpx;
}
.text-mini {
  font-size: 22rpx;
}
.menu-indicator {
  width: 6rpx;
  height: 22rpx;
  border-radius: 10rpx;
  background-color: $uni-color-primary;
}
:deep(.wd-card__footer) {
  padding: 10rpx !important;
}
</style>
eims-ui-mobile/src/service/dict.ts
@@ -8,6 +8,9 @@
export const DICT_REPAIR_REQ_STATUS = 'repair_req_status'
export const DICT_REPAIR_RES_STATUS = 'repair_res_status'
export const DICT_SYS_EQU_STATUS = 'sys_equ_status'
export const getDictInfo = (dictType: string) => {
  return http.get<DictData[]>(`/system/dict/data/type/${dictType}`)
}
eims-ui-mobile/src/service/equ.d.ts
@@ -2,123 +2,123 @@
  /**
   *
   */
  equId: number | string;
  equId?: number | string;
  /**
   * èµ„产编号
   */
  assetNo: string;
  assetNo?: string;
  /**
   * è®¾å¤‡ç¼–码
   */
  equCode: string;
  equCode?: string;
  /**
   * è®¾å¤‡åç§°
   */
  equName: string;
  equName?: string;
  /**
   * è®¾å¤‡ç±»åž‹
   */
  equTypeName: string;
  equTypeName?: string;
  /**
   * åž‹å·
   */
  modelNo: string;
  modelNo?: string;
  /**
   * åˆ¶é€ å•†
   */
  madeIn: string;
  madeIn?: string;
  /**
   * é¢åº¦åŠŸçŽ‡
   */
  ratedPower: number;
  ratedPower?: number;
  /**
   * é“­ç‰Œä¿¡æ¯
   */
  plateInfo: string;
  plateInfo?: string;
  /**
   * é‡‡è´­æ—¥æœŸ
   */
  purchaseDate: string;
  purchaseDate?: string;
  /**
   * çŠ¶æ€
   */
  status: string;
  status?: string;
  /**
   * æ‰€åœ¨åœºæ‰€
   */
  location: string;
  location?: string;
  /**
   * ä½¿ç”¨éƒ¨é—¨ï¼ˆå…³è”id)
   */
  deptUsed: number;
  deptUsed?: number;
  /**
   * ä½¿ç”¨éƒ¨é—¨åç§°
   */
  deptName: number;
  deptName?: number;
  /**
   * è´£ä»»äºº(关联id)
   */
  respPerson: number;
  respPerson?: number;
  /**
   * è´£ä»»äºº
   */
  respPersonName: string;
  respPersonName?: string;
  /**
   * è”系电话
   */
  contactPhone: string;
  contactPhone?: string;
  /**
   * æ­£å¼ä½¿ç”¨æ—¥æœŸ
   */
  deployDate: string;
  deployDate?: string;
  /**
   * å¼€å§‹è¯•用日期
   */
  trialDate: string;
  trialDate?: string;
  /**
   * è®¡åˆ’验收日期
   */
  planAcceptDate: string;
  planAcceptDate?: string;
  /**
   * å®žé™…验收日期
   */
  actualAcceptDate: string;
  actualAcceptDate?: string;
  /**
   * å¯¼å…¥çŠ¶æ€ï¼ˆå­—å…¸ï¼‰
   */
  importStatus: number;
  importStatus?: number;
  /**
   * ç›˜ç‚¹æ ‡å¿—
   */
  inventoryFlag: number;
  inventoryFlag?: number;
  /**
   * ä¸Šæ¬¡ç›˜ç‚¹æ—¥æœŸ
   */
  inventoryDate: string;
  inventoryDate?: string;
  /**
   * ä½¿ç”¨å¹´é™
   */
  serviceLife: number;
  serviceLife?: number;
}
eims-ui-mobile/src/service/equ.ts
@@ -7,3 +7,11 @@
export const getEquList = (params: any) => {
  return http.get<EquVO[]>('/eims/equ/list', params)
}
/**
 * æ ¹æ®èµ„产编号查询设备
 * @param id
 */
export const getEquByAssetNo = (assetNo: string) => {
  return http.get<EquVO>(`/eims/equ/info/${assetNo}`)
}
eims-ui-mobile/src/service/inspect.ts
@@ -1,6 +1,6 @@
import { http } from '@/utils/http'
import type { InspectStVO, InspectRecordVO } from './inspect.d'
type ID = number | string
/**
 * ç‚¹æ£€æ±‡æ€»åˆ—表
 */
@@ -9,6 +9,22 @@
}
/**
 * æ ¹æ®id查询汇总
 * @param id
 */
export const getInspSt = (id: ID) => {
  return http.get<InspectStVO>(`/eims/inspectSt/${id}`)
}
/**
 * æ ¹æ®id查询汇总
 * @param stId
 */
export const getInspStByStId = (stId: string) => {
  return http.get<InspectStVO>(`/eims/inspectSt/info/${stId}`)
}
/**
 * ç‚¹æ£€æ±‡æ€»åˆ—表下点检记录列表
 */
export const getInspStRecordList = (params: any) => {
eims-ui-mobile/src/service/repair.d.ts
@@ -206,22 +206,22 @@
  /**
   * ç»´ä¿®åŠæ—¶æ€§(字典)
   */
  repairTimeliness?: number | string;
  repairTimeliness?: number ;
  /**
   * æœåŠ¡æ€åº¦
   */
  serviceAttitude?: number | string;
  serviceAttitude?: number ;
  /**
   * ç»´ä¿®çŽ°åœº6s
   */
  repairSs?: number | string;
  repairSs?: number ;
  /**
   * ç»´ä¿®æ»¡æ„åº¦
   */
  repairSatisfaction?: number | string;
  repairSatisfaction?: number ;
  /**
   * æ„è§æˆ–建议
eims-ui-mobile/src/service/repair.ts
@@ -72,8 +72,13 @@
  return http.post<void>('/eims/repairFb', data)
}
/**
 * ç¼–辑维修评价
 * @param data
 */
export const updateRepairFb = (data: any) => {
  return http.put<void>('/eims/repairFb', data)
}
/**
 * ç»´ä¿®è®°å½•列表
eims-ui-mobile/src/service/spare.d.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,90 @@
export interface SpareVO {
  /**
   *
   */
  id: number | string;
  /**
   * ç±»åž‹
   */
  type: number;
  /**
   * å¤‡ä»¶åç§°
   */
  name: string;
  /**
   * å¤‡ä»¶ç¼–码
   */
  code: string;
  /**
   * å¤‡ä»¶å›¾ç‰‡
   */
  img: number;
  /**
   * å¤‡ä»¶å›¾ç‰‡Url
   */
  imgUrl: string;
  /**
   * åž‹å·
   */
  modelNo: string;
  /**
   * åˆ¶é€ å•†
   */
  madeIn: string;
  /**
   * ä¾›åº”商
   */
  supplier: string;
  /**
   * è®¡é‡å•位(字典)
   */
  unit: string;
  /**
   * å‚考价格
   */
  referPrice: number;
  /**
   * åº“存上限
   */
  upperStock: number;
  /**
   * åº“存下限
   */
  lowerStock: number;
  /**
   * å®žé™…库存
   */
  actualStock: number;
  /**
   * åº“存金额
   */
  stockAmount: number;
  /**
   * æ›´æ¢å‘¨æœŸ
   */
  replaceCycle: number;
  /**
   * æ›´æ¢å‘¨æœŸå•位(字典)
   */
  cycleUnit: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
eims-ui-mobile/src/service/spare.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
import { http } from '@/utils/http'
import type { SpareVO } from './spare.d'
/**
 * å¤‡ä»¶åˆ—表
 */
export const getSpareList = (params: any) => {
  return http.get<SpareVO[]>('/eims/spare/list', params)
}
eims-ui-mobile/src/static/ico/ico1.png
eims-ui-mobile/src/static/ico/ico10.png
eims-ui-mobile/src/static/ico/ico11.png
eims-ui-mobile/src/static/ico/ico12.png
eims-ui-mobile/src/static/ico/ico13.png
eims-ui-mobile/src/static/ico/ico14.png
eims-ui-mobile/src/static/ico/ico15.png
eims-ui-mobile/src/static/ico/ico16.png
eims-ui-mobile/src/static/ico/ico17.png
eims-ui-mobile/src/static/ico/ico18.png
eims-ui-mobile/src/static/ico/ico19.png
eims-ui-mobile/src/static/ico/ico2.png
eims-ui-mobile/src/static/ico/ico20.png
eims-ui-mobile/src/static/ico/ico3.png
eims-ui-mobile/src/static/ico/ico4.png
eims-ui-mobile/src/static/ico/ico5.png
eims-ui-mobile/src/static/ico/ico6.png
eims-ui-mobile/src/static/ico/ico7.png
eims-ui-mobile/src/static/ico/ico8.png
eims-ui-mobile/src/static/ico/ico9.png
eims-ui-mobile/src/static/images/cgq.png
eims-ui-mobile/src/style/index.scss
@@ -57,5 +57,3 @@
  background: $uni-color-primary;
}
eims-ui-mobile/src/types/uni-pages.d.ts
@@ -16,12 +16,14 @@
       "/pages/maint/maint-st" |
       "/pages/maint/order-detail" |
       "/pages/my/index" |
       "/pages/repair/feedback" |
       "/pages/repair/repair-add" |
       "/pages/repair/repair-fb" |
       "/pages/repair/req-list" |
       "/pages/repair/res-detail" |
       "/pages/repair/res-list" |
       "/pages/spare/index";
       "/pages/scan/index" |
       "/pages/spare/index" |
       "/pages/spare/spare-list";
}
interface RedirectToOptions extends NavigateToOptions {}
eims-ui-mobile/src/utils/RoleUtils.ts
@@ -39,3 +39,22 @@
    roles.includes(ROLE_LINE) || roles.includes(ROLE_SUPER_ADMIN) || roles.includes(ROLE_LEADER)
  )
}
export const loginRoleName = () => {
  const roles = useUserStore()?.userInfo?.roles || []
  if (roles.includes(ROLE_SUPER_ADMIN)) {
    return '超级管理员'
  }
  if (roles.includes(ROLE_LEADER)) {
    return '管理员'
  }
  if (roles.includes(ROLE_OPERATOR)) {
    return '操作员'
  }
  if (roles.includes(ROLE_LINE)) {
    return '线长'
  }
  if (roles.includes(ROLE_REPAIR)) {
    return '维修工'
  }
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsEquController.java
@@ -77,6 +77,18 @@
    }
    /**
     * èŽ·å–ã€è®¾å¤‡å°è´¦ã€‘è¯¦ç»†ä¿¡æ¯
     *
     * @param assetNo
     */
    @SaCheckPermission("eims:equ:query")
    @GetMapping("/info/{assetNo}")
    public R<EimsEquVo> getInfoByAssetNo(@NotNull(message = "资产编号不能为空")
                                @PathVariable String assetNo) {
        return R.ok(eimsEquipmentService.queryByAssetNo(assetNo));
    }
    /**
     * æ–°å¢žã€è®¾å¤‡å°è´¦ã€‘
     */
    @SaCheckPermission("eims:equ:add")
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/controller/EimsInspectStController.java
@@ -68,6 +68,13 @@
        return R.ok(eimsInspectStService.queryById(id));
    }
    @SaCheckPermission("eims:inspectSt:query")
    @GetMapping("/info/{stId}")
    public R<EimsInspectStVo> getInfoByStid(@NotNull(message = "主键不能为空")
                                      @PathVariable String stId) {
        return R.ok(eimsInspectStService.queryByStId(stId));
    }
    /**
     * æ–°å¢žç‚¹æ£€æ±‡æ€»
     */
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/domain/bo/EimsRepairResBo.java
@@ -116,6 +116,7 @@
    // å…³è”表字段
    private  String reqCode;//报修单编码
    private  String reqType;//报修单类型
    private  String assetNo;//设备资产编号
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/IEimsInspectStService.java
@@ -1,5 +1,6 @@
package org.dromara.eims.service;
import jakarta.validation.constraints.NotNull;
import org.dromara.eims.domain.vo.EimsInspectStVo;
import org.dromara.eims.domain.bo.EimsInspectStBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -23,7 +24,7 @@
     * @return ç‚¹æ£€æ±‡æ€»
     */
    EimsInspectStVo queryById(Long id);
    EimsInspectStVo queryByStId(String stId);
    /**
     * åˆ†é¡µæŸ¥è¯¢ç‚¹æ£€æ±‡æ€»åˆ—表
     *
@@ -65,4 +66,6 @@
     * @return æ˜¯å¦åˆ é™¤æˆåŠŸ
     */
    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsInspectStServiceImpl.java
@@ -10,8 +10,10 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.eims.domain.EimsEqu;
import org.dromara.eims.domain.EimsInspectRecord;
import org.dromara.eims.domain.vo.EimsInspectRecordVo;
import org.dromara.eims.mapper.EimsEquMapper;
import org.dromara.eims.mapper.EimsInspectRecordMapper;
import org.springframework.stereotype.Service;
import org.dromara.eims.domain.bo.EimsInspectStBo;
@@ -39,6 +41,7 @@
public class EimsInspectStServiceImpl implements IEimsInspectStService {
    private final EimsInspectStMapper baseMapper;
    private final EimsEquMapper equMapper;
    private final EimsInspectRecordMapper recordMapper;
    /**
@@ -50,16 +53,36 @@
    @Override
    public EimsInspectStVo queryById(Long id){
        EimsInspectStVo stVo = baseMapper.selectVoById(id);
        if(stVo!=null&&stVo.getEquId()!=null){
            EimsEqu eimsEqu = equMapper.selectById(stVo.getEquId());
            stVo.setEquName(eimsEqu.getEquName());
            stVo.setAssetNo(eimsEqu.getAssetNo());
        }
        // fillStDataSingle(stVo);
        return stVo;
    }
    @Override
    public EimsInspectStVo queryByStId(String stId) {
        QueryWrapper<EimsInspectSt> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("st_id", stId);
        EimsInspectStVo stVo = baseMapper.selectVoOne(queryWrapper);
        if(stVo!=null&&stVo.getEquId()!=null){
            EimsEqu eimsEqu = equMapper.selectById(stVo.getEquId());
            stVo.setEquName(eimsEqu.getEquName());
            stVo.setAssetNo(eimsEqu.getAssetNo());
        }
        // fillStDataSingle(stVo);
        return stVo;
    }
    /**
     *
     * @param stVo
     * @param type Day-日视图 Month-月视图
     * @param stVo type Day-日视图 Month-月视图
     * @param
     */
    private void fillStDataSingle(EimsInspectStVo stVo,String type) {
    private void fillStDataSingle(EimsInspectStVo stVo) {
            LambdaQueryWrapper<EimsInspectRecord> recordLqw = Wrappers.lambdaQuery();
            recordLqw.eq(EimsInspectRecord::getEquId, stVo.getEquId());
@@ -69,7 +92,7 @@
            LocalDate endOfMonth = planTime.with(TemporalAdjusters.lastDayOfMonth());
            // æ—¥è§†å›¾æŸ¥è¯¢èŒƒå›´
            if(type.equals("Day")){
            if(stVo.getType().equals("Day")){
                recordLqw.between(EimsInspectRecord::getPlanTime, planTime, planTime);
            }else {
                //  æœˆè§†å›¾æŸ¥è¯¢èŒƒå›´
eims/ruoyi-modules/lb-eims/src/main/java/org/dromara/eims/service/impl/EimsRepairResServiceImpl.java
@@ -296,6 +296,7 @@
        qw.eq(bo.getResUser() != null, "res.res_user", bo.getResUser());
        qw.eq(bo.getReqType() != null, "req.req_type", bo.getReqType());
        qw.eq(bo.getReqUser() != null, "res.req_user", bo.getReqUser());
        qw.eq(bo.getAssetNo() != null, "equ.asset_no", bo.getAssetNo());
        List<Long> resDeptIds = getAllDescendantIds(bo.getResDept());
        qw.in(bo.getResDept() != null, "res.res_dept", resDeptIds);