Selaa lähdekoodia

feat(zfgl): 新增租房信息管理功能

- 实现了房屋信息的新增、编辑、删除和详情查看功能
- 添加了房屋信息的搜索和筛选功能- 集成了房屋基本信息和详细信息的管理
- 优化了表格展示和对话框样式
nahida 10 kuukautta sitten
vanhempi
commit
79c5441ac8
1 muutettua tiedostoa jossa 644 lisäystä ja 0 poistoa
  1. 644 0
      src/views/zfgl/zfxxgl.vue

+ 644 - 0
src/views/zfgl/zfxxgl.vue

@@ -0,0 +1,644 @@
+<script setup lang="ts">
+import { onMounted, reactive, ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Delete, Edit, Eye, Home, Plus, Search } from 'lucide-vue-next'
+import { clientGet, clientPost } from '@/utils/request.ts'
+
+interface ASimplifiedHouseInfo {
+  id: string
+  assetType?: string | null
+  building?: string | null
+  floor?: string | null
+  houseName?: string | null
+  address?: string | null
+  status?: string | null
+  rentRange?: string | null
+  createTime?: Date | null
+  updateTime?: Date | null
+}
+
+interface ASimplifiedHouseInfoReponse extends BaseResponse {
+  data: PageType<ASimplifiedHouseInfo[]>
+}
+
+interface AddASimplifiedHouseInfo {
+  assetType?: string | null
+  building?: string | null
+  floor?: string | null
+  houseName?: string | null
+  address?: string | null
+  status?: string | null
+  rentRange?: string | null
+}
+
+interface UpdateASimplifiedHouseInfo {
+  id: string
+  assetType?: string | null
+  building?: string | null
+  floor?: string | null
+  houseName?: string | null
+  address?: string | null
+  status?: string | null
+  rentRange?: string | null
+}
+
+interface AHouseInfoDetail {
+  id: string
+  simplifiedHouseId?: string | null
+  area?: string | null
+  introduce?: string | null
+  houseType?: string | null
+  createTime?: Date | null
+  updateTime?: Date | null
+}
+
+interface AHouseInfoDetailResponse extends BaseResponse {
+  data: AHouseInfoDetail
+}
+
+interface AddAHouseInfoDetail {
+  simplifiedHouseId: string
+  area?: string | null
+  introduce?: string | null
+  houseType?: string | null
+}
+
+interface UpdateAHouseInfoDetail {
+  id: string
+  simplifiedHouseId: string
+  area?: string | null
+  introduce?: string | null
+  houseType?: string | null
+}
+
+// 响应式数据
+const loading = ref(false)
+const tableData = ref<ASimplifiedHouseInfo[]>([])
+const total = ref(0)
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 搜索表单
+const searchForm = reactive({
+  status: '',
+  houseName: '',
+  building: '',
+  assetType: '',
+})
+
+// 对话框控制
+const dialogVisible = ref(false)
+const detailDialogVisible = ref(false)
+const isEdit = ref(false)
+const dialogTitle = ref('新增房屋信息')
+
+// 表单数据
+const houseForm = reactive<AddASimplifiedHouseInfo & { id?: string }>({
+  assetType: '',
+  building: '',
+  floor: '',
+  houseName: '',
+  address: '',
+  status: '空闲',
+  rentRange: '',
+})
+
+const detailForm = reactive<AddAHouseInfoDetail & { id?: string }>({
+  simplifiedHouseId: '',
+  area: '',
+  introduce: '',
+  houseType: '',
+})
+
+// 选中的行
+const selectedRows = ref<ASimplifiedHouseInfo[]>([])
+const currentHouseId = ref('')
+
+// 模拟数据
+const mockHouseList = ref<ASimplifiedHouseInfo[]>([
+  {
+    id: '1',
+    assetType: '公租房',
+    building: 'A栋',
+    floor: '1楼',
+    houseName: 'A栋101',
+    address: '某某小区A栋101室',
+    status: '空闲',
+    rentRange: '1000-1500元/月',
+    createTime: new Date(),
+    updateTime: new Date(),
+  },
+  {
+    id: '2',
+    assetType: '厂房',
+    building: 'B栋',
+    floor: '2楼',
+    houseName: 'B栋201',
+    address: '某某工业园B栋201室',
+    status: '已租',
+    rentRange: '2000-2500元/月',
+    createTime: new Date(),
+    updateTime: new Date(),
+  },
+])
+
+// API方法
+const addRentingHouse = async (info: AddASimplifiedHouseInfo) => {
+  const res = await clientPost<AddASimplifiedHouseInfo, BaseResponse>(
+    '/asimplifiedHouseInfo/save',
+    info,
+  )
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const updateRentingHouse = async (info: UpdateASimplifiedHouseInfo) => {
+  const res = await clientPost<UpdateASimplifiedHouseInfo, BaseResponse>(
+    '/asimplifiedHouseInfo/update',
+    info,
+  )
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const deleteBatchRentingHouse = async (ids: string[]) => {
+  const res = await clientPost<string[], BaseResponse>('/asimplifiedHouseInfo/deleteBatch', ids)
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const getList = async () => {
+  loading.value = true
+  try {
+    const params: any = {
+      pageNum: currentPage.value,
+      pageSize: pageSize.value,
+    }
+
+    if (searchForm.status) params.status = searchForm.status
+    if (searchForm.houseName) params.houseName = searchForm.houseName
+    if (searchForm.building) params.building = searchForm.building
+    if (searchForm.assetType) params.assetType = searchForm.assetType
+
+    const res = await clientGet<any, ASimplifiedHouseInfoReponse>(
+      '/asimplifiedHouseInfo/findByPage',
+      { params },
+    )
+    if (res.code !== 200) {
+      ElMessage.error(res.msg)
+      return
+    }
+    tableData.value = res.data.records
+    total.value = res.data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+const addRentingHouseDetail = async (info: AddAHouseInfoDetail) => {
+  const res = await clientPost<AddAHouseInfoDetail, BaseResponse>('/ahouseInfoDetail/save', info)
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const updateRentingHouseDetail = async (info: UpdateAHouseInfoDetail) => {
+  const res = await clientPost<UpdateAHouseInfoDetail, BaseResponse>(
+    '/ahouseInfoDetail/update',
+    info,
+  )
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return false
+  }
+  ElMessage.success(res.msg)
+  return true
+}
+
+const getDetail = async (simplifiedHouseId: string) => {
+  const res = await clientGet<{ id: string }, AHouseInfoDetailResponse>(
+    '/ahouseInfoDetail/getBySimplifiedHouseId',
+    {
+      params: { simplifiedHouseId },
+    },
+  )
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return null
+  }
+  return res.data
+}
+
+// 页面方法
+const handleSearch = () => {
+  currentPage.value = 1
+  getList()
+}
+
+const handleReset = () => {
+  Object.assign(searchForm, {
+    status: '',
+    houseName: '',
+    building: '',
+    assetType: '',
+  })
+  handleSearch()
+}
+
+const handleAdd = () => {
+  isEdit.value = false
+  dialogTitle.value = '新增房屋信息'
+  Object.assign(houseForm, {
+    assetType: '',
+    building: '',
+    floor: '',
+    houseName: '',
+    address: '',
+    status: '空闲',
+    rentRange: '',
+  })
+  dialogVisible.value = true
+}
+
+const handleEdit = (row: ASimplifiedHouseInfo) => {
+  isEdit.value = true
+  dialogTitle.value = '编辑房屋信息'
+  Object.assign(houseForm, { ...row })
+  dialogVisible.value = true
+}
+
+const handleDelete = async (row: ASimplifiedHouseInfo) => {
+  try {
+    await ElMessageBox.confirm('确定要删除这条记录吗?', '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    })
+
+    const success = await deleteBatchRentingHouse([row.id])
+    if (success) {
+      getList()
+    }
+  } catch {
+    // 用户取消删除
+  }
+}
+
+const handleBatchDelete = async () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning('请选择要删除的记录')
+    return
+  }
+
+  try {
+    await ElMessageBox.confirm(`确定要删除选中的 ${selectedRows.value.length} 条记录吗?`, '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    })
+
+    const ids = selectedRows.value.map((row) => row.id)
+    const success = await deleteBatchRentingHouse(ids)
+    if (success) {
+      getList()
+    }
+  } catch {
+    // 用户取消删除
+  }
+}
+
+const handleViewDetail = async (row: ASimplifiedHouseInfo) => {
+  currentHouseId.value = row.id
+  const detail = await getDetail(row.id)
+  if (detail) {
+    Object.assign(detailForm, { ...detail, simplifiedHouseId: row.id })
+  } else {
+    Object.assign(detailForm, {
+      id: '',
+      simplifiedHouseId: row.id,
+      area: '',
+      introduce: '',
+      houseType: '',
+    })
+  }
+  detailDialogVisible.value = true
+}
+
+const handleSubmit = async () => {
+  let success = false
+  if (isEdit.value) {
+    success = await updateRentingHouse(houseForm as UpdateASimplifiedHouseInfo)
+  } else {
+    success = await addRentingHouse(houseForm)
+  }
+
+  if (success) {
+    dialogVisible.value = false
+    getList()
+  }
+}
+
+const handleDetailSubmit = async () => {
+  let success = false
+  if (detailForm.id) {
+    success = await updateRentingHouseDetail(detailForm as UpdateAHouseInfoDetail)
+  } else {
+    success = await addRentingHouseDetail(detailForm)
+  }
+
+  if (success) {
+    detailDialogVisible.value = false
+  }
+}
+
+const handleSelectionChange = (selection: ASimplifiedHouseInfo[]) => {
+  selectedRows.value = selection
+}
+
+const handlePageChange = (page: number) => {
+  currentPage.value = page
+  getList()
+}
+
+const handleSizeChange = (size: number) => {
+  pageSize.value = size
+  currentPage.value = 1
+  getList()
+}
+
+onMounted(() => {
+  getList()
+})
+</script>
+
+<template>
+  <div class="p-6 bg-gray-50 min-h-screen">
+    <div class="bg-white rounded-lg shadow-sm">
+      <!-- 页面标题 -->
+      <div class="flex items-center gap-3 p-6 border-b border-gray-200">
+        <div class="flex items-center justify-center w-10 h-10 bg-blue-100 rounded-lg">
+          <Home class="w-5 h-5 text-blue-600" />
+        </div>
+        <div>
+          <h1 class="text-xl font-semibold text-gray-900">租房信息管理</h1>
+          <p class="text-sm text-gray-500">管理房屋基本信息和详细信息</p>
+        </div>
+      </div>
+
+      <!-- 搜索区域 -->
+      <div class="p-6 border-b border-gray-200">
+        <el-form :model="searchForm" inline class="flex flex-wrap gap-4">
+          <el-form-item label="资产类型">
+            <el-select
+              v-model="searchForm.assetType"
+              placeholder="请选择资产类型"
+              clearable
+              class="w-40"
+            >
+              <el-option label="公租房" value="公租房" />
+              <el-option label="厂房" value="厂房" />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="楼栋">
+            <el-input
+              v-model="searchForm.building"
+              placeholder="请输入楼栋"
+              clearable
+              class="w-40"
+            />
+          </el-form-item>
+
+          <el-form-item label="房间名称">
+            <el-input
+              v-model="searchForm.houseName"
+              placeholder="请输入房间名称"
+              clearable
+              class="w-40"
+            />
+          </el-form-item>
+
+          <el-form-item label="状态">
+            <el-select v-model="searchForm.status" placeholder="请选择状态" clearable class="w-32">
+              <el-option label="空闲" value="空闲" />
+              <el-option label="已租" value="已租" />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item>
+            <el-button type="primary" @click="handleSearch" :icon="Search">搜索</el-button>
+            <el-button @click="handleReset">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <!-- 操作按钮区域 -->
+      <div class="flex items-center justify-between p-6">
+        <div class="flex gap-3">
+          <el-button type="primary" @click="handleAdd" :icon="Plus">新增房屋</el-button>
+          <el-button
+            type="danger"
+            @click="handleBatchDelete"
+            :disabled="selectedRows.length === 0"
+            :icon="Delete"
+          >
+            批量删除
+          </el-button>
+        </div>
+        <div class="text-sm text-gray-500">共 {{ total }} 条记录</div>
+      </div>
+
+      <!-- 数据表格 -->
+      <div class="px-6">
+        <el-table
+          :data="tableData"
+          v-loading="loading"
+          @selection-change="handleSelectionChange"
+          class="w-full"
+          stripe
+        >
+          <el-table-column type="selection" width="55" />
+
+          <el-table-column prop="assetType" label="资产类型" width="100">
+            <template #default="{ row }">
+              <el-tag :type="row.assetType === '公租房' ? 'primary' : 'success'">
+                {{ row.assetType }}
+              </el-tag>
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="houseName" label="房间名称" width="120" />
+          <el-table-column prop="building" label="楼栋" width="100" />
+          <el-table-column prop="floor" label="楼层" width="100" />
+          <el-table-column prop="address" label="地址" min-width="200" show-overflow-tooltip />
+
+          <el-table-column prop="status" label="状态" width="100">
+            <template #default="{ row }">
+              <el-tag :type="row.status === '空闲' ? 'success' : 'warning'">
+                {{ row.status }}
+              </el-tag>
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="rentRange" label="租金范围" width="150" />
+
+          <el-table-column label="操作" width="200" fixed="right">
+            <template #default="{ row }">
+              <div class="flex gap-2">
+                <el-button type="primary" size="small" @click="handleViewDetail(row)" :icon="Eye">
+                  详情
+                </el-button>
+                <el-button type="warning" size="small" @click="handleEdit(row)" :icon="Edit">
+                  编辑
+                </el-button>
+                <el-button type="danger" size="small" @click="handleDelete(row)" :icon="Delete">
+                  删除
+                </el-button>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!-- 分页 -->
+      <div class="flex justify-center p-6">
+        <el-pagination
+          v-model:current-page="currentPage"
+          v-model:page-size="pageSize"
+          :page-sizes="[10, 20, 50, 100]"
+          :total="total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handlePageChange"
+        />
+      </div>
+    </div>
+
+    <!-- 新增/编辑对话框 -->
+    <el-dialog
+      v-model="dialogVisible"
+      :title="dialogTitle"
+      width="600px"
+      :close-on-click-modal="false"
+    >
+      <el-form :model="houseForm" label-width="100px" class="grid grid-cols-2 gap-4">
+        <el-form-item label="资产类型" required>
+          <el-select v-model="houseForm.assetType" placeholder="请选择资产类型" class="w-full">
+            <el-option label="公租房" value="公租房" />
+            <el-option label="厂房" value="厂房" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="楼栋" required>
+          <el-input v-model="houseForm.building" placeholder="请输入楼栋" />
+        </el-form-item>
+
+        <el-form-item label="楼层">
+          <el-input v-model="houseForm.floor" placeholder="请输入楼层" />
+        </el-form-item>
+
+        <el-form-item label="房间名称" required>
+          <el-input v-model="houseForm.houseName" placeholder="请输入房间名称" />
+        </el-form-item>
+
+        <el-form-item label="状态" required>
+          <el-select v-model="houseForm.status" placeholder="请选择状态" class="w-full">
+            <el-option label="空闲" value="空闲" />
+            <el-option label="已租" value="已租" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="租金范围">
+          <el-input v-model="houseForm.rentRange" placeholder="请输入租金范围" />
+        </el-form-item>
+
+        <el-form-item label="地址" class="col-span-2">
+          <el-input v-model="houseForm.address" placeholder="请输入详细地址" />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="flex justify-end gap-3">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleSubmit">确定</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 详细信息对话框 -->
+    <el-dialog
+      v-model="detailDialogVisible"
+      title="房屋详细信息"
+      width="500px"
+      :close-on-click-modal="false"
+    >
+      <el-form :model="detailForm" label-width="100px">
+        <el-form-item label="面积">
+          <el-input v-model="detailForm.area" placeholder="请输入面积" />
+        </el-form-item>
+
+        <el-form-item label="房屋类型">
+          <el-select v-model="detailForm.houseType" 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="detailForm.introduce"
+            type="textarea"
+            :rows="4"
+            placeholder="请输入房屋介绍"
+          />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="flex justify-end gap-3">
+          <el-button @click="detailDialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleDetailSubmit">保存</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<style scoped>
+.el-form-item {
+  margin-bottom: 18px;
+}
+
+.el-table {
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.el-dialog__header {
+  padding: 20px 20px 10px;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.el-dialog__body {
+  padding: 20px;
+}
+</style>