yangguanjin 4 недель назад
Родитель
Сommit
e80845ddb9

+ 3 - 0
src/App.vue

@@ -1,6 +1,7 @@
 <script lang="ts">
 import { onLaunch, onShow, onHide, onLoad, onReady } from '@dcloudio/uni-app'
 import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
+import { useDictStore } from '@/store/dict'
 import { beforEach } from '@/router/index'
  // #ifdef APP-PLUS
 import appUpdate from "@/common/appUpdate";
@@ -12,6 +13,8 @@ export default {
     // #ifdef APP-PLUS
     // 检测升级
     appUpdate()
+    // 初始化字典数据
+    useDictStore().setDictMap()
     // #endif
   },
   onShow: function (options) {

+ 18 - 0
src/api/system/dict.ts

@@ -0,0 +1,18 @@
+import { httpGet } from '@/utils/http'
+
+export type DictDataVO = {
+  id: number | undefined
+  sort: number | undefined
+  label: string
+  value: string
+  dictType: string
+  status: number
+  colorType: string
+  cssClass: string
+  remark: string
+  createTime: Date
+}
+
+export const getSimpleDictDataList = () => {
+  return httpGet<DictDataVO[]>('/system/dict-data/simple-list')
+}

+ 43 - 35
src/components/StreetSelect/StreetSelect.vue

@@ -1,10 +1,13 @@
 <template>
-  <picker :range="streetNames" @change="onChange">
-    <view class="street-picker">
-      <text :class="['street-picker__text', !selectedStreet && 'street-picker__placeholder']">
-        {{ selectedStreet?.name || placeholder }}
-      </text>
-    </view>
+  <picker
+    :range="streetNames"
+    @change="onChange"
+    :disabled="!isEdit"
+    :class="{ 'cell-text': !isEdit, 'edit-input-text': isEdit }"
+  >
+    <text class="cell-text">
+      {{ selectedStreet?.name || placeholder }}
+    </text>
   </picker>
 </template>
 
@@ -14,8 +17,8 @@ export default {
   options: {
     addGlobalClass: true,
     virtualHost: true,
-    styleIsolation: 'shared'
-  }
+    styleIsolation: 'shared',
+  },
 }
 </script>
 
@@ -26,16 +29,20 @@ import { useAreaStore, type AreaNode } from '@/store/area'
 const props = defineProps({
   districtId: {
     type: Number,
-    required: true
+    required: true,
   },
   modelValue: {
     type: Number,
-    default: undefined
+    default: undefined,
   },
   placeholder: {
     type: String,
-    default: '请选择街道'
-  }
+    default: '请选择街道',
+  },
+  isEdit: {
+    type: Boolean,
+    default: false,
+  },
 })
 
 const emit = defineEmits<{
@@ -75,33 +82,34 @@ function onChange(e: { detail: { value: number } }) {
   emit('change', street)
 }
 
-watch(() => props.districtId, () => { loadStreets() }, { immediate: true })
+watch(
+  () => props.districtId,
+  () => {
+    loadStreets()
+  },
+  { immediate: true },
+)
 
-watch(() => props.modelValue, () => { syncSelection() })
+watch(
+  () => props.modelValue,
+  () => {
+    syncSelection()
+  },
+)
 </script>
 
 <style lang="scss" scoped>
-.street-picker {
-  display: flex;
-  align-items: center;
-  padding: 8px 12px;
-  background-color: #fff;
-  border: 1px solid #dcdfe6;
-  border-radius: 4px;
-  box-sizing: border-box;
-
-  &:active {
-    border-color: #409eff;
-  }
-
-  &__text {
-    flex: 1;
-    font-size: 14px;
-    color: #333;
-  }
+.cell-text {
+  font-size: 14px;
+  color: rgb(106, 106, 106);
+}
 
-  &__placeholder {
-    color: #c0c4cc;
-  }
+.edit-input-text {
+  flex: 1;
+  height: 30px;
+  padding: 0 10px;
+  font-size: 14px;
+  border: 1px solid #ddd;
+  border-radius: 5px;
 }
 </style>

+ 1 - 3
src/pages/equipment/detail/components/BoilerBaseInfo.vue

@@ -86,7 +86,6 @@
           <view class="table-cell content">
             <view v-if="isEdit" class="edit-input" @click="showCascader = true">
               <text>{{ districtFullName || '请选择' }}</text>
-              <image class="arrow-icon" src="/static/images/arrow-right.png" />
             </view>
             <text v-else class="cell-text">{{ getDistrictFullName(equipment.equipDistrict) }}</text>
             <AreaCascader
@@ -105,13 +104,12 @@
           </view>
           <view class="table-cell content">
             <StreetSelect
-              v-if="isEdit"
+              :isEdit="isEdit"
               v-model="equipment.equipStreet"
               :districtId="equipment.equipDistrict"
               placeholder="请选择街道"
               style="width: 100%"
             />
-            <text v-else class="cell-text">{{ streetNameDisplay }}</text>
           </view>
         </view>
 

+ 83 - 27
src/pages/equipment/detail/components/BoilerEquipmentInfo.vue

@@ -20,13 +20,18 @@
             <text class="cell-title">设备分类</text>
           </view>
           <view class="table-cell content">
-            <input
-              v-if="isEdit"
-              v-model="equipment.type"
-              class="edit-input-text"
-              placeholder="请输入"
-            />
-            <text v-else class="cell-text">{{ equipment.type }}</text>
+            <picker
+              :range="equipTypeOptions"
+              range-key="label"
+              mode="selector"
+              :value="selectedEquipTypeIndex"
+              :disabled="!isEdit"
+              :class="{'cell-text': !isEdit, 'edit-input-text': isEdit}"
+              placeholder="请选择"
+              @change="handleEquipTypeChange"
+            >
+              <text class="cell-text">{{ equipTypeOptions[selectedEquipTypeIndex]?.label }}</text>
+            </picker>
           </view>
         </view>
 
@@ -168,6 +173,7 @@
               v-if="isEdit"
               mode="date"
               :value="formatDate(equipment.completeInstallTime)"
+              :disabled="!isEdit"
               @change="onCompleteInstallTimeChange"
             >
               <view class="edit-input">
@@ -569,13 +575,18 @@
             <text class="cell-title">使用状态</text>
           </view>
           <view class="table-cell content">
-            <input
-              v-if="isEdit"
-              v-model="equipment.useStatus"
-              class="edit-input-text"
-              placeholder="请输入"
-            />
-            <text v-else class="cell-text">{{ equipment.useStatus }}</text>
+            <picker
+              :range="useStatusOptions"
+              range-key="label"
+              mode="selector"
+              :value="selectedUseStatusIndex"
+              :disabled="!isEdit"
+              :class="{'cell-text': !isEdit, 'edit-input-text': isEdit}"
+              placeholder="请选择"
+              @change="handleUseStatusChange"
+            >
+              <text class="cell-text">{{ useStatusOptions[selectedUseStatusIndex]?.label }}</text>
+            </picker>
           </view>
         </view>
 
@@ -585,13 +596,18 @@
             <text class="cell-title">运行状态</text>
           </view>
           <view class="table-cell content">
-            <input
-              v-if="isEdit"
-              v-model="equipment.status"
-              class="edit-input-text"
-              placeholder="请输入"
-            />
-            <text v-else class="cell-text">{{ equipment.status }}</text>
+            <picker
+              :range="useStatusOptions"
+              range-key="label"
+              mode="selector"
+              :value="selectedStatusIndex"
+              :disabled="!isEdit"
+              :class="{'cell-text': !isEdit, 'edit-input-text': isEdit}"
+              placeholder="请选择"
+              @change="handleStatusChange"
+            >
+              <text class="cell-text">{{ useStatusOptions[selectedStatusIndex]?.label }}</text>
+            </picker>
           </view>
         </view>
 
@@ -1517,8 +1533,19 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, onMounted, watchEffect } from 'vue'
+import { ref, reactive, onMounted, watch } from 'vue'
 import { updateEquipBoiler } from '@/api/boiler/boilerEquip'
+import { getDictOptions, DICT_TYPE } from '@/utils/dictMap'
+
+const equipTypeOptions = getDictOptions(DICT_TYPE.SYSTEM_EQUIP_BOILER_TYPE)
+console.log(equipTypeOptions)
+const useStatusOptions = getDictOptions(DICT_TYPE.SYSTEM_EQUIP_BOILER_STATUS)
+
+const selectedEquipTypeIndex = ref(0)
+const selectedUseStatusIndex = ref(0)
+const selectedStatusIndex = ref(0)
+
+
 
 interface Props {
   equipmentData: any
@@ -1642,11 +1669,18 @@ const equipment = reactive<any>({
   waterlastresult: '',
   workpressure: '',
 })
-watchEffect(() => {
-  if (props.equipmentData) {
-    Object.assign(equipment, props.equipmentData)
-  }
-})
+watch(
+  () => props.equipmentData,
+  (newVal) => {
+    if (newVal) {
+      Object.assign(equipment, newVal)
+      selectedEquipTypeIndex.value = equipTypeOptions.findIndex((item: any) => item.value == equipment.type)
+      selectedUseStatusIndex.value = useStatusOptions.findIndex((item: any) => item.value == equipment.useStatus)
+      selectedStatusIndex.value = useStatusOptions.findIndex((item: any) => item.value == equipment.status)
+    }
+  },
+  { immediate: true, deep: true }
+)
 
 const isEdit = ref(false)
 const originalData = ref<any>(null)
@@ -1662,6 +1696,9 @@ const handleEdit = () => {
 const handleCancel = () => {
   if (originalData.value) {
     Object.assign(equipment, originalData.value)
+    selectedEquipTypeIndex.value = equipTypeOptions.findIndex((item: any) => item.value === equipment.type)
+    selectedUseStatusIndex.value = useStatusOptions.findIndex((item: any) => item.value === equipment.useStatus)
+    selectedStatusIndex.value = useStatusOptions.findIndex((item: any) => item.value === equipment.status)
   }
   isEdit.value = false
 }
@@ -1791,6 +1828,25 @@ const parseDate = (dateStr: string): number => {
   return new Date(dateStr).getTime()
 }
 
+const handleEquipTypeChange = (e: any) => {
+  console.log('@@@@@', e.detail.value)
+  selectedEquipTypeIndex.value = e.detail.value
+  console.log('selectedEquipTypeIndex.....', selectedEquipTypeIndex.value, equipTypeOptions[selectedEquipTypeIndex.value]?.label)
+  equipment.type = equipTypeOptions[e.detail.value].value
+}
+
+const handleUseStatusChange = (e: any) => {
+  selectedUseStatusIndex.value = e.detail.value
+  equipment.useStatus = useStatusOptions[e.detail.value].value
+}
+
+const handleStatusChange = (e: any) => {
+  selectedStatusIndex.value = e.detail.value
+  equipment.status = useStatusOptions[e.detail.value].value
+}
+
+
+
 defineExpose({
   updateAdressInfo: (data: any) => {
     Object.assign(equipment, data)

+ 107 - 34
src/pages/equipment/detail/components/PipeEquipmentInfo.vue

@@ -68,13 +68,16 @@
             <text class="cell-title">管道类别</text>
           </view>
           <view class="table-cell content">
-            <input
-              v-if="isEdit"
-              v-model="equipment.pipeCategory"
-              class="edit-input-text"
-              placeholder="请输入"
-            />
-            <text v-else class="cell-text">{{ equipment.pipeCategory }}</text>
+            <picker
+              :range="pipeCategoryOptions"
+              range-key="label"
+              mode="selector"
+              :value="selectedPipeCategoryIndex"
+              :disabled="!isEdit"
+              @change="handlePipeCategoryChange"
+            >
+              <text class="cell-text">{{ pipeCategoryOptions[selectedPipeCategoryIndex]?.label }}</text>
+            </picker>
           </view>
         </view>
 
@@ -116,13 +119,18 @@
             <text class="cell-title">所在行政区</text>
           </view>
           <view class="table-cell content">
-            <input
-              v-if="isEdit"
-              v-model="equipment.equipDistrictName"
-              class="edit-input-text"
-              placeholder="请输入"
+            <view v-if="isEdit" class="edit-input" @click="showCascader = true">
+              <text>{{ districtFullName || '请选择' }}</text>
+              <image class="arrow-icon" src="/static/images/arrow-right.png" />
+            </view>
+            <text v-else class="cell-text">{{ getDistrictFullName(equipment.equipDistrict) }}</text>
+            <AreaCascader
+              v-show="isEdit"
+              v-model="selectedDistrict"
+              v-model:visible="showCascader"
+              title="请选择行政区"
+              @confirm="handleAreaConfirm"
             />
-            <text v-else class="cell-text">{{ equipment.equipDistrictName }}</text>
           </view>
         </view>
 
@@ -132,13 +140,14 @@
             <text class="cell-title">所在街道</text>
           </view>
           <view class="table-cell content">
-            <input
+            <StreetSelect
               v-if="isEdit"
-              v-model="equipment.equipStreetName"
-              class="edit-input-text"
-              placeholder="请输入"
+              v-model="equipment.equipStreet"
+              :districtId="equipment.equipDistrict"
+              placeholder="请选择街道"
+              style="width: 100%"
             />
-            <text v-else class="cell-text">{{ equipment.equipStreetName }}</text>
+            <text v-else class="cell-text">{{ streetNameDisplay }}</text>
           </view>
         </view>
 
@@ -196,13 +205,16 @@
             <text class="cell-title">使用状态</text>
           </view>
           <view class="table-cell content">
-            <input
-              v-if="isEdit"
-              v-model="equipment.useStatus"
-              class="edit-input-text"
-              placeholder="请输入"
-            />
-            <text v-else class="cell-text">{{ equipment.useStatus }}</text>
+            <picker
+              :range="useStatusOptions"
+              range-key="label"
+              mode="selector"
+              :value="selectedUseStatusIndex"
+              :disabled="!isEdit"
+              @change="handleUseStatusChange"
+            >
+              <text class="cell-text">{{ useStatusOptions[selectedUseStatusIndex]?.label }}</text>
+            </picker>
           </view>
         </view>
 
@@ -1324,8 +1336,29 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, reactive, computed, onMounted, watchEffect } from 'vue'
+import { ref, reactive, computed, onMounted, watch } from 'vue'
 import { updateEquipPipe } from '@/api/pipe/pipeEquip'
+import { getDictOptions, DICT_TYPE } from '@/utils/dictMap'
+import AreaCascader from '@/components/AreaCascader/AreaCascader.vue'
+import StreetSelect from '@/components/StreetSelect/StreetSelect.vue'
+import { useAreaStore } from '@/store/area'
+
+const areaStore = useAreaStore()
+const getDistrictFullName = areaStore.getDistrictFullName
+
+const pipeCategoryOptions = getDictOptions(DICT_TYPE.PIPE_TYPE)
+const useStatusOptions = getDictOptions(DICT_TYPE.SYSTEM_EQUIP_BOILER_STATUS)
+
+const selectedPipeCategoryIndex = ref(0)
+const selectedUseStatusIndex = ref(0)
+
+const districtFullName = computed(() => {
+  return getDistrictFullName(Number(selectedDistrict.value))
+})
+
+const streetNameDisplay = computed(() => {
+  return areaStore.getStreetName(Number(equipment.equipStreet), Number(equipment.equipDistrict))
+})
 
 interface Props {
   dataSource?: any
@@ -1401,13 +1434,20 @@ const equipment = reactive<any>({
   categories: '',
 })
 const pipeList = ref<any[]>([])
-watchEffect(() => {
-  if (props.equipmentData) {
-    Object.assign(equipment, props.equipmentData)
-  }
-  pipeList.value = !props.equipmentData?.detailSaveReqVOS
-    ? []
-    : props.equipmentData.detailSaveReqVOS.map((item: any) => ({
+const selectedDistrict = ref<string | number | (string | number)[]>('')
+const showCascader = ref(false)
+
+watch(
+  () => props.equipmentData,
+  (newVal) => {
+    if (newVal) {
+      Object.assign(equipment, newVal)
+      selectedPipeCategoryIndex.value = pipeCategoryOptions.findIndex((item: any) => item.value == equipment.pipeCategory)
+      selectedUseStatusIndex.value = useStatusOptions.findIndex((item: any) => item.value == equipment.useStatus)
+    }
+    pipeList.value = !newVal?.detailSaveReqVOS
+      ? []
+      : newVal.detailSaveReqVOS.map((item: any) => ({
         pipeId: item.id || '',
         pipeName: item.pipeName || '',
         pipeNo: item.pipeNo || '',
@@ -1457,7 +1497,23 @@ watchEffect(() => {
         lastYearCheckConclusion: item.lastYearCheckConclusion || '',
         lastYearCheckProblem: item.lastYearCheckProblem || '',
       }))
-})
+  },
+  { immediate: true, deep: true }
+)
+
+function handleAreaConfirm(data: {
+  value: string | number | (string | number)[]
+  selectedOptions: any[]
+}) {
+  selectedDistrict.value = data.value
+  if (data.selectedOptions.length > 0) {
+    const lastOption = data.selectedOptions[data.selectedOptions.length - 1]
+    if (equipment.equipDistrict !== lastOption.id) {
+      equipment.equipDistrict = lastOption.id
+      equipment.equipStreet = null
+    }
+  }
+}
 
 const expandedNames = ref<string>('1')
 const handleCollapseChange = (detail: any) => {
@@ -1465,6 +1521,11 @@ const handleCollapseChange = (detail: any) => {
 }
 
 const isEdit = ref(false)
+watch(isEdit, (editing) => {
+  if (editing) {
+    selectedDistrict.value = equipment.equipDistrict || ''
+  }
+})
 const originalData = ref<any>(null)
 const handleEdit = () => {
   if (isEdit.value) {
@@ -1478,6 +1539,8 @@ const handleEdit = () => {
 const handleCancel = () => {
   if (originalData.value) {
     Object.assign(equipment, originalData.value)
+    selectedPipeCategoryIndex.value = pipeCategoryOptions.findIndex((item: any) => item.value == equipment.pipeCategory)
+    selectedUseStatusIndex.value = useStatusOptions.findIndex((item: any) => item.value == equipment.useStatus)
   }
   isEdit.value = false
 }
@@ -1550,6 +1613,16 @@ const onAcceptDateChange = (e: any) => {
   equipment.acceptdate = parseDate(e.detail.value)
 }
 
+const handlePipeCategoryChange = (e: any) => {
+  selectedPipeCategoryIndex.value = e.detail.value
+  equipment.pipeCategory = pipeCategoryOptions[e.detail.value].value
+}
+
+const handleUseStatusChange = (e: any) => {
+  selectedUseStatusIndex.value = e.detail.value
+  equipment.useStatus = useStatusOptions[e.detail.value].value
+}
+
 const onDesignDateChange = (e: any) => {
   equipment.designdate = parseDate(e.detail.value)
 }

+ 12 - 5
src/pages/securityCheck/detail/index.vue

@@ -36,14 +36,21 @@
 <script lang="ts" setup>
 import { ref, computed, onMounted } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
-import { getDynamicTbVal } from '@/api/task'
 import HeadView from '../components/HeadView.vue'
 import NavBar from '@/components/NavBar/NavBar.vue'
-import { getSecurityCheckTemplate } from '@/api/boiler/boilerTaskOrderSecurityCheck'
-import { getStandardTemplate } from '@/api'
-import { buildFileUrl } from '@/utils/index'
 import SpreadPDFViewer from '@/components/SpreadDesigner/SpreadPDFViewer.vue'
 
+import { useConfigStore } from '@/store/config'
+
+import { buildFileUrl } from '@/utils/index'
+import { requestFunc, SecurityCheckFuncName } from '@/api/ApiRouter/taskOrderSecurityCheck'
+import { getDynamicTbVal } from '@/api/task'
+import { getStandardTemplate } from '@/api'
+
+
+const configStore = useConfigStore()
+const equipType = configStore.getEquipType()
+
 // 路由参数
 const detailItem = ref<any>({})
 const orderId = ref('')
@@ -113,7 +120,7 @@ const init = async () => {
     // await getAppServiceOrderPDF(tplParams)
     const id = detailItem.value?.id || ''
     if (!id) return
-    const defaultTemplateResp = await getSecurityCheckTemplate({ orderId: orderId.value })
+    const defaultTemplateResp = await requestFunc(SecurityCheckFuncName.getTemplate, equipType, { orderId: orderId.value })
     const res = await getStandardTemplate({ id: defaultTemplateResp.data?.templateId })
     const resData = (res as any).data
     const dataMap: any = {}

+ 149 - 0
src/store/dict.ts

@@ -0,0 +1,149 @@
+import { defineStore } from 'pinia'
+import store from '@/store'
+import { type DictDataVO, getSimpleDictDataList } from '@/api/system/dict'
+
+export interface DictValueType {
+  value: any
+  label: string
+  colorType?: string
+  cssClass?: string
+}
+
+interface CachePayload {
+  data: Record<string, DictValueType[]>
+  expire: number
+}
+
+const DICT_CACHE_KEY = 'DICT_CACHE'
+const CACHE_EXPIRE_MS = 10 * 60 * 1000
+
+function buildDictMap(list: DictDataVO[]): Record<string, DictValueType[]> {
+  const dictDataMap: Record<string, DictValueType[]> = {}
+  list.forEach((dictData) => {
+    if (!dictDataMap[dictData.dictType]) {
+      dictDataMap[dictData.dictType] = []
+    }
+    dictDataMap[dictData.dictType].push({
+      value: dictData.value,
+      label: dictData.label,
+      colorType: dictData.colorType,
+      cssClass: dictData.cssClass,
+    })
+  })
+  return dictDataMap
+}
+
+export const useDictStore = defineStore('dict', {
+  state: () => ({
+    dictMap: {} as Record<string, DictValueType[]>,
+    isRefreshing: false,
+  }),
+  getters: {
+    getDictMap(): Record<string, DictValueType[]> {
+      this._ensureLoaded()
+      return this.dictMap
+    },
+  },
+  actions: {
+    _readCache(): CachePayload | null {
+      try {
+        const raw = uni.getStorageSync(DICT_CACHE_KEY)
+        if (!raw) return null
+        const parsed: CachePayload = JSON.parse(raw)
+        if (parsed && parsed.data) {
+          return parsed
+        }
+      } catch (e) {
+        // ignore
+      }
+      return null
+    },
+
+    _writeCache(data: Record<string, DictValueType[]>) {
+      try {
+        const payload: CachePayload = { data, expire: Date.now() + CACHE_EXPIRE_MS }
+        uni.setStorageSync(DICT_CACHE_KEY, JSON.stringify(payload))
+      } catch (e) {
+        // ignore
+      }
+    },
+
+    _clearCache() {
+      try {
+        uni.removeStorageSync(DICT_CACHE_KEY)
+      } catch (e) {
+        // ignore
+      }
+    },
+
+    _isCacheExpired(cache: CachePayload): boolean {
+      return cache.expire <= Date.now()
+    },
+
+    _ensureLoaded() {
+      if (Object.keys(this.dictMap).length) return
+
+      const cache = this._readCache()
+      if (cache) {
+        this.dictMap = cache.data
+        if (this._isCacheExpired(cache) && !this.isRefreshing) {
+          this._refreshInBackground()
+        }
+      } else {
+        this.setDictMap()
+      }
+    },
+
+    async _refreshInBackground() {
+      this.isRefreshing = true
+      try {
+        const res = await getSimpleDictDataList()
+        const list = (res as any)?.data || res || []
+        const dictDataMap = buildDictMap(list as DictDataVO[])
+        this.dictMap = dictDataMap
+        this._writeCache(dictDataMap)
+      } catch (e) {
+        // ignore
+      } finally {
+        this.isRefreshing = false
+      }
+    },
+
+    async setDictMap() {
+      if (Object.keys(this.dictMap).length) return
+
+      const cache = this._readCache()
+      if (cache) {
+        this.dictMap = cache.data
+        if (this._isCacheExpired(cache) && !this.isRefreshing) {
+          this._refreshInBackground()
+        }
+        return
+      }
+
+      const res = await getSimpleDictDataList()
+      const list = (res as any)?.data || res || []
+      const dictDataMap = buildDictMap(list as DictDataVO[])
+      this.dictMap = dictDataMap
+      this._writeCache(dictDataMap)
+    },
+
+    getDictByType(type: string): DictValueType[] {
+      this._ensureLoaded()
+      return this.dictMap[type] || []
+    },
+
+    async resetDict() {
+      this._clearCache()
+      const res = await getSimpleDictDataList()
+      const list = (res as any)?.data || res || []
+      const dictDataMap = buildDictMap(list as DictDataVO[])
+      this.dictMap = dictDataMap
+      this._writeCache(dictDataMap)
+    },
+  },
+})
+
+export const useDictStoreWithOut = () => {
+  return useDictStore(store)
+}

+ 1 - 0
src/store/index.ts

@@ -16,3 +16,4 @@ export default store
 // 模块统一导出
 export * from './user'
 export * from './area'
+export * from './dict'

+ 141 - 0
src/utils/dictMap.ts

@@ -1,3 +1,5 @@
+import { useDictStoreWithOut, type DictValueType } from '@/store/dict'
+
 export enum PressureCheckerMyTaskStatus {
   WAIT_CONFIRM = 100,
   CANCELLATION = 200,
@@ -97,3 +99,142 @@ export function getCheckTypeFromText(checkTypeName?: string): number | undefined
       return undefined
   }
 }
+
+// ========================== 数据字典工具函数 ==========================
+
+export interface DictDataType {
+  dictType: string
+  label: string
+  value: string | number | boolean
+  colorType: string
+  cssClass: string
+}
+
+export interface NumberDictDataType extends DictDataType {
+  value: number
+}
+
+export interface StringDictDataType extends DictDataType {
+  value: string
+}
+
+export const getDictOptions = (dictType: string): DictDataType[] => {
+  const dictStore = useDictStoreWithOut()
+  const list: DictValueType[] = dictStore.getDictByType(dictType)
+  return list.map((item) => ({
+    dictType,
+    label: item.label,
+    value: item.value,
+    colorType: item.colorType || '',
+    cssClass: item.cssClass || '',
+  }))
+}
+
+export const getIntDictOptions = (dictType: string): NumberDictDataType[] => {
+  const dictOptions: DictDataType[] = getDictOptions(dictType)
+  return dictOptions.map((dict) => ({
+    ...dict,
+    value: parseInt(dict.value + ''),
+  }))
+}
+
+export const getStrDictOptions = (dictType: string): StringDictDataType[] => {
+  const dictOptions: DictDataType[] = getDictOptions(dictType)
+  return dictOptions.map((dict) => ({
+    ...dict,
+    value: dict.value + '',
+  }))
+}
+
+export const getBoolDictOptions = (dictType: string): DictDataType[] => {
+  const dictOptions: DictDataType[] = getDictOptions(dictType)
+  return dictOptions.map((dict) => ({
+    ...dict,
+    value: dict.value + '' === 'true',
+  }))
+}
+
+export const getDictObj = (dictType: string, value: any): DictDataType | undefined => {
+  const dictOptions: DictDataType[] = getDictOptions(dictType)
+  for (const dict of dictOptions) {
+    if (dict.value === value + '') {
+      return dict
+    }
+  }
+}
+
+export const getDictLabel = (dictType: string, value: any): string => {
+  const dictOptions: DictDataType[] = getDictOptions(dictType)
+  for (const dict of dictOptions) {
+    if (dict.value === value + '') {
+      return dict.label
+    }
+  }
+  return ''
+}
+
+export enum DICT_TYPE {
+  USER_TYPE = 'user_type',
+  COMMON_STATUS = 'common_status',
+  TERMINAL = 'terminal',
+  DATE_INTERVAL = 'date_interval',
+
+  SYSTEM_USER_SEX = 'system_user_sex',
+  SYSTEM_MENU_TYPE = 'system_menu_type',
+  SYSTEM_ROLE_TYPE = 'system_role_type',
+  SYSTEM_DATA_SCOPE = 'system_data_scope',
+  SYSTEM_NOTICE_TYPE = 'system_notice_type',
+  SYSTEM_LOGIN_TYPE = 'system_login_type',
+  SYSTEM_LOGIN_RESULT = 'system_login_result',
+  SYSTEM_SMS_CHANNEL_CODE = 'system_sms_channel_code',
+  SYSTEM_SMS_TEMPLATE_TYPE = 'system_sms_template_type',
+  SYSTEM_SMS_SEND_STATUS = 'system_sms_send_status',
+  SYSTEM_SMS_RECEIVE_STATUS = 'system_sms_receive_status',
+  SYSTEM_OAUTH2_GRANT_TYPE = 'system_oauth2_grant_type',
+  SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status',
+  SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type',
+  SYSTEM_SOCIAL_TYPE = 'system_social_type',
+  SYSTEM_EQUIP_CONTAINER_TYPE = 'system_equip_container_type',
+  SYSTEM_EQUIP_CONTAINER_STATUS = 'system_equip_container_status',
+  SYSTEM_EQUIP_CONTAINER_EQUIP_TYPE = 'system_equip_container_equip_type',
+  SYSTEM_EQUIP_CONTAINER_EQUIP_CATEGORY = 'system_equip_container_equip_category',
+  SYSTEM_EQUIP_CONTAINER_AIRSTORE_CATEGORY = 'system_equip_container_airstore_category',
+
+  INFRA_BOOLEAN_STRING = 'infra_boolean_string',
+  INFRA_JOB_STATUS = 'infra_job_status',
+  INFRA_JOB_LOG_STATUS = 'infra_job_log_status',
+  INFRA_API_ERROR_LOG_PROCESS_STATUS = 'infra_api_error_log_process_status',
+  INFRA_CONFIG_TYPE = 'infra_config_type',
+  INFRA_CODEGEN_TEMPLATE_TYPE = 'infra_codegen_template_type',
+  INFRA_CODEGEN_FRONT_TYPE = 'infra_codegen_front_type',
+  INFRA_CODEGEN_SCENE = 'infra_codegen_scene',
+  INFRA_FILE_STORAGE = 'infra_file_storage',
+  INFRA_OPERATE_TYPE = 'infra_operate_type',
+
+  BPM_MODEL_TYPE = 'bpm_model_type',
+  BPM_MODEL_FORM_TYPE = 'bpm_model_form_type',
+  BPM_TASK_CANDIDATE_STRATEGY = 'bpm_task_candidate_strategy',
+  BPM_PROCESS_INSTANCE_STATUS = 'bpm_process_instance_status',
+  BPM_TASK_STATUS = 'bpm_task_status',
+  BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type',
+  BPM_PROCESS_LISTENER_TYPE = 'bpm_process_listener_type',
+  BPM_PROCESS_LISTENER_VALUE_TYPE = 'bpm_process_listener_value_type',
+  BPM_AUDIT_STATUS = 'bpm_audit_status',
+
+  PIPE_TYPE = 'PIPE_TYPE',
+  PIPE_CHILD_TYPE = 'PIPE_CHILD_TYPE',
+  COMPRESSION_PROJECT_TEMPLATEMANAGEMENT = 'COMPRESSION_PROJECT_TEMPLATEMANAGEMENT',
+
+  PRESSURE2_EQUIP_BOILER_TRUE_FALSE = 'pressure2_equip_boiler_true_false',
+  SYSTEM_TEMPLATE_INIT_DATA_CLASSIFICATION = 'system_template_init_data_classification',
+  PRESSURE2_TB_TYPE = 'pressure2_tb_type',
+  PRESSURE2_COL_VAL_TYPE = 'pressure2_col_val_type',
+  PRESSURE2_COL_ROUND = 'pressure2_col_round',
+  PRESSURE2_EQUIP_MAIN_TYPE = 'pressure2_equip_main_type',
+  PRESSURE2_BOILER_PART_TYPE = 'pressure2_boiler_part_type',
+  PRESSURE2_PIPE_LEVEL = 'PIPE_LEVEL',
+  PRESSURE2_DYNAMIC_REPORT_TYPE = 'pressure2_dynamic_report_type',
+  PRESSURE2_DYNAMIC_PROJECT_TYPE = 'pressure2_dynamic_project_type',
+  SYSTEM_EQUIP_BOILER_TYPE = 'system_equip_boiler_type',
+  SYSTEM_EQUIP_BOILER_STATUS = 'system_equip_boiler_status',
+}