Преглед изворни кода

feat(zfxxgl):增加设备维护记录管理功能- 新增设备维护记录相关接口和数据结构
- 实现设备维护记录的查看、新增、编辑和删除功能
- 优化房屋信息和设备列表界面,增加维护记录相关操作
- 重构部分代码以支持新功能

nahida пре 10 месеци
родитељ
комит
48ce275f02
1 измењених фајлова са 415 додато и 15 уклоњено
  1. 415 15
      src/views/zfgl/zfxxgl.vue

+ 415 - 15
src/views/zfgl/zfxxgl.vue

@@ -1,9 +1,19 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { onMounted, reactive, ref } from 'vue'
 import { onMounted, reactive, ref } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { ElMessage, ElMessageBox } from 'element-plus'
-import { Delete, Edit, Eye, Home, Info, Package, Plus, Search, Settings } from 'lucide-vue-next'
+import {
+  Delete,
+  Edit,
+  Eye,
+  Home,
+  Info,
+  Package,
+  Plus,
+  Search,
+  Settings,
+  Wrench,
+} from 'lucide-vue-next'
 import { clientGet, clientPost } from '@/utils/request.ts'
 import { clientGet, clientPost } from '@/utils/request.ts'
-import { BaseResponse, PageType } from '@/utils/types.ts' // Import BaseResponse and PageType
 
 
 interface ASimplifiedHouseInfo {
 interface ASimplifiedHouseInfo {
   id: string
   id: string
@@ -13,7 +23,7 @@ interface ASimplifiedHouseInfo {
   houseName?: string | null
   houseName?: string | null
   address?: string | null
   address?: string | null
   status?: string | null
   status?: string | null
-  rentRange?: string | null
+  rentRange?: number | null
   createTime?: Date | null
   createTime?: Date | null
   updateTime?: Date | null
   updateTime?: Date | null
 }
 }
@@ -29,7 +39,7 @@ interface AddASimplifiedHouseInfo {
   houseName?: string | null
   houseName?: string | null
   address?: string | null
   address?: string | null
   status?: string | null
   status?: string | null
-  rentRange?: string | null
+  rentRange?: number | null
 }
 }
 
 
 interface UpdateASimplifiedHouseInfo {
 interface UpdateASimplifiedHouseInfo {
@@ -40,7 +50,7 @@ interface UpdateASimplifiedHouseInfo {
   houseName?: string | null
   houseName?: string | null
   address?: string | null
   address?: string | null
   status?: string | null
   status?: string | null
-  rentRange?: string | null
+  rentRange?: number | null
 }
 }
 
 
 interface AHouseInfoDetail {
 interface AHouseInfoDetail {
@@ -107,6 +117,44 @@ interface UpdateADeviceInfo {
   devicePrice?: string | null
   devicePrice?: string | null
 }
 }
 
 
+interface AMaintenanceRecords {
+  id: string
+  deviceId: string
+  maintenanceDate: Date | null
+  maintenanceContent: string
+  maintenanceType: string
+  maintenanceCost: number | null
+  maintenancePerson: string
+  maintenanceStatus: string
+  createTime?: Date | null
+  updateTime?: Date | null
+}
+
+interface AMaintenanceRecordsListReponse extends BaseResponse {
+  data: AMaintenanceRecords[]
+}
+
+interface AddAMaintenanceRecords {
+  deviceId: string
+  maintenanceDate: Date | null
+  maintenanceContent: string
+  maintenanceType: string
+  maintenanceCost: number | null
+  maintenancePerson: string
+  maintenanceStatus: string
+}
+
+interface UpdateAMaintenanceRecords {
+  id: string
+  deviceId: string
+  maintenanceDate: Date | null
+  maintenanceContent: string
+  maintenanceType: string
+  maintenanceCost: number | null
+  maintenancePerson: string
+  maintenanceStatus: string
+}
+
 // 响应式数据
 // 响应式数据
 const loading = ref(false)
 const loading = ref(false)
 const tableData = ref<ASimplifiedHouseInfo[]>([])
 const tableData = ref<ASimplifiedHouseInfo[]>([])
@@ -126,8 +174,11 @@ const searchForm = reactive({
 const dialogVisible = ref(false)
 const dialogVisible = ref(false)
 const detailDialogVisible = ref(false)
 const detailDialogVisible = ref(false)
 const deviceDialogVisible = ref(false)
 const deviceDialogVisible = ref(false)
+const maintenanceDialogVisible = ref(false)
+const maintenanceRecordDialogVisible = ref(false)
 const isEdit = ref(false)
 const isEdit = ref(false)
 const isDeviceEdit = ref(false)
 const isDeviceEdit = ref(false)
+const isMaintenanceEdit = ref(false)
 const dialogTitle = ref('新增房屋信息')
 const dialogTitle = ref('新增房屋信息')
 const activeTab = ref('detail')
 const activeTab = ref('detail')
 
 
@@ -139,7 +190,7 @@ const houseForm = reactive<AddASimplifiedHouseInfo & { id?: string }>({
   houseName: '',
   houseName: '',
   address: '',
   address: '',
   status: '空闲',
   status: '空闲',
-  rentRange: '',
+  rentRange: 0,
 })
 })
 
 
 const detailForm = reactive<AddAHouseInfoDetail & { id?: string }>({
 const detailForm = reactive<AddAHouseInfoDetail & { id?: string }>({
@@ -158,6 +209,22 @@ const deviceForm = reactive<AddADeviceInfo & { id?: string }>({
   devicePrice: '',
   devicePrice: '',
 })
 })
 
 
+// 维护记录相关数据
+const currentDeviceId = ref('')
+const currentDeviceName = ref('')
+const maintenanceList = ref<AMaintenanceRecords[]>([])
+const maintenanceLoading = ref(false)
+
+const maintenanceForm = reactive<AddAMaintenanceRecords & { id?: string }>({
+  deviceId: '',
+  maintenanceDate: null,
+  maintenanceContent: '',
+  maintenanceType: '',
+  maintenanceCost: null,
+  maintenancePerson: '',
+  maintenanceStatus: '待处理',
+})
+
 // 选中的行和设备数据
 // 选中的行和设备数据
 const selectedRows = ref<ASimplifiedHouseInfo[]>([])
 const selectedRows = ref<ASimplifiedHouseInfo[]>([])
 const currentHouseId = ref('')
 const currentHouseId = ref('')
@@ -310,6 +377,56 @@ const updateDevice = async (info: UpdateADeviceInfo) => {
   return true
   return true
 }
 }
 
 
+const addDeviceMaintainRecord = async (info: AddAMaintenanceRecords) => {
+  const res = await clientPost<AddAMaintenanceRecords, BaseResponse>(
+    '/amaintenanceRecords/save',
+    info,
+  )
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const updateDeviceMaintainRecord = async (info: UpdateAMaintenanceRecords) => {
+  const res = await clientPost<UpdateAMaintenanceRecords, BaseResponse>(
+    '/amaintenanceRecords/update',
+    info,
+  )
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const deleteDeviceMaintainRecord = async (ids: string[]) => {
+  const res = await clientPost<string[], BaseResponse>('/amaintenanceRecords/delete', ids)
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const getDeviceMaintainRecord = async (deviceId: string) => {
+  const res = await clientGet<{ deviceId: string }, AMaintenanceRecordsListReponse>(
+    '/amaintenanceRecords/getByDeviceId',
+    {
+      params: { deviceId },
+    },
+  )
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return []
+  }
+  return res.data
+}
+
 // 页面方法
 // 页面方法
 const handleSearch = () => {
 const handleSearch = () => {
   currentPage.value = 1
   currentPage.value = 1
@@ -329,6 +446,7 @@ const handleReset = () => {
 const handleAdd = () => {
 const handleAdd = () => {
   isEdit.value = false
   isEdit.value = false
   dialogTitle.value = '新增房屋信息'
   dialogTitle.value = '新增房屋信息'
+  houseForm.id = undefined
   Object.assign(houseForm, {
   Object.assign(houseForm, {
     assetType: '',
     assetType: '',
     building: '',
     building: '',
@@ -336,7 +454,7 @@ const handleAdd = () => {
     houseName: '',
     houseName: '',
     address: '',
     address: '',
     status: '空闲',
     status: '空闲',
-    rentRange: '',
+    rentRange: 0,
   })
   })
   dialogVisible.value = true
   dialogVisible.value = true
 }
 }
@@ -441,7 +559,7 @@ const handleDetailSubmit = async () => {
     success = await addRentingHouseDetail(detailForm)
     success = await addRentingHouseDetail(detailForm)
   }
   }
   if (success) {
   if (success) {
-    ElMessage.success('房屋详细信息保存成功')
+    // ElMessage.success('房屋详细信息保存成功')
   }
   }
 }
 }
 
 
@@ -494,6 +612,74 @@ const handleDeviceSubmit = async () => {
   }
   }
 }
 }
 
 
+// 设备维护记录相关方法
+const handleViewMaintenance = async (device: ADeviceInfo) => {
+  currentDeviceId.value = device.id
+  currentDeviceName.value = device.deviceName
+  await loadMaintenanceList(device.id)
+  maintenanceDialogVisible.value = true
+}
+
+const loadMaintenanceList = async (deviceId: string) => {
+  maintenanceLoading.value = true
+  try {
+    const records = await getDeviceMaintainRecord(deviceId)
+    maintenanceList.value = records || []
+  } finally {
+    maintenanceLoading.value = false
+  }
+}
+
+const handleAddMaintenance = () => {
+  isMaintenanceEdit.value = false
+  Object.assign(maintenanceForm, {
+    id: '',
+    deviceId: currentDeviceId.value,
+    maintenanceDate: null,
+    maintenanceContent: '',
+    maintenanceType: '',
+    maintenanceCost: null,
+    maintenancePerson: '',
+    maintenanceStatus: '待处理',
+  })
+  maintenanceRecordDialogVisible.value = true
+}
+
+const handleEditMaintenance = (record: AMaintenanceRecords) => {
+  isMaintenanceEdit.value = true
+  Object.assign(maintenanceForm, { ...record })
+  maintenanceRecordDialogVisible.value = true
+}
+
+const handleDeleteMaintenance = async (record: AMaintenanceRecords) => {
+  try {
+    await ElMessageBox.confirm('确定要删除这条维护记录吗?', '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    })
+    const success = await deleteDeviceMaintainRecord([record.id])
+    if (success) {
+      await loadMaintenanceList(currentDeviceId.value)
+    }
+  } catch {
+    // 用户取消删除
+  }
+}
+
+const handleMaintenanceSubmit = async () => {
+  let success = false
+  if (isMaintenanceEdit.value) {
+    success = await updateDeviceMaintainRecord(maintenanceForm as UpdateAMaintenanceRecords)
+  } else {
+    success = await addDeviceMaintainRecord(maintenanceForm)
+  }
+  if (success) {
+    maintenanceRecordDialogVisible.value = false
+    await loadMaintenanceList(currentDeviceId.value)
+  }
+}
+
 const handleSelectionChange = (selection: ASimplifiedHouseInfo[]) => {
 const handleSelectionChange = (selection: ASimplifiedHouseInfo[]) => {
   selectedRows.value = selection
   selectedRows.value = selection
 }
 }
@@ -509,6 +695,36 @@ const handleSizeChange = (size: number) => {
   getList()
   getList()
 }
 }
 
 
+const getMaintenanceTypeColor = (type: string) => {
+  const colorMap: Record<string, string> = {
+    定期保养: 'success',
+    故障维修: 'danger',
+    清洁保养: 'info',
+    零件更换: 'warning',
+    升级改造: 'primary',
+    其他: '',
+  }
+  return colorMap[type] || ''
+}
+
+const getMaintenanceStatusColor = (status: string) => {
+  const colorMap: Record<string, string> = {
+    待处理: 'warning',
+    进行中: 'primary',
+    已完成: 'success',
+    已取消: 'info',
+  }
+  return colorMap[status] || ''
+}
+
+const getAssetTypeTag = (assetType: string | null | undefined): string => {
+  if (!assetType) return 'default'
+  if (assetType === '公租房') return 'primary'
+  if (assetType === '厂房') return 'success'
+  if (assetType === '创新创业基地') return 'danger' // 新增类型
+  return 'warning' // 默认颜色
+}
+
 onMounted(() => {
 onMounted(() => {
   getList()
   getList()
 })
 })
@@ -540,6 +756,7 @@ onMounted(() => {
             >
             >
               <el-option label="公租房" value="公租房" />
               <el-option label="公租房" value="公租房" />
               <el-option label="厂房" value="厂房" />
               <el-option label="厂房" value="厂房" />
+              <el-option label="创新创业基地" value="创新创业基地" />
             </el-select>
             </el-select>
           </el-form-item>
           </el-form-item>
           <el-form-item label="楼栋">
           <el-form-item label="楼栋">
@@ -604,7 +821,7 @@ onMounted(() => {
           <el-table-column type="selection" width="55" />
           <el-table-column type="selection" width="55" />
           <el-table-column prop="assetType" label="资产类型" width="100">
           <el-table-column prop="assetType" label="资产类型" width="100">
             <template #default="{ row }">
             <template #default="{ row }">
-              <el-tag :type="row.assetType === '公租房' ? 'primary' : 'success'">
+              <el-tag :type="getAssetTypeTag(row.assetType)">
                 {{ row.assetType }}
                 {{ row.assetType }}
               </el-tag>
               </el-tag>
             </template>
             </template>
@@ -620,7 +837,7 @@ onMounted(() => {
               </el-tag>
               </el-tag>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
-          <el-table-column prop="rentRange" label="租金范围" width="150" />
+          <el-table-column prop="rentRange" label="租金" width="150" />
           <el-table-column label="操作" width="250" fixed="right">
           <el-table-column label="操作" width="250" fixed="right">
             <template #default="{ row }">
             <template #default="{ row }">
               <div class="flex gap-2">
               <div class="flex gap-2">
@@ -665,6 +882,7 @@ onMounted(() => {
           <el-select v-model="houseForm.assetType" placeholder="请选择资产类型" class="w-full">
           <el-select v-model="houseForm.assetType" placeholder="请选择资产类型" class="w-full">
             <el-option label="公租房" value="公租房" />
             <el-option label="公租房" value="公租房" />
             <el-option label="厂房" value="厂房" />
             <el-option label="厂房" value="厂房" />
+            <el-option label="创新创业基地" value="创新创业基地" />
           </el-select>
           </el-select>
         </el-form-item>
         </el-form-item>
         <el-form-item label="楼栋" required>
         <el-form-item label="楼栋" required>
@@ -682,8 +900,13 @@ onMounted(() => {
             <el-option label="已租" value="已租" />
             <el-option label="已租" value="已租" />
           </el-select>
           </el-select>
         </el-form-item>
         </el-form-item>
-        <el-form-item label="租金范围">
-          <el-input v-model="houseForm.rentRange" placeholder="请输入租金范围" />
+        <el-form-item label="租金">
+          <el-input-number
+            :min="0"
+            v-model="houseForm.rentRange"
+            :precision="2"
+            placeholder="请输入租金"
+          />
         </el-form-item>
         </el-form-item>
         <el-form-item label="地址" class="col-span-2">
         <el-form-item label="地址" class="col-span-2">
           <el-input v-model="houseForm.address" placeholder="请输入详细地址" />
           <el-input v-model="houseForm.address" placeholder="请输入详细地址" />
@@ -701,7 +924,7 @@ onMounted(() => {
     <el-dialog
     <el-dialog
       v-model="detailDialogVisible"
       v-model="detailDialogVisible"
       :title="`${currentHouseName} - 详细信息管理`"
       :title="`${currentHouseName} - 详细信息管理`"
-      width="900px"
+      width="1000px"
       :close-on-click-modal="false"
       :close-on-click-modal="false"
       class="detail-dialog"
       class="detail-dialog"
     >
     >
@@ -729,6 +952,8 @@ onMounted(() => {
                   <el-option label="两室一厅" value="两室一厅" />
                   <el-option label="两室一厅" value="两室一厅" />
                   <el-option label="三室一厅" value="三室一厅" />
                   <el-option label="三室一厅" value="三室一厅" />
                   <el-option label="三室两厅" value="三室两厅" />
                   <el-option label="三室两厅" value="三室两厅" />
+                  <el-option label="单间" value="单间" />
+                  <el-option label="套间" value="套间" />
                   <el-option label="厂房" value="厂房" />
                   <el-option label="厂房" value="厂房" />
                   <el-option label="仓库" value="仓库" />
                   <el-option label="仓库" value="仓库" />
                 </el-select>
                 </el-select>
@@ -778,9 +1003,17 @@ onMounted(() => {
                     <span class="text-green-600 font-medium">{{ row.devicePrice }}</span>
                     <span class="text-green-600 font-medium">{{ row.devicePrice }}</span>
                   </template>
                   </template>
                 </el-table-column>
                 </el-table-column>
-                <el-table-column label="操作" width="200" fixed="right">
+                <el-table-column label="操作" width="270" fixed="right">
                   <template #default="{ row }">
                   <template #default="{ row }">
-                    <div class="flex gap-2">
+                    <div class="flex gap-1 flex-wrap">
+                      <el-button
+                        type="info"
+                        size="small"
+                        @click="handleViewMaintenance(row)"
+                        :icon="Wrench"
+                      >
+                        维护记录
+                      </el-button>
                       <el-button
                       <el-button
                         type="warning"
                         type="warning"
                         size="small"
                         size="small"
@@ -858,6 +1091,173 @@ onMounted(() => {
         </div>
         </div>
       </template>
       </template>
     </el-dialog>
     </el-dialog>
+
+    <!-- 维护记录管理对话框 -->
+    <el-dialog
+      v-model="maintenanceDialogVisible"
+      :title="`${currentDeviceName} - 维护记录管理`"
+      width="900px"
+      :close-on-click-modal="false"
+    >
+      <div class="mb-4 flex justify-between items-center">
+        <el-button type="primary" @click="handleAddMaintenance" :icon="Plus" size="small">
+          新增维护记录
+        </el-button>
+        <div class="text-sm text-gray-500">共 {{ maintenanceList.length }} 条维护记录</div>
+      </div>
+
+      <div v-loading="maintenanceLoading">
+        <el-table :data="maintenanceList" stripe class="w-full">
+          <el-table-column prop="maintenanceDate" label="维护时间" width="120">
+            <template #default="{ row }">
+              {{ row.maintenanceDate ? new Date(row.maintenanceDate).toLocaleDateString() : '-' }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="maintenanceType" label="维护类型" width="100">
+            <template #default="{ row }">
+              <el-tag :type="getMaintenanceTypeColor(row.maintenanceType)">
+                {{ row.maintenanceType }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop="maintenanceContent"
+            label="维护内容"
+            min-width="150"
+            show-overflow-tooltip
+          />
+          <el-table-column prop="maintenancePerson" label="维护人员" width="100" />
+          <el-table-column prop="maintenanceCost" label="维护费用" width="100">
+            <template #default="{ row }">
+              <span class="text-red-600 font-medium">
+                {{ row.maintenanceCost ? `¥${row.maintenanceCost}` : '-' }}
+              </span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="maintenanceStatus" label="状态" width="100">
+            <template #default="{ row }">
+              <el-tag :type="getMaintenanceStatusColor(row.maintenanceStatus)">
+                {{ row.maintenanceStatus }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="200" fixed="right">
+            <template #default="{ row }">
+              <div class="flex gap-2">
+                <el-button
+                  type="warning"
+                  size="small"
+                  @click="handleEditMaintenance(row)"
+                  :icon="Edit"
+                >
+                  编辑
+                </el-button>
+                <el-button
+                  type="danger"
+                  size="small"
+                  @click="handleDeleteMaintenance(row)"
+                  :icon="Delete"
+                >
+                  删除
+                </el-button>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <!-- 空状态 -->
+        <div v-if="maintenanceList.length === 0" class="text-center py-12">
+          <Wrench class="w-16 h-16 text-gray-400 mx-auto mb-4" />
+          <p class="text-gray-500 text-lg">暂无维护记录</p>
+          <p class="text-gray-400 text-sm mt-2">点击上方按钮添加维护记录</p>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="flex justify-end">
+          <el-button @click="maintenanceDialogVisible = false">关闭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 维护记录新增/编辑对话框 -->
+    <el-dialog
+      v-model="maintenanceRecordDialogVisible"
+      :title="isMaintenanceEdit ? '编辑维护记录' : '新增维护记录'"
+      width="600px"
+      :close-on-click-modal="false"
+    >
+      <el-form :model="maintenanceForm" label-width="100px" class="grid grid-cols-2 gap-4">
+        <el-form-item label="维护时间" required>
+          <el-date-picker
+            v-model="maintenanceForm.maintenanceDate"
+            type="date"
+            placeholder="请选择维护时间"
+            class="w-full"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+          />
+        </el-form-item>
+
+        <el-form-item label="维护类型" required>
+          <el-select
+            v-model="maintenanceForm.maintenanceType"
+            placeholder="请选择维护类型"
+            class="w-full"
+          >
+            <el-option label="定期保养" value="定期保养" />
+            <el-option label="故障维修" value="故障维修" />
+            <el-option label="清洁保养" value="清洁保养" />
+            <el-option label="零件更换" value="零件更换" />
+            <el-option label="升级改造" value="升级改造" />
+            <el-option label="其他" value="其他" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="维护人员">
+          <el-input v-model="maintenanceForm.maintenancePerson" placeholder="请输入维护人员" />
+        </el-form-item>
+
+        <el-form-item label="维护费用">
+          <el-input-number
+            v-model="maintenanceForm.maintenanceCost"
+            :min="0"
+            :precision="2"
+            placeholder="请输入维护费用"
+            class="w-full"
+          />
+        </el-form-item>
+
+        <el-form-item label="维护状态" required>
+          <el-select
+            v-model="maintenanceForm.maintenanceStatus"
+            placeholder="请选择维护状态"
+            class="w-full"
+          >
+            <el-option label="待处理" value="待处理" />
+            <el-option label="进行中" value="进行中" />
+            <el-option label="已完成" value="已完成" />
+            <el-option label="已取消" value="已取消" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="维护内容" class="col-span-2">
+          <el-input
+            v-model="maintenanceForm.maintenanceContent"
+            type="textarea"
+            :rows="4"
+            placeholder="请输入详细的维护内容描述"
+          />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="flex justify-end gap-3">
+          <el-button @click="maintenanceRecordDialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleMaintenanceSubmit">确定</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
   </div>
 </template>
 </template>