pyt
2025-03-20 c594eef54b6a7ae813ac3aede5ff6207d60b92e7
Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/chongzhouResettle
15个文件已修改
10个文件已添加
5100 ■■■■ 已修改文件
.env.development 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.production 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.staging 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/application-batch.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/placement.js 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/RightToolbar/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/modal.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/applicationBatchList/components/ApprovalDialog.vue 395 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/applicationBatchList/components/UploadDialog.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/applicationBatchList/detail.vue 191 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/applicationBatchList/list.vue 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/applicationBatchList/service.js 补丁 | 查看 | 原始文档 | blame | 历史
src/views/placement-batch/addResettle.vue 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/placement-batch/applayPerson.vue 601 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/placement-batch/components/ApprovalDialog.vue 619 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/placement-batch/components/exportMoneyApplay.vue 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/placement-batch/index.vue 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/placement-batch/person.vue 414 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/relocatablePersonnel/add.vue 476 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/relocatablePersonnel/detail.vue 484 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/relocatablePersonnel/edit.vue 476 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/relocatablePersonnel/index.vue 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -1,10 +1,10 @@
# 页面标题
VUE_APP_TITLE = 若依管理系统
VUE_APP_TITLE = 崇州自主安置管理后台
# 开发环境配置
ENV = 'development'
# 若依管理系统/开发环境
# 崇州自主安置管理后台/开发环境
VUE_APP_BASE_API = 'http://182.140.209.168:8888/api'
# 路由懒加载
.env.production
@@ -1,8 +1,8 @@
# 页面标题
VUE_APP_TITLE = 若依管理系统
VUE_APP_TITLE = 崇州自主安置管理后台
# 生产环境配置
ENV = 'production'
# 若依管理系统/生产环境
# 崇州自主安置管理后台/生产环境
VUE_APP_BASE_API = '/prod-api'
.env.staging
@@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = 若依管理系统
VUE_APP_TITLE = 崇州自主安置管理后台
BABEL_ENV = production
@@ -8,5 +8,5 @@
# 测试环境配置
ENV = 'staging'
# 若依管理系统/测试环境
# 崇州自主安置管理后台/测试环境
VUE_APP_BASE_API = '/stage-api'
package.json
@@ -1,7 +1,7 @@
{
  "name": "ruoyi",
  "version": "3.8.9",
  "description": "若依管理系统",
  "description": "崇州自主安置管理后台",
  "author": "若依",
  "license": "MIT",
  "scripts": {
src/api/application-batch.js
New file
@@ -0,0 +1,26 @@
import request from '@/utils/request'
// 补偿标准信息
export function geTabletList(data) {
  return request({
    url: '/placement-apply/page',
    method: 'post',
    data
  })
}
//安置新增审批批次
export function importBatch(data) {
  return request({
    url: '/placement-apply/imports',
    method: 'post',
    data
  })
}
//安置详情列表
export function geDetailTabletList(data) {
  return request({
    url: '/placement-apply/detail',
    method: 'post',
    data
  })
}
src/api/placement.js
New file
@@ -0,0 +1,61 @@
import request from '@/utils/request'
// 列表
export function getListData(data) {
    return request({
        url: '/placement/page',
        method: 'post',
        data
    })
}
// 下载模板
export function downloadTemplate() {
    return request({
        url: '/placement/download-template',
        method: 'post'
    })
}
// 新增
export function add(data) {
    return request({
        url: '/placement/add',
        method: 'post',
        data
    })
}
// 详情
export function getDetail(data) {
    return request({
        url: '/placement/detail',
        method: 'post',
        data
    })
}
// 修改
export function update(data) {
    return request({
        url: '/placement/edit',
        method: 'post',
        data
    })
}
// 删除
export function del(data) {
    return request({
        url: '/placement/del',
        method: 'post',
        data
    })
}
// 根据字典类型查询字典数据信息
export function getDictData(data) {
    return request({
        url: `/system/dict/data/type/${data}`,
        method: 'get'
    })
}
src/components/RightToolbar/index.vue
@@ -1,9 +1,9 @@
<template>
  <div class="top-right-btn" :style="style">
    <el-row>
      <el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
      <!-- <el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
        <el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
      </el-tooltip>
      </el-tooltip> -->
      <el-tooltip class="item" effect="dark" content="刷新" placement="top">
        <el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" />
      </el-tooltip>
src/plugins/modal.js
@@ -53,7 +53,7 @@
  },
  // 确认窗体
  confirm(content) {
    return MessageBox.confirm(content, "系统提示", {
    return MessageBox.confirm(content, "提示", {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: "warning",
@@ -61,7 +61,7 @@
  },
  // 提交内容
  prompt(content) {
    return MessageBox.prompt(content, "系统提示", {
    return MessageBox.prompt(content, "提示", {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: "warning",
src/router/index.js
@@ -69,6 +69,59 @@
      }
    ]
  },
  {
    path: '/placement/batch',
    component: Layout,
    children: [
      {
        path: 'personnel',
        component: () => import('@/views/placement-batch/person'),
        name: 'PlacementBatchPerson',
        meta: { title: '需安置人员信息列表', activeMenu: '/placement-batch/list' }
      }
    ]
  },
  {
    path: '/placement/batch',
    component: Layout,
    children: [
      {
        path: 'addResettle',
        component: () => import('@/views/placement-batch/addResettle'),
        name: 'AddResettle',
        meta: { title: '编辑安置户信息', activeMenu: '/placement-batch/list' }
      }
    ]
  },
  {
    path: '/placement/batch',
    component: Layout,
    children: [
      {
        path: 'applayPerson',
        component: () => import('@/views/placement-batch/applayPerson'),
        name: 'ApplayPerson',
        meta: { title: '新增安置户申请详情', activeMenu: '/placement-batch/list' }
      }
    ]
  },
  // {
  //   path: '/user',
  //   component: Layout,
  //   hidden: true,
  //   redirect: 'noredirect',
  //   children: [
  //     {
  //       path: 'profile',
  //       component: () => import('@/views/system/user/profile/index'),
  //       name: 'Profile',
  //       meta: { title: '个人中心', icon: 'user' }
  //     }
  //   ]
  // }
]
// 动态路由,基于用户权限动态去加载
src/views/applicationBatchList/components/ApprovalDialog.vue
@@ -1,428 +1,198 @@
<template>
  <el-dialog
    :title="type === 'audit' ? '审批安置户申请信息' : '安置户申请信息'"
    :visible.sync="dialogVisible"
    width="80%"
    :close-on-click-modal="false"
    :append-to-body="true"
  >
  <el-dialog :title="type === 'audit' ? '审批安置户申请信息' : '安置户申请信息'" :visible.sync="dialogVisible" width="80%"
    :close-on-click-modal="false" :append-to-body="true">
    <div class="approval-content">
      <!-- 左侧表格区域 -->
      <div class="table-container">
        <el-table
          :data="tableData"
          border
          style="width: 100%"
          :row-class-name="tableRowClassName"
        >
          <el-table-column
            type="index"
            label="序号"
            width="50"
            align="center"
          />
          <el-table-column
            prop="town"
            label="镇(街道)"
            align="center"
            width="80"
          >
        <el-table :data="tableData" border style="width: 100%" :row-class-name="tableRowClassName">
          <el-table-column type="index" label="序号" width="50" align="center" />
          <el-table-column prop="town" label="镇(街道)" align="center" width="80">
            <template slot-scope="scope">
              {{ scope.row.town }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.town"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.town" placement="top">
                <div slot="content">{{ scope.row.errors.town }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="projectName"
            label="拆迁项目名称"
            align="center"
            width="150"
          >
          <el-table-column prop="projectName" label="拆迁项目名称" align="center" width="150">
            <template slot-scope="scope">
              {{ scope.row.projectName }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.projectName"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.projectName" placement="top">
                <div slot="content">{{ scope.row.errors.projectName }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="village"
            label="所在村(社区)"
            align="center"
            width="100"
          >
          <el-table-column prop="village" label="所在村(社区)" align="center" width="100">
            <template slot-scope="scope">
              {{ scope.row.village }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.village"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.village" placement="top">
                <div slot="content">{{ scope.row.errors.village }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="time"
            label="拆迁时间"
            align="center"
            width="100"
          >
          <el-table-column prop="time" label="拆迁时间" align="center" width="100">
            <template slot-scope="scope">
              {{ scope.row.time }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.time"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.time" placement="top">
                <div slot="content">{{ scope.row.errors.time }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="owner"
            label="产主姓名"
            align="center"
            width="80"
          >
          <el-table-column prop="owner" label="产主姓名" align="center" width="80">
            <template slot-scope="scope">
              {{ scope.row.owner }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.owner"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.owner" placement="top">
                <div slot="content">{{ scope.row.errors.owner }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="idCard"
            label="身份证号"
            align="center"
            width="180"
          >
          <el-table-column prop="idCard" label="身份证号" align="center" width="180">
            <template slot-scope="scope">
              {{ scope.row.idCard }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.idCard"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.idCard" placement="top">
                <div slot="content">{{ scope.row.errors.idCard }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="contact"
            label="联系电话"
            align="center"
            width="120"
          >
          <el-table-column prop="contact" label="联系电话" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.contact }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.contact"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.contact" placement="top">
                <div slot="content">{{ scope.row.errors.contact }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column label="家庭安置人数(人)" align="center">
            <el-table-column
              prop="resettlementPeople"
              label="集体经济组织成员"
              align="center"
              width="120"
            >
            <el-table-column prop="resettlementPeople" label="集体经济组织成员" align="center" width="120">
              <template slot-scope="scope">
                {{ scope.row.resettlementPeople }}
                <el-tooltip
                  v-if="scope.row.errors && scope.row.errors.resettlementPeople"
                  placement="top"
                >
                <el-tooltip v-if="scope.row.errors && scope.row.errors.resettlementPeople" placement="top">
                  <div slot="content">
                    {{ scope.row.errors.resettlementPeople }}
                  </div>
                  <i
                    class="el-icon-warning"
                    style="color: #e6a23c; margin-left: 5px"
                  ></i>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column
              prop="additionalPeople"
              label="非集体经济组织成员"
              align="center"
              width="120"
            >
            <el-table-column prop="additionalPeople" label="非集体经济组织成员" align="center" width="120">
              <template slot-scope="scope">
                {{ scope.row.additionalPeople }}
                <el-tooltip
                  v-if="scope.row.errors && scope.row.errors.additionalPeople"
                  placement="top"
                >
                <el-tooltip v-if="scope.row.errors && scope.row.errors.additionalPeople" placement="top">
                  <div slot="content">
                    {{ scope.row.errors.additionalPeople }}
                  </div>
                  <i
                    class="el-icon-warning"
                    style="color: #e6a23c; margin-left: 5px"
                  ></i>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column
              prop="totalPeople"
              label="合计"
              align="center"
              width="60"
            >
            <el-table-column prop="totalPeople" label="合计" align="center" width="60">
              <template slot-scope="scope">
                {{ scope.row.totalPeople }}
                <el-tooltip
                  v-if="scope.row.errors && scope.row.errors.totalPeople"
                  placement="top"
                >
                <el-tooltip v-if="scope.row.errors && scope.row.errors.totalPeople" placement="top">
                  <div slot="content">{{ scope.row.errors.totalPeople }}</div>
                  <i
                    class="el-icon-warning"
                    style="color: #e6a23c; margin-left: 5px"
                  ></i>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
          </el-table-column>
          <el-table-column
            prop="houseName"
            label="待安置家庭成员姓名"
            align="center"
            width="120"
          >
          <el-table-column prop="houseName" label="待安置家庭成员姓名" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.houseName }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.houseName"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.houseName" placement="top">
                <div slot="content">{{ scope.row.errors.houseName }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="area"
            label="待安置人员应安置面积合计(㎡)"
            align="center"
            width="120"
          >
          <el-table-column prop="area" label="待安置人员应安置面积合计(㎡)" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.area }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.area"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.area" placement="top">
                <div slot="content">{{ scope.row.errors.area }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column label="补偿金额(万元)" align="center">
            <el-table-column
              prop="firstPayment"
              label="新建商品住房、商业用房、停车位"
              align="center"
              width="100"
            >
            <el-table-column prop="firstPayment" label="新建商品住房、商业用房、停车位" align="center" width="100">
              <template slot-scope="scope">
                {{ scope.row.firstPayment }}
                <el-tooltip
                  v-if="scope.row.errors && scope.row.errors.firstPayment"
                  placement="top"
                >
                <el-tooltip v-if="scope.row.errors && scope.row.errors.firstPayment" placement="top">
                  <div slot="content">{{ scope.row.errors.firstPayment }}</div>
                  <i
                    class="el-icon-warning"
                    style="color: #e6a23c; margin-left: 5px"
                  ></i>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column
              prop="secondPayment"
              label="二手住房"
              align="center"
              width="80"
            >
            <el-table-column prop="secondPayment" label="二手住房" align="center" width="80">
              <template slot-scope="scope">
                {{ scope.row.secondPayment }}
                <el-tooltip
                  v-if="scope.row.errors && scope.row.errors.secondPayment"
                  placement="top"
                >
                <el-tooltip v-if="scope.row.errors && scope.row.errors.secondPayment" placement="top">
                  <div slot="content">{{ scope.row.errors.secondPayment }}</div>
                  <i
                    class="el-icon-warning"
                    style="color: #e6a23c; margin-left: 5px"
                  ></i>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column
              prop="totalPayment"
              label="合计"
              align="center"
              width="60"
            >
            <el-table-column prop="totalPayment" label="合计" align="center" width="60">
              <template slot-scope="scope">
                {{ scope.row.totalPayment }}
                <el-tooltip
                  v-if="scope.row.errors && scope.row.errors.totalPayment"
                  placement="top"
                >
                <el-tooltip v-if="scope.row.errors && scope.row.errors.totalPayment" placement="top">
                  <div slot="content">{{ scope.row.errors.totalPayment }}</div>
                  <i
                    class="el-icon-warning"
                    style="color: #e6a23c; margin-left: 5px"
                  ></i>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
          </el-table-column>
          <el-table-column
            prop="monthlyPayment"
            label="25%首付款(万元)"
            align="center"
            width="130"
          >
          <el-table-column prop="monthlyPayment" label="25%首付款(万元)" align="center" width="130">
            <template slot-scope="scope">
              {{ scope.row.monthlyPayment }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.monthlyPayment"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.monthlyPayment" placement="top">
                <div slot="content">{{ scope.row.errors.monthlyPayment }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="remainingPayment"
            label="每季度需支付款项(万元)"
            align="center"
            width="120"
          >
          <el-table-column prop="remainingPayment" label="每季度需支付款项(万元)" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.remainingPayment }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.remainingPayment"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.remainingPayment" placement="top">
                <div slot="content">
                  {{ scope.row.errors.remainingPayment }}
                </div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="totalPaid"
            label="过渡补贴(万元)"
            align="center"
            width="60"
          >
          <el-table-column prop="totalPaid" label="过渡补贴(万元)" align="center" width="60">
            <template slot-scope="scope">
              {{ scope.row.totalPaid }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.totalPaid"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.totalPaid" placement="top">
                <div slot="content">{{ scope.row.errors.totalPaid }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="remark" label="备注" align="center" width="60">
            <template slot-scope="scope">
              {{ scope.row.remark }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.remark"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.remark" placement="top">
                <div slot="content">{{ scope.row.errors.remark }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column
            prop="difference"
            label="购房差异情况"
            align="center"
            width="60"
          >
          <el-table-column prop="difference" label="购房差异情况" align="center" width="60">
            <template slot-scope="scope">
              {{ scope.row.difference }}
              <el-tooltip
                v-if="scope.row.errors && scope.row.errors.difference"
                placement="top"
              >
              <el-tooltip v-if="scope.row.errors && scope.row.errors.difference" placement="top">
                <div slot="content">{{ scope.row.errors.difference }}</div>
                <i
                  class="el-icon-warning"
                  style="color: #e6a23c; margin-left: 5px"
                ></i>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
@@ -436,11 +206,7 @@
          <template v-if="type === 'audit'">
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar
                  size="small"
                  icon="el-icon-user"
                  :style="{ background: '#6d78ff' }"
                ></el-avatar>
                <el-avatar size="small" icon="el-icon-user" :style="{ background: '#6d78ff' }"></el-avatar>
              </div>
              <div class="timeline-content info-box">
                <div class="info-line">
@@ -458,16 +224,10 @@
            <div class="timeline-divider"></div>
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar
                  size="small"
                  icon="el-icon-time"
                  :style="{ background: '#909399' }"
                ></el-avatar>
                <el-avatar size="small" icon="el-icon-time" :style="{ background: '#909399' }"></el-avatar>
              </div>
              <div class="timeline-content">
                <el-button size="small" disabled class="waiting-btn"
                  >等待审核</el-button
                >
                <el-button size="small" disabled class="waiting-btn">等待审核</el-button>
              </div>
            </div>
          </template>
@@ -475,11 +235,7 @@
          <template v-else>
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar
                  size="small"
                  icon="el-icon-user"
                  :style="{ background: '#6d78ff' }"
                ></el-avatar>
                <el-avatar size="small" icon="el-icon-user" :style="{ background: '#6d78ff' }"></el-avatar>
              </div>
              <div class="timeline-content info-box">
                <div class="info-line">
@@ -497,11 +253,7 @@
            <div class="timeline-divider"></div>
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar
                  size="small"
                  icon="el-icon-user"
                  :style="{ background: '#6d78ff' }"
                ></el-avatar>
                <el-avatar size="small" icon="el-icon-user" :style="{ background: '#6d78ff' }"></el-avatar>
              </div>
              <div class="timeline-content info-box">
                <div class="info-line">
@@ -542,13 +294,8 @@
      <div class="audit-comment">
        <div class="comment-title">审批意见</div>
        <el-input
          type="textarea"
          :rows="4"
          placeholder="请输入审批意见"
          v-model="form.auditComment"
          :disabled="type === 'detail'"
        ></el-input>
        <el-input type="textarea" :rows="4" placeholder="请输入审批意见" v-model="form.auditComment"
          :disabled="type === 'detail'"></el-input>
      </div>
    </div>
@@ -869,4 +616,4 @@
.error-row {
  background-color: #ffecec !important;
}
</style>
</style>
src/views/applicationBatchList/components/UploadDialog.vue
@@ -1,15 +1,15 @@
<template>
  <el-dialog
    :title="type === 'add' ? '新增申请批次' : '批量导入'"
    :title="'导入自主购房安置申请'"
    :visible.sync="dialogVisible"
    width="40%"
    @close="handleClose"
  >
    <el-form ref="uploadForm" :model="form" :rules="rules" label-width="80px">
      <el-form-item label="批次号" prop="batchNo">
        <el-input v-model="form.batchNo" placeholder="请输入" />
    <el-form ref="uploadForm" :model="form" :rules="rules" label-width="180px">
      <el-form-item label="批次号" prop="batchNumber">
        <el-input v-model="form.batchNumber" placeholder="请输入" />
      </el-form-item>
      <el-form-item :label="type === 'add' ? '导入文件' : '批量文件'" prop="file">
      <el-form-item :label="'导入安置申请表'" prop="file">
        <el-upload
          class="upload-demo"
          drag
@@ -21,7 +21,7 @@
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
          <div class="el-upload__tip" slot="tip">
            支持扩展名:.doc .docx .pdf .jpg .png .xlsx .xls
            支持扩展名:.doc .docx .xlsx .xls
          </div>
        </el-upload>
      </el-form-item>
@@ -34,6 +34,7 @@
</template>
<script>
import { importBatch } from "@/api/application-batch";
export default {
  name: 'UploadDialog',
  props: {
@@ -41,23 +42,16 @@
      type: Boolean,
      default: false
    },
    type: {
      type: String,
      default: 'add',
      validator: function(value) {
        return ['add', 'batch'].indexOf(value) !== -1
      }
    }
  },
  data() {
    return {
      dialogVisible: false,
      form: {
        batchNo: '',
        batchNumber: '',
        file: null
      },
      rules: {
        batchNo: [
        batchNumber: [
          { required: true, message: '请输入批次号', trigger: 'blur' }
        ],
        file: [
@@ -76,7 +70,7 @@
  },
  methods: {
    handleClose() {
      this.form.batchNo = '';
      this.form.batchNumber = '';
      this.form.file = null;
      this.$refs.uploadForm && this.$refs.uploadForm.resetFields();
    },
@@ -94,10 +88,6 @@
        // 这里添加实际的上传逻辑
        const formData = new FormData();
        formData.append('file', this.form.file);
        if (this.type === 'add') {
          formData.append('batchNo', this.form.batchNo);
        }
        // 模拟上传
        this.$message.info('正在上传,请稍候...');
        setTimeout(() => {
@@ -112,7 +102,7 @@
<style scoped>
.upload-demo {
  text-align: center;
  text-align: left;
}
.el-upload {
  width: 100%;
src/views/applicationBatchList/detail.vue
@@ -3,7 +3,7 @@
    <!-- 头部信息卡片 -->
    <div class="batch-info">
      <div class="header">
        <div class="batch-title">批次号:{{ batchNo }}</div>
        <div class="batch-title">批次号:{{ batchInfo.batchNumber }}</div>
        <div class="back-btn">
          <el-button
            type="primary"
@@ -16,16 +16,16 @@
      </div>
      <div class="info-cards">
        <el-card class="box-card">
          <div class="card-title">29,183</div>
          <div class="card-title">{{ batchInfo.personNum }}</div>
          <div class="card-desc">申请总人数</div>
        </el-card>
        <el-card class="box-card">
          <div class="card-title">2,183 万元</div>
          <div class="card-title">{{ batchInfo.totalAmount }} 万元</div>
          <div class="card-desc">申请总金额</div>
        </el-card>
        <el-card class="box-card">
          <div class="card-title">2,183 ㎡</div>
          <div class="card-desc">居安置总面积</div>
          <div class="card-title">{{ batchInfo.waitFamilyArea }}㎡</div>
          <div class="card-desc">应安置总面积</div>
        </el-card>
      </div>
    </div>
@@ -34,7 +34,7 @@
    <el-form :inline="true" :model="queryParams" class="search-form">
      <el-form-item label="镇街">
        <el-input
          v-model="queryParams.town"
          v-model="queryParams.street"
          placeholder="请输入"
          clearable
          size="small"
@@ -50,7 +50,7 @@
      </el-form-item>
      <el-form-item label="所在村(社区)">
        <el-input
          v-model="queryParams.village"
          v-model="queryParams.community"
          placeholder="请输入"
          clearable
          size="small"
@@ -58,7 +58,7 @@
      </el-form-item>
      <el-form-item label="户主姓名/身份证号">
        <el-input
          v-model="queryParams.owner"
          v-model="queryParams.headOrIdCard"
          placeholder="请输入"
          clearable
          size="small"
@@ -79,7 +79,7 @@
    </el-form>
    <!-- 操作按钮区域 -->
    <el-row :gutter="10" class="mb8" v-if="status === '待审核'">
    <el-row :gutter="10" class="mb8" v-if="batchInfo.status == '0'">
      <el-col :span="1.5">
        <el-button type="primary" size="small" @click="handleAddHousehold"
          >新增安置户信息</el-button
@@ -123,14 +123,19 @@
      :row-class-name="tableRowClassName"
    >
      <el-table-column type="index" label="序号" width="50" align="center" />
      <el-table-column prop="town" label="镇(街道)" align="center" width="80">
      <el-table-column
        prop="street"
        label="镇(街道)"
        align="center"
        width="80"
      >
        <template slot-scope="scope">
          {{ scope.row.town }}
          {{ scope.row.street }}
          <el-tooltip
            v-if="scope.row.errors && scope.row.errors.town"
            v-if="scope.row.errors && scope.row.errors.street"
            placement="top"
          >
            <div slot="content">{{ scope.row.errors.town }}</div>
            <div slot="content">{{ scope.row.errors.street }}</div>
            <i
              class="el-icon-warning"
              style="color: #e6a23c; margin-left: 5px"
@@ -159,18 +164,18 @@
        </template>
      </el-table-column>
      <el-table-column
        prop="village"
        prop="community"
        label="所在村(社区)"
        align="center"
        width="100"
      >
        <template slot-scope="scope">
          {{ scope.row.village }}
          {{ scope.row.community }}
          <el-tooltip
            v-if="scope.row.errors && scope.row.errors.village"
            v-if="scope.row.errors && scope.row.errors.community"
            placement="top"
          >
            <div slot="content">{{ scope.row.errors.village }}</div>
            <div slot="content">{{ scope.row.errors.community }}</div>
            <i
              class="el-icon-warning"
              style="color: #e6a23c; margin-left: 5px"
@@ -193,14 +198,19 @@
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column prop="owner" label="产主姓名" align="center" width="80">
      <el-table-column
        prop="headOrIdCard"
        label="产主姓名"
        align="center"
        width="80"
      >
        <template slot-scope="scope">
          {{ scope.row.owner }}
          {{ scope.row.headOrIdCard }}
          <el-tooltip
            v-if="scope.row.errors && scope.row.errors.owner"
            v-if="scope.row.errors && scope.row.errors.headOrIdCard"
            placement="top"
          >
            <div slot="content">{{ scope.row.errors.owner }}</div>
            <div slot="content">{{ scope.row.errors.headOrIdCard }}</div>
            <i
              class="el-icon-warning"
              style="color: #e6a23c; margin-left: 5px"
@@ -513,34 +523,32 @@
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        align="center"
        width="150"
        fixed="right"
      >
      <el-table-column label="操作" align="center" width="150" fixed="right">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            @click="handleHouseholdDetail(scope.row)"
          >详情</el-button>
            >详情</el-button
          >
          <template v-if="status === '待审核'">
            <el-button
              size="mini"
              type="text"
              @click="handleHouseholdEdit(scope.row)"
            >编辑</el-button>
              >编辑</el-button
            >
            <el-button
              size="mini"
              type="text"
              @click="handleHouseholdDelete(scope.row)"
            >删除</el-button>
              >删除</el-button
            >
          </template>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination
@@ -558,92 +566,49 @@
</template>
<script>
import { geDetailTabletList } from "@/api/application-batch";
export default {
  name: "ApplicationBatchDetail",
  data() {
    return {
      // 批次号
      batchNo: "",
      // 批次状态
      status: "",
      batchInfo: {
        // 批次id
        id: "",
        // 批次号
        batchNumber: "",
        // 批次状态
        status: "",
        // 安置总户数
        waitFamilyArea: "",
        // 安置总人数
        personNum: "",
        // 补偿资金总额
        totalAmount: "",
      },
      // 加载状态
      loading: false,
      // 总条数
      total: 0,
      // 表格数据
      tableData: [
        {
          projectName: "李家窑水库工程征地拆迁",
          village: "松花社区",
          time: "",
          owner: "陈向荣",
          idCard: "220102198512345678",
          contact: "",
          resettlementPeople: 1,
          additionalPeople: 2,
          totalPeople: 3,
          houseName: "陈向荣、李辉",
          area: "160",
        },
        {
          projectName: "李家窑水库工程征地拆迁",
          village: "松花社区",
          time: "",
          owner: "席娟",
          idCard: "330105197803120987",
          contact: "",
          resettlementPeople: 1,
          additionalPeople: 1,
          totalPeople: 2,
          houseName: "周吉彬",
          area: "215",
        },
        {
          projectName:
            "成都绿道二环线生态区公园工程(含川师)征地拆迁及前期公示",
          village: "清泉村",
          time: "",
          owner: "周忠心",
          idCard: "440203199000999876",
          contact: "",
          resettlementPeople: 1,
          additionalPeople: 1,
          totalPeople: 2,
          houseName: "周忠心、杨春云",
          area: "103",
        },
        {
          projectName:
            "成都绿道二环线生态区公园工程(含川师)征地拆迁及前期公示",
          village: "清泉村",
          time: "",
          owner: "李辉",
          idCard: "440203199000999876",
          contact: "",
          resettlementPeople: 2,
          additionalPeople: 1,
          totalPeople: 3,
          houseName: "王强",
          area: "302",
        },
      ],
      tableData: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        town: undefined,
        street: undefined,
        projectName: undefined,
        village: undefined,
        owner: undefined,
        community: undefined,
        headOrIdCard: undefined,
      },
    };
  },
  created() {
    // 从路由获取批次号和状态
    const { batchNo, status } = this.$route.query;
    this.batchNo = batchNo || "";
    this.status = status || "待审核";
    const { id } = this.$route.query;
    this.batchInfo = {
      ...this.batchInfo,
      id: id || "",
    };
    this.getList();
  },
  methods: {
@@ -653,7 +618,16 @@
      // 这里添加实际的API调用获取数据
      setTimeout(() => {
        this.loading = false;
        this.total = this.tableData.length;
        geDetailTabletList({
          ...this.queryParams,
          applyId: this.batchInfo.id,
        }).then((res) => {
          this.tableData = res.data.records;
          this.total = res.data.total;
          this.batchInfo = {
            ...res.data.placementApply,
          };
        });
      }, 500);
    },
    /** 搜索按钮操作 */
@@ -666,11 +640,12 @@
      this.queryParams = {
        pageNum: 1,
        pageSize: 10,
        town: undefined,
        village: undefined,
        owner: undefined,
        street: undefined,
        projectName: undefined,
        community: undefined,
        headOrIdCard: undefined,
      };
      this.handleQuery();
      this.getList();
    },
    /** 返回按钮操作 */
    goBack() {
@@ -738,24 +713,29 @@
.app-container {
  padding: 20px;
}
.batch-info {
  margin-bottom: 20px;
}
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
}
.batch-title {
  font-size: 18px;
  font-weight: bold;
}
.info-cards {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}
.box-card {
  width: 32%;
  background-color: #6f82fb;
@@ -763,23 +743,28 @@
  text-align: center;
  border-radius: 5px;
}
.card-title {
  font-size: 22px;
  margin: 10px 0;
}
.card-desc {
  font-size: 14px;
  margin-bottom: 10px;
}
.search-form {
  margin-bottom: 20px;
  background-color: #fff;
  padding: 20px;
  border-radius: 4px;
}
.mb8 {
  margin-bottom: 15px;
}
.pagination-container {
  margin-top: 15px;
  text-align: right;
src/views/applicationBatchList/list.vue
@@ -5,19 +5,26 @@
      <el-form :inline="true" :model="queryParams" class="search-form">
        <el-form-item label="批次号">
          <el-input
            v-model="queryParams.batchNo"
            v-model="queryParams.batchNumber"
            placeholder="请输入"
            clearable
            size="small"
          />
        </el-form-item>
        <el-form-item label="状态">
          <el-input
          <el-select
            v-model="queryParams.status"
            placeholder="请输入"
            placeholder="请选择"
            clearable
            size="small"
          />
          >
            <el-option
              v-for="dict in statusOptions"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="default" @click="resetQuery">重置</el-button>
@@ -30,61 +37,100 @@
    <div class="action-buttons">
      <el-button type="primary" @click="handleAdd">新增申请批次</el-button>
      <el-button type="success" @click="handleImport">下载导入模板</el-button>
      <el-button type="primary" @click="handleBatchImport">批量导入</el-button>
    </div>
    <!-- 表格区域 -->
    <el-table
      v-loading="loading"
      :data="tableData"
      border
      style="width: 100%"
    >
    <el-table v-loading="loading" :data="tableData" border style="width: 100%">
      <el-table-column type="index" label="序号" width="60" align="center" />
      <el-table-column prop="batchNo" label="批次号" min-width="120" align="center" />
      <el-table-column prop="totalApplications" label="申请总数" min-width="100" align="center" />
      <el-table-column prop="totalApplicants" label="申请总人数" min-width="100" align="center" />
      <el-table-column prop="compensationAmount" label="补偿金总额(万元)" min-width="150" align="center" />
      <el-table-column prop="quarterlyAmount" label="25%暂付款(万元)" min-width="150" align="center" />
      <el-table-column prop="quarterlyPaymentStatus" label="每季度发放支付情况(万元)" min-width="180" align="center" />
      <el-table-column prop="transitionalAmount" label="过渡补助(万元)" min-width="150" align="center" />
      <el-table-column
        prop="batchNumber"
        label="批次号"
        min-width="120"
        align="center"
      />
      <el-table-column
        prop="householdsNum"
        label="申请总户数"
        min-width="100"
        align="center"
      />
      <el-table-column
        prop="personNum"
        label="申请总人数"
        min-width="100"
        align="center"
      />
      <el-table-column
        prop="totalAmount"
        label="补偿资金总额(万元)"
        min-width="150"
        align="center"
      />
      <el-table-column
        prop="downPaymentAmount"
        label="25%暂付款(万元)"
        min-width="150"
        align="center"
      />
      <el-table-column
        prop="quarterPayAmount"
        label="每季度发放支付情况(万元)"
        min-width="180"
        align="center"
      />
      <el-table-column
        prop="subsidyAmount"
        label="过渡补助(万元)"
        min-width="150"
        align="center"
      />
      <el-table-column label="状态" width="100" align="center">
        <template slot-scope="scope">
          <el-tag
            :type="scope.row.status === '待审核' ? 'warning' : scope.row.status === '已通过' ? 'success' : 'info'"
          >{{ scope.row.status }}</el-tag>
            :type="
              scope.row.status === 0
                ? 'warning'
                : scope.row.status === 1
                ? 'success'
                : 'info'
            "
            >{{ statusMap[scope.row.status] }}</el-tag
          >
        </template>
      </el-table-column>
      <el-table-column label="操作" width="180" align="center" fixed="right">
        <template slot-scope="scope">
          <!-- 待审核状态 -->
          <template v-if="scope.row.status === '待审核'">
          <!-- 已审核状态 -->
          <template>
            <el-button
              size="mini"
              type="text"
              v-if="scope.row.status === 0"
              @click="handleView(scope.row, 'audit')"
            >审核</el-button>
              >审核</el-button
            >
            <el-button
              size="mini"
              type="text"
              @click="handleView(scope.row, 'view')"
            >查看</el-button>
          </template>
          <!-- 已审核状态 -->
          <template v-else>
              >查看</el-button
            >
            <el-button
              size="mini"
              type="text"
              v-if="scope.row.status != 0"
              @click="handleView(scope.row, 'detail')"
            >详情</el-button>
              >详情</el-button
            >
            <el-button
              size="mini"
              type="text"
              @click="handleDelete(scope.row)"
            >删除</el-button>
              v-if="scope.row.status != 0"
              >删除</el-button
            >
          </template>
        </template>
      </el-table-column>
@@ -118,7 +164,6 @@
    <upload-dialog
      ref="uploadDialog"
      :visible.sync="uploadDialogVisible"
      :type="uploadType"
      @success="handleUploadSuccess"
    />
  </div>
@@ -128,6 +173,7 @@
import Pagination from "@/components/Pagination";
import UploadDialog from "./components/UploadDialog";
import ApprovalDialog from "./components/ApprovalDialog";
import { geTabletList } from "@/api/application-batch";
export default {
  name: "ApplicationBatchList",
@@ -144,144 +190,29 @@
      total: 4,
      // 状态数据字典
      statusOptions: [
        { value: "待审核", label: "待审核" },
        { value: "已通过", label: "已通过" },
        { value: "已驳回", label: "已驳回" },
        { value: 0, label: "待审核" },
        { value: 1, label: "已通过" },
        { value: 2, label: "已驳回" },
      ],
      // 状态映射
      statusMap: {
        0: "待审核",
        1: "已通过",
        2: "已驳回",
      },
      // 审核相关
      approvalDialogVisible: false,
      approvalType: "audit", // 'audit' 或 'detail'
      currentRow: {},
      // 上传相关
      uploadDialogVisible: false,
      uploadType: "add", // 'add' 或 'batch'
      // 表格数据
      tableData: [
        {
          projectName: "白鹤镇和平街道改造",
          projectCompleteTime: "2024-07-27",
          town: "白鹤镇",
          village: "白鹤村",
          group: "3组",
          owner: "陈向荣",
          ownerIdCard: "123456789012345678",
          relationship: "户主",
          personType: "集体",
          idCard: "123456789012345678",
          name: "陈向荣",
          age: "25岁",
          remark1: "事实",
          birthDate: "2024-01-05",
          resettlementType: "货币补偿",
          firstDeliveryDate: "2024-07-16",
          secondDeliveryDate: "2025-07-23",
          thirdDeliveryDate: "2025-11-21",
          thirdDeliveryRemark: "未完善",
          resettlementArea: "6",
          previousTotalAmount: "4",
          previousPaid: "19612348970",
          previousUnpaid: "",
          accountNumber: "19612348970",
          contact: "19612348970",
          remark: "",
          status: "待审核",
        },
        {
          projectName: "白鹤镇和平街道改造",
          projectCompleteTime: "2024-08-10",
          town: "白鹤镇",
          village: "白鹤村",
          group: "3组",
          owner: "席娟",
          ownerIdCard: "123456789012345678",
          relationship: "妻",
          personType: "集体",
          idCard: "330105197803120987",
          name: "李女士",
          age: "25岁",
          remark1: "事实",
          birthDate: "2024-01-22",
          resettlementType: "货币补偿",
          firstDeliveryDate: "2025-09-22",
          secondDeliveryDate: "2025-07-19",
          thirdDeliveryDate: "2025-04-22",
          thirdDeliveryRemark: "未完善",
          resettlementArea: "90",
          previousTotalAmount: "45",
          previousPaid: "19323312231",
          previousUnpaid: "",
          accountNumber: "19323312231",
          contact: "19323312231",
          remark: "",
          status: "待审核",
        },
        {
          projectName: "白鹤镇和平街道改造",
          projectCompleteTime: "2024-06-20",
          town: "白鹤镇",
          village: "白鹤村",
          group: "3组",
          owner: "梁小小",
          ownerIdCard: "123456789012345678",
          relationship: "子",
          personType: "北城集",
          idCard: "123456789012345678",
          name: "梁家辉",
          age: "25岁",
          remark1: "事实",
          birthDate: "2025-08-08",
          resettlementType: "货币补偿",
          firstDeliveryDate: "2024-07-04",
          secondDeliveryDate: "2024-12-20",
          thirdDeliveryDate: "2025-12-03",
          thirdDeliveryRemark: "未完善",
          resettlementArea: "65",
          previousTotalAmount: "90",
          previousPaid: "19876782134",
          previousUnpaid: "",
          accountNumber: "19876782134",
          contact: "19876782134",
          remark: "",
          status: "已驳回",
        },
        {
          projectName: "白鹤镇和平街道改造",
          projectCompleteTime: "2024-07-19",
          town: "白鹤镇",
          village: "白鹤村",
          group: "3组",
          owner: "王开莱",
          ownerIdCard: "123456789012345678",
          relationship: "兄",
          personType: "北城集",
          idCard: "123456789012345678",
          name: "王中山",
          age: "25岁",
          remark1: "事实",
          birthDate: "2024-06-09",
          resettlementType: "货币补偿",
          firstDeliveryDate: "2025-01-11",
          secondDeliveryDate: "2024-09-21",
          thirdDeliveryDate: "2024-12-12",
          thirdDeliveryRemark: "未完善",
          resettlementArea: "34",
          previousTotalAmount: "62",
          previousPaid: "19113212388",
          previousUnpaid: "",
          accountNumber: "19113212388",
          contact: "19113212388",
          remark: "",
          status: "已通过",
        },
      ],
      tableData: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        projectName: undefined,
        town: undefined,
        owner: undefined,
        idCard: undefined,
        status: undefined,
      },
    };
@@ -296,6 +227,10 @@
      // 这里添加实际的API调用
      setTimeout(() => {
        this.loading = false;
        geTabletList({ ...this.queryParams }).then((res) => {
          this.tableData = res.data.records;
          this.total = res.data.total;
        });
      }, 500);
    },
    /** 搜索按钮操作 */
@@ -309,36 +244,37 @@
        pageNum: 1,
        pageSize: 10,
        projectName: undefined,
        town: undefined,
        owner: undefined,
        idCard: undefined,
        status: undefined,
      };
      this.handleQuery();
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.uploadType = "add";
      this.uploadDialogVisible = true;
    },
    /** 导入模板下载操作 */
    handleImport() {
      // 实现下载逻辑
    },
    /** 批量导入按钮操作 */
    handleBatchImport() {
      this.uploadType = "batch";
      this.uploadDialogVisible = true;
    },
    /** 统一的查看/详情按钮操作 */
    handleView(row, type) {
      this.$router.push({
        path: "/applicationBatchList/detail",
        query: {
          batchNo: row.batchNo,
          type: type // 'audit'/'view'/'detail'
        },
      });
      this.currentRow = row;
      if (type === "audit" || type === "detail") {
        this.approvalType = type;
        this.approvalDialogVisible = true;
      } else if (type === "view") {
        this.$router.push({
          path: "/applicationBatchList/detail",
          query: {
            id: row.id,
            batchNumber: row.batchNumber,
            waitFamilyArea: row.waitFamilyArea || 0,
            personNum: row.personNum,
            totalAmount: row.totalAmount,
            status: row.status, //0待审核 1已通过 2已驳回
          },
        });
      }
    },
    /** 审核提交处理 */
    handleApprovalSubmit(data) {
@@ -374,7 +310,7 @@
      this.getList();
      this.$message({
        type: "success",
        message: this.uploadType === "add" ? "新增成功!" : "批量导入成功!",
        message:"新增成功!" ,
      });
    },
  },
@@ -395,7 +331,7 @@
    .search-form {
      display: flex;
      align-items: center;
      .el-form-item {
        margin-bottom: 0;
        margin-right: 20px;
@@ -405,7 +341,7 @@
  .action-buttons {
    margin-bottom: 20px;
    .el-button {
      margin-right: 10px;
    }
@@ -413,10 +349,10 @@
  .el-table {
    margin-bottom: 20px;
    .el-button--text {
      padding: 0 8px;
      &:not(:last-child) {
        border-right: 1px solid #dcdfe6;
      }
src/views/applicationBatchList/service.js
src/views/placement-batch/addResettle.vue
New file
@@ -0,0 +1,267 @@
<template>
    <div class="app-container">
        <el-card class="box-card">
            <el-form ref="form" :model="form" :rules="rules" label-width="215px" size="small">
                <!-- 基本信息 -->
                <div class="form-section">
                    <el-row :gutter="20">
                        <el-col :span="8">
                            <el-form-item label="拆迁项目名称" prop="projectName">
                                <el-input style="width: 200px;" v-model="form.projectName" placeholder="请输入"
                                    clearable />
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="所在村(社区)" prop="village">
                                <el-input style="width: 200px;"
                                 v-model="form.village" placeholder="请输入" clearable />
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="户主姓名" prop="householderName">
                                <el-input style="width: 200px;" v-model="form.householderName" placeholder="请输入"
                                    clearable />
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row :gutter="20">
                        <el-col :span="8">
                            <el-form-item label="户主身份号" prop="idCard">
                                <el-input style="width: 200px;" v-model="form.idCard" placeholder="请输入" clearable />
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="应安置人数" prop="familySize">
                                <el-input v-model="form.familySize" :min="1" :controls="false"
                                    controls-position="right" style="width: 200px;">
                                    <template slot="append">人</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="所有家庭成员应安置面积" prop="totalArea">
                                <el-input style="width: 200px;" v-model="form.totalArea" :controls="false"
                                    :min="0" :precision="2" controls-position="right">
                                    <template slot="append">㎡</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                </div>
                <!-- 补偿金额标准 -->
                <div class="form-section">
                    <div class="section-title">补偿金额标准</div>
                    <el-row :gutter="20">
                        <el-col :span="12">
                            <el-form-item label="新建商品住房/商业用房/停车位" prop="newBuildingStandard">
                                <el-input v-model="form.newBuildingStandard" :min="0" :controls="false"
                                    :precision="2" controls-position="right" style="width: 200px;">
                                    <template slot="append">万元</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="二手住房" prop="secondHandStandard">
                                <el-input v-model="form.secondHandStandard" :min="0" :controls="false"
                                    :precision="2" controls-position="right" style="width: 200px;">
                                    <template slot="append">万元</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                </div>
                <!-- 补偿金额 -->
                <div class="form-section">
                    <div class="section-title">补偿金额</div>
                    <el-row :gutter="20">
                        <el-col :span="8">
                            <el-form-item label="补偿总金额" prop="totalAmount">
                                <el-input v-model="form.totalAmount" :min="0" :controls="false" :precision="2"
                                    controls-position="right" style="width: 200px;">
                                    <template slot="append">万元</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="25%首付款" prop="downPayment">
                                <el-input v-model="form.downPayment" :min="0" :controls="false" :precision="2"
                                    controls-position="right" style="width: 200px;">
                                    <template slot="append">万元</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="每季度需要支付款项" prop="quarterlyPayment">
                                <el-input v-model="form.quarterlyPayment" :min="0" :controls="false"
                                    :precision="2" controls-position="right" style="width: 200px;">
                                    <template slot="append">万元</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row :gutter="20">
                        <el-col :span="8">
                            <el-form-item label="过渡补贴" prop="transitionalSubsidy">
                                <el-input v-model="form.transitionalSubsidy" :min="0" :controls="false"
                                    :precision="2" controls-position="right" style="width: 200px;">
                                    <template slot="append">万元</template>
                                </el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row>
                        <el-col :span="16">
                            <el-form-item label="备注" prop="remarks">
                                <el-input v-model="form.remarks" type="textarea" :rows="3" placeholder="请输入备注信息" />
                            </el-form-item>
                        </el-col>
                    </el-row>
                </div>
                <!-- 按钮区域 -->
                <div class="form-footer">
                    <el-button type="primary" size="small" @click="submitForm">提交</el-button>
                </div>
            </el-form>
        </el-card>
    </div>
</template>
<script>
export default {
    name: 'AddResettle',
    data() {
        return {
            // 表单数据
            form: {
                projectName: '',
                village: '',
                householderName: '',
                idCard: '',
                familySize: 1,
                totalArea: 0,
                newBuildingStandard: 0,
                secondHandStandard: 0,
                totalAmount: 0,
                downPayment: 0,
                quarterlyPayment: 0,
                transitionalSubsidy: 0,
                remarks: ''
            },
            // 表单校验规则
            rules: {
                projectName: [
                    { required: true, message: '请输入镇街项目名称', trigger: 'blur' }
                ],
                village: [
                    { required: true, message: '请输入所在村(社区)', trigger: 'blur' }
                ],
                householderName: [
                    { required: true, message: '请输入户主姓名', trigger: 'blur' }
                ],
                idCard: [
                    { required: true, message: '请输入户主身份号', trigger: 'blur' },
                    { pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '请输入正确的身份证号', trigger: 'blur' }
                ],
                newBuildingStandard: [
                    { required: true, message: '请输入新建商品住房/商业用房/停车位', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                secondHandStandard: [
                    { required: true, message: '请输入二手住房', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                transitionalSubsidy: [
                    { required: true, message: '请输入过渡补贴', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                downPayment: [
                    { required: true, message: '请输入25%首付款', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                quarterlyPayment: [
                    { required: true, message: '请输入每季度需要支付款项', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                transitionalSubsidy: [
                    { required: true, message: '请输入过渡补贴', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                familySize: [
                    { required: true, message: '请输入应安置人数', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                totalArea: [
                    { required: true, message: '请输入所有家庭成员应安置面积', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ],
                totalAmount: [
                    { required: true, message: '请输入补偿总金额', trigger: 'blur' },
                    { type: 'number', message: '请输入正确的数字', trigger: 'blur' }
                ]
            }
        }
    },
    methods: {
        // 提交表单
        submitForm() {
            this.$refs.form.validate(valid => {
                if (valid) {
                    // TODO: 调用接口提交数据
                    this.$message.success('提交成功')
                } else {
                    return false
                }
            })
        },
        // 重置表单
        resetForm() {
            this.$refs.form.resetFields()
        }
    }
}
</script>
<style lang="scss" scoped>
.app-container {
    padding: 20px;
    background-color: #f5f7fa;
    min-height: calc(100vh - 84px);
}
.box-card {
    margin-bottom: 20px;
    .form-section {
        margin-bottom: 30px;
        .section-title {
            font-size: 16px;
            font-weight: bold;
            color: #303133;
            margin-bottom: 20px;
            padding-left: 10px;
            border-left: 4px solid #409EFF;
        }
    }
    .form-footer {
        text-align: center;
        margin-top: 40px;
    }
}
:deep(.el-input-number) {
    width: 100%;
}
:deep(.el-textarea__inner) {
    font-family: Arial, sans-serif;
}
</style>
src/views/placement-batch/applayPerson.vue
New file
@@ -0,0 +1,601 @@
<template>
  <div class="app-container">
    <el-card class="box-card">
      <el-form ref="form" :model="form" :rules="rules" label-width="180px" size="small">
        <!-- 基本信息 -->
        <el-row :gutter="20">
          <el-col :span="6">
            <el-form-item label="镇(街道)" prop="town" required>
              <el-input v-model="form.town" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="所在村(社区)" prop="village" required>
              <el-input v-model="form.village" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="拆迁项目名称" prop="projectName" required>
              <el-input v-model="form.projectName" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="拆迁时间" prop="demolitionTime">
                <el-date-picker v-model="form.demolitionTime" type="date" placeholder="请选择拆迁时间" style="width: 250px;" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="6">
            <el-form-item label="户主姓名" prop="householderName" required>
              <el-input v-model="form.householderName" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="户主身份号" prop="idCard" required>
              <el-input v-model="form.idCard" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="联系电话" prop="phone" required>
              <el-input v-model="form.phone" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 本次安置人数 -->
        <div class="section-title">本次安置人数</div>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="集体经济组织成员" prop="collectiveMember" required>
              <div class="input-with-unit">
                <el-input v-model="form.collectiveMember" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">人</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="非集体经济组织成员" prop="nonCollectiveMember" required>
              <div class="input-with-unit">
                <el-input v-model="form.nonCollectiveMember" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">人</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="合计" prop="totalMember">
              <div class="input-with-unit">
                <el-input v-model="form.totalMember" placeholder="自动计算" disabled style="width: 250px;" >
                    <template slot="append">人</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="待安置家庭成员姓名" prop="familyMembers" required>
              <el-input v-model="form.familyMembers" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="待安置人员应安置面积合计" label-width="215px" prop="totalSettlementArea" required>
              <div class="input-with-unit">
                <el-input v-model="form.totalSettlementArea" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">㎡</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 补偿金额 -->
        <div class="section-title">补偿金额</div>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="新建商品住房/商业用房/停车位" label-width="215px" prop="newBuildingAmount" required>
              <div class="input-with-unit">
                <el-input v-model="form.newBuildingAmount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="二手住房"  label-width="215px" prop="secondHandAmount" required>
              <div class="input-with-unit">
                <el-input v-model="form.secondHandAmount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="合计"  label-width="215px" prop="totalAmount">
              <div class="input-with-unit">
                <el-input v-model="form.totalAmount" placeholder="自动计算" disabled style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="25%首付款"  label-width="215px" prop="downPayment" required>
              <div class="input-with-unit">
                <el-input v-model="form.downPayment" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="每季度需支付款项"  label-width="215px" prop="quarterlyPayment" required>
              <div class="input-with-unit">
                <el-input v-model="form.quarterlyPayment" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="过渡补贴"  label-width="215px" prop="transitionalSubsidy" required>
              <div class="input-with-unit">
                <el-input v-model="form.transitionalSubsidy" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备注"  label-width="215px" prop="remarks">
              <el-input
                type="textarea"
                v-model="form.remarks"
                placeholder="请输入备注信息"
                :rows="3"
                style="width: 100%;"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 领证发放时间 -->
        <el-row>
          <el-col :span="8">
            <el-form-item label="领证发放时间"  label-width="215px" prop="certificateTime" required>
              <el-date-picker
                v-model="form.certificateTime"
                type="date"
                placeholder="请选择领证发放时间"
                style="width: 250px;"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 购房信息 -->
        <div class="section-title">购房信息</div>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="购房时间" prop="purchaseTime" required>
              <el-date-picker
                v-model="form.purchaseTime"
                type="date"
                placeholder="请选择购房时间"
                style="width: 250px;"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="成交金额" prop="dealAmount" required>
              <div class="input-with-unit">
                <el-input v-model="form.dealAmount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="楼盘名称" prop="newBuildingName" required>
              <el-input v-model="form.newBuildingName" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="面积" prop="newBuildingArea" required>
              <div class="input-with-unit">
                <el-input v-model="form.newBuildingArea" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">㎡</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="套数" prop="newBuildingCount" required>
              <div class="input-with-unit">
                <el-input v-model="form.newBuildingCount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">套</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="小区名称" prop="secondHandName" required>
              <el-input v-model="form.secondHandName" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="面积" prop="secondHandArea" required>
              <div class="input-with-unit">
                <el-input v-model="form.secondHandArea" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">㎡</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="套数" prop="secondHandCount" required>
              <div class="input-with-unit">
                <el-input v-model="form.secondHandCount" placeholder="请输入" clearable style="width: 160px;" >
                    <template slot="append">套</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="新建商业用房" prop="newCommercialName" required>
              <el-input v-model="form.newCommercialName" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="金额" prop="newCommercialAmount" required>
              <div class="input-with-unit">
                <el-input v-model="form.newCommercialAmount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="面积" prop="newCommercialArea" required>
              <div class="input-with-unit">
                <el-input v-model="form.newCommercialArea" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">㎡</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="套数" prop="newCommercialCount" required>
              <div class="input-with-unit">
                <el-input v-model="form.newCommercialCount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">套</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="新建停车位" prop="newParkingName" required>
              <el-input v-model="form.newParkingName" placeholder="请输入" clearable style="width: 250px;" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="金额" prop="newParkingAmount" required>
              <div class="input-with-unit">
                <el-input v-model="form.newParkingAmount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">万元</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="个数" prop="newParkingCount" required>
              <div class="input-with-unit">
                <el-input v-model="form.newParkingCount" placeholder="请输入" clearable style="width: 250px;" >
                    <template slot="append">套</template>
                </el-input>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 补偿款支付 -->
        <div class="section-title">补偿款支付</div>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="自主购房协议签订时间" prop="agreementSignTime" required>
              <el-date-picker
                v-model="form.agreementSignTime"
                type="date"
                placeholder="请选择时间"
                style="width: 250px;"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="25%补偿款及过渡补贴支付时间" label-width="220px" prop="downPaymentTime" required>
              <el-date-picker
                v-model="form.downPaymentTime"
                type="date"
                placeholder="请选择时间"
                style="width: 250px;"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="剩余款项支付时间:" prop="remainingPaymentTime">
              <el-row :gutter="20">
                <el-col :span="4">
                  <div class="payment-label">第一年</div>
                  <el-date-picker
                    v-model="form.firstYearPayment"
                    type="date"
                    placeholder="请选择时间"
                    style="width: 200px;"
                  />
                </el-col>
                <el-col :span="4">
                  <div class="payment-label">第二年</div>
                  <el-date-picker
                    v-model="form.secondYearPayment"
                    type="date"
                    placeholder="请选择时间"
                    style="width: 200px;"
                  />
                </el-col>
                <el-col :span="4">
                  <div class="payment-label">第三年</div>
                  <el-date-picker
                    v-model="form.thirdYearPayment"
                    type="date"
                    placeholder="请选择时间"
                    style="width: 200px;"
                  />
                </el-col>
                <el-col :span="4">
                  <div class="payment-label">第四年</div>
                  <el-date-picker
                    v-model="form.fourthYearPayment"
                    type="date"
                    placeholder="请选择时间"
                    style="width: 200px;"
                  />
                </el-col>
                <el-col :span="4">
                  <div class="payment-label">第五年</div>
                  <el-date-picker
                    v-model="form.fifthYearPayment"
                    type="date"
                    placeholder="请选择时间"
                    style="width: 200px;"
                  />
                </el-col>
              </el-row>
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 按钮区域 -->
        <div class="form-footer">
          <el-button type="primary" @click="submitForm">提交</el-button>
        </div>
      </el-form>
    </el-card>
  </div>
</template>
<script>
export default {
  name: 'ApplayPerson',
  data() {
    return {
      form: {
        town: '',
        village: '',
        projectName: '',
        demolitionTime: '',
        householderName: '',
        idCard: '',
        phone: '',
        collectiveMember: '',
        nonCollectiveMember: '',
        totalMember: '',
        familyMembers: '',
        totalSettlementArea: '',
        newBuildingAmount: '',
        secondHandAmount: '',
        totalAmount: '',
        downPayment: '',
        quarterlyPayment: '',
        transitionalSubsidy: '',
        remarks: '',
        certificateTime: '',
        purchaseTime: '',
        dealAmount: '',
        newBuildingName: '',
        newBuildingArea: '',
        newBuildingCount: '',
        secondHandName: '',
        secondHandArea: '',
        secondHandCount: '',
        newCommercialName: '',
        newCommercialAmount: '',
        newCommercialArea: '',
        newCommercialCount: '',
        newParkingName: '',
        newParkingAmount: '',
        newParkingCount: '',
        agreementSignTime: '',
        downPaymentTime: '',
        firstYearPayment: '',
        secondYearPayment: '',
        thirdYearPayment: '',
        fourthYearPayment: '',
        fifthYearPayment: '',
      },
      rules: {
        town: [{ required: true, message: '请输入镇(街道)', trigger: 'blur' }],
        village: [{ required: true, message: '请输入所在村(社区)', trigger: 'blur' }],
        projectName: [{ required: true, message: '请输入拆迁项目名称', trigger: 'blur' }],
        householderName: [{ required: true, message: '请输入户主姓名', trigger: 'blur' }],
        idCard: [
          { required: true, message: '请输入户主身份号', trigger: 'blur' },
          { pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '请输入正确的身份证号', trigger: 'blur' }
        ],
        phone: [
          { required: true, message: '请输入联系电话', trigger: 'blur' },
          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
        ],
        collectiveMember: [{ required: true, message: '请输入集体经济组织成员人数', trigger: 'blur' }],
        nonCollectiveMember: [{ required: true, message: '请输入非集体经济组织成员人数', trigger: 'blur' }],
        familyMembers: [{ required: true, message: '请输入待安置家庭成员姓名', trigger: 'blur' }],
        totalSettlementArea: [{ required: true, message: '请输入待安置人员应安置面积合计', trigger: 'blur' }],
        newBuildingAmount: [{ required: true, message: '请输入新建商品住房/商业用房/停车位金额', trigger: 'blur' }],
        secondHandAmount: [{ required: true, message: '请输入二手住房金额', trigger: 'blur' }],
        downPayment: [{ required: true, message: '请输入25%首付款', trigger: 'blur' }],
        quarterlyPayment: [{ required: true, message: '请输入每季度需支付款项', trigger: 'blur' }],
        transitionalSubsidy: [{ required: true, message: '请输入过渡补贴', trigger: 'blur' }],
        certificateTime: [{ required: true, message: '请选择领证发放时间', trigger: 'change' }],
        purchaseTime: [{ required: true, message: '请选择购房时间', trigger: 'change' }],
        dealAmount: [{ required: true, message: '请输入成交金额', trigger: 'blur' }],
        newBuildingName: [{ required: true, message: '请输入楼盘名称', trigger: 'blur' }],
        newBuildingArea: [{ required: true, message: '请输入面积', trigger: 'blur' }],
        newBuildingCount: [{ required: true, message: '请输入套数', trigger: 'blur' }],
        secondHandName: [{ required: true, message: '请输入小区名称', trigger: 'blur' }],
        secondHandArea: [{ required: true, message: '请输入面积', trigger: 'blur' }],
        secondHandCount: [{ required: true, message: '请输入套数', trigger: 'blur' }],
        newCommercialName: [{ required: true, message: '请输入新建商业用房名称', trigger: 'blur' }],
        newCommercialAmount: [{ required: true, message: '请输入金额', trigger: 'blur' }],
        newCommercialArea: [{ required: true, message: '请输入面积', trigger: 'blur' }],
        newCommercialCount: [{ required: true, message: '请输入套数', trigger: 'blur' }],
        newParkingName: [{ required: true, message: '请输入新建停车位名称', trigger: 'blur' }],
        newParkingAmount: [{ required: true, message: '请输入金额', trigger: 'blur' }],
        newParkingCount: [{ required: true, message: '请输入个数', trigger: 'blur' }],
        agreementSignTime: [{ required: true, message: '请选择自主购房协议签订时间', trigger: 'change' }],
        downPaymentTime: [{ required: true, message: '请选择25%补偿款及过渡补贴支付时间', trigger: 'change' }],
      }
    }
  },
  watch: {
    // 监听集体和非集体成员人数,自动计算总人数
    'form.collectiveMember': {
      handler(val) {
        this.calculateTotalMember()
      }
    },
    'form.nonCollectiveMember': {
      handler(val) {
        this.calculateTotalMember()
      }
    },
    // 监听新建和二手房金额,自动计算总金额
    'form.newBuildingAmount': {
      handler(val) {
        this.calculateTotalAmount()
      }
    },
    'form.secondHandAmount': {
      handler(val) {
        this.calculateTotalAmount()
      }
    }
  },
  methods: {
    // 计算总人数
    calculateTotalMember() {
      const collective = parseFloat(this.form.collectiveMember) || 0
      const nonCollective = parseFloat(this.form.nonCollectiveMember) || 0
      this.form.totalMember = collective + nonCollective
    },
    // 计算总金额
    calculateTotalAmount() {
      const newBuilding = parseFloat(this.form.newBuildingAmount) || 0
      const secondHand = parseFloat(this.form.secondHandAmount) || 0
      this.form.totalAmount = newBuilding + secondHand
    },
    // 提交表单
    submitForm() {
      this.$refs.form.validate(valid => {
        if (valid) {
          // TODO: 调用接口提交数据
          this.$message.success('提交成功')
        }
      })
    },
    // 重置表单
    resetForm() {
      this.$refs.form.resetFields()
    }
  }
}
</script>
<style lang="scss" scoped>
.app-container {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: calc(100vh - 84px);
}
.box-card {
  margin-bottom: 20px;
}
.section-title {
  font-size: 16px;
  font-weight: bold;
  color: #303133;
  margin: 20px 0;
  padding-left: 10px;
  border-left: 4px solid #409EFF;
}
.input-with-unit {
  display: inline-flex;
  align-items: center;
  .unit {
    margin-left: 8px;
    color: #606266;
  }
}
.form-footer {
  text-align: center;
  margin-top: 40px;
}
:deep(.el-textarea__inner) {
  font-family: Arial, sans-serif;
}
.payment-label {
  font-size: 14px;
  color: #606266;
  margin-bottom: 8px;
}
</style>
src/views/placement-batch/components/ApprovalDialog.vue
New file
@@ -0,0 +1,619 @@
<template>
  <el-dialog :title="type === 'audit' ? '审批安置户申请信息' : '安置户申请信息'" :visible.sync="dialogVisible" width="80%"
    :close-on-click-modal="false" :append-to-body="true">
    <div class="approval-content">
      <!-- 左侧表格区域 -->
      <div class="table-container">
        <el-table :data="tableData" border style="width: 100%" :row-class-name="tableRowClassName">
          <el-table-column type="index" label="序号" width="50" align="center" />
          <el-table-column prop="town" label="镇(街道)" align="center" width="80">
            <template slot-scope="scope">
              {{ scope.row.town }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.town" placement="top">
                <div slot="content">{{ scope.row.errors.town }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="projectName" label="拆迁项目名称" align="center" width="150">
            <template slot-scope="scope">
              {{ scope.row.projectName }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.projectName" placement="top">
                <div slot="content">{{ scope.row.errors.projectName }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="village" label="所在村(社区)" align="center" width="100">
            <template slot-scope="scope">
              {{ scope.row.village }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.village" placement="top">
                <div slot="content">{{ scope.row.errors.village }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="time" label="拆迁时间" align="center" width="100">
            <template slot-scope="scope">
              {{ scope.row.time }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.time" placement="top">
                <div slot="content">{{ scope.row.errors.time }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="owner" label="产主姓名" align="center" width="80">
            <template slot-scope="scope">
              {{ scope.row.owner }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.owner" placement="top">
                <div slot="content">{{ scope.row.errors.owner }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="idCard" label="身份证号" align="center" width="180">
            <template slot-scope="scope">
              {{ scope.row.idCard }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.idCard" placement="top">
                <div slot="content">{{ scope.row.errors.idCard }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="contact" label="联系电话" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.contact }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.contact" placement="top">
                <div slot="content">{{ scope.row.errors.contact }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column label="家庭安置人数(人)" align="center">
            <el-table-column prop="resettlementPeople" label="集体经济组织成员" align="center" width="120">
              <template slot-scope="scope">
                {{ scope.row.resettlementPeople }}
                <el-tooltip v-if="scope.row.errors && scope.row.errors.resettlementPeople" placement="top">
                  <div slot="content">
                    {{ scope.row.errors.resettlementPeople }}
                  </div>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column prop="additionalPeople" label="非集体经济组织成员" align="center" width="120">
              <template slot-scope="scope">
                {{ scope.row.additionalPeople }}
                <el-tooltip v-if="scope.row.errors && scope.row.errors.additionalPeople" placement="top">
                  <div slot="content">
                    {{ scope.row.errors.additionalPeople }}
                  </div>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column prop="totalPeople" label="合计" align="center" width="60">
              <template slot-scope="scope">
                {{ scope.row.totalPeople }}
                <el-tooltip v-if="scope.row.errors && scope.row.errors.totalPeople" placement="top">
                  <div slot="content">{{ scope.row.errors.totalPeople }}</div>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
          </el-table-column>
          <el-table-column prop="houseName" label="待安置家庭成员姓名" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.houseName }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.houseName" placement="top">
                <div slot="content">{{ scope.row.errors.houseName }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="area" label="待安置人员应安置面积合计(㎡)" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.area }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.area" placement="top">
                <div slot="content">{{ scope.row.errors.area }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column label="补偿金额(万元)" align="center">
            <el-table-column prop="firstPayment" label="新建商品住房、商业用房、停车位" align="center" width="100">
              <template slot-scope="scope">
                {{ scope.row.firstPayment }}
                <el-tooltip v-if="scope.row.errors && scope.row.errors.firstPayment" placement="top">
                  <div slot="content">{{ scope.row.errors.firstPayment }}</div>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column prop="secondPayment" label="二手住房" align="center" width="80">
              <template slot-scope="scope">
                {{ scope.row.secondPayment }}
                <el-tooltip v-if="scope.row.errors && scope.row.errors.secondPayment" placement="top">
                  <div slot="content">{{ scope.row.errors.secondPayment }}</div>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
            <el-table-column prop="totalPayment" label="合计" align="center" width="60">
              <template slot-scope="scope">
                {{ scope.row.totalPayment }}
                <el-tooltip v-if="scope.row.errors && scope.row.errors.totalPayment" placement="top">
                  <div slot="content">{{ scope.row.errors.totalPayment }}</div>
                  <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
                </el-tooltip>
              </template>
            </el-table-column>
          </el-table-column>
          <el-table-column prop="monthlyPayment" label="25%首付款(万元)" align="center" width="130">
            <template slot-scope="scope">
              {{ scope.row.monthlyPayment }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.monthlyPayment" placement="top">
                <div slot="content">{{ scope.row.errors.monthlyPayment }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="remainingPayment" label="每季度需支付款项(万元)" align="center" width="120">
            <template slot-scope="scope">
              {{ scope.row.remainingPayment }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.remainingPayment" placement="top">
                <div slot="content">
                  {{ scope.row.errors.remainingPayment }}
                </div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="totalPaid" label="过渡补贴(万元)" align="center" width="60">
            <template slot-scope="scope">
              {{ scope.row.totalPaid }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.totalPaid" placement="top">
                <div slot="content">{{ scope.row.errors.totalPaid }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="remark" label="备注" align="center" width="60">
            <template slot-scope="scope">
              {{ scope.row.remark }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.remark" placement="top">
                <div slot="content">{{ scope.row.errors.remark }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
          <el-table-column prop="difference" label="购房差异情况" align="center" width="60">
            <template slot-scope="scope">
              {{ scope.row.difference }}
              <el-tooltip v-if="scope.row.errors && scope.row.errors.difference" placement="top">
                <div slot="content">{{ scope.row.errors.difference }}</div>
                <i class="el-icon-warning" style="color: #e6a23c; margin-left: 5px"></i>
              </el-tooltip>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- 右侧审核信息 -->
      <div class="approval-info">
        <div class="approver-timeline">
          <!-- 审核状态下显示审批人和等待审核按钮 -->
          <template v-if="type === 'audit'">
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar size="small" icon="el-icon-user" :style="{ background: '#6d78ff' }"></el-avatar>
              </div>
              <div class="timeline-content info-box">
                <div class="info-line">
                  <div class="approver-info">
                    <div class="approver-title">审批人:</div>
                    <div class="approver-name">{{ approver }}</div>
                  </div>
                  <div class="approval-time-info">
                    <div class="approval-time-title">审批时间:</div>
                    <div class="approval-time">{{ approvalTime }}</div>
                  </div>
                </div>
              </div>
            </div>
            <div class="timeline-divider"></div>
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar size="small" icon="el-icon-time" :style="{ background: '#909399' }"></el-avatar>
              </div>
              <div class="timeline-content">
                <el-button size="small" disabled class="waiting-btn">等待审核</el-button>
              </div>
            </div>
          </template>
          <!-- 详情状态下显示经办人和审核人 -->
          <template v-else>
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar size="small" icon="el-icon-user" :style="{ background: '#6d78ff' }"></el-avatar>
              </div>
              <div class="timeline-content info-box">
                <div class="info-line">
                  <div class="approver-info">
                    <div class="approver-title">经办人:</div>
                    <div class="approver-name">{{ operatorName }}</div>
                  </div>
                  <div class="approval-time-info">
                    <div class="approval-time-title">提交时间:</div>
                    <div class="approval-time">{{ submitTime }}</div>
                  </div>
                </div>
              </div>
            </div>
            <div class="timeline-divider"></div>
            <div class="timeline-item">
              <div class="timeline-icon">
                <el-avatar size="small" icon="el-icon-user" :style="{ background: '#6d78ff' }"></el-avatar>
              </div>
              <div class="timeline-content info-box">
                <div class="info-line">
                  <div class="approver-info">
                    <div class="approver-title">审核人:</div>
                    <div class="approver-name">{{ auditorName }}</div>
                  </div>
                  <div class="approval-time-info">
                    <div class="approval-time-title">审核时间:</div>
                    <div class="approval-time">{{ auditTime }}</div>
                  </div>
                </div>
              </div>
            </div>
          </template>
        </div>
      </div>
    </div>
    <!-- 警告信息 -->
    <div class="warning-info" v-if="hasWarning && type === 'audit'">
      <div class="warning-text">
        注意: 系统检测到该申请表中存在异常数据,请仔细核实!
      </div>
    </div>
    <!-- 审核结果区域 -->
    <div class="audit-section">
      <div class="audit-result" v-if="type === 'audit'">
        <div class="result-title">审核结果</div>
        <div class="result-options">
          <el-radio-group v-model="form.auditResult">
            <el-radio label="pass">通过</el-radio>
            <el-radio label="reject">驳回</el-radio>
          </el-radio-group>
        </div>
      </div>
      <div class="audit-comment">
        <div class="comment-title">审批意见</div>
        <el-input type="textarea" :rows="4" placeholder="请输入审批意见" v-model="form.auditComment"
          :disabled="type === 'detail'"></el-input>
      </div>
    </div>
    <!-- 底部按钮 - 仅审核模式显示 -->
    <div slot="footer" class="dialog-footer" v-if="type === 'audit'">
      <el-button @click="cancelAudit">取消</el-button>
      <el-button type="primary" @click="submitAudit">确认</el-button>
    </div>
  </el-dialog>
</template>
<script>
export default {
  name: "ApprovalDialog",
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    type: {
      type: String,
      default: "audit", // 'audit' 或 'detail'
      validator: function (value) {
        return ["audit", "detail"].indexOf(value) !== -1;
      },
    },
    rowData: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      dialogVisible: false,
      hasWarning: true,
      approver: "李四",
      approvalTime: "2025-1-17 09:35:24",
      operatorName: "张三",
      submitTime: "2025-1-17 09:35:24",
      auditorName: "王五",
      auditTime: "2025-1-17 09:35:24",
      approvalStatus: "", // 'passed', 'rejected', ''
      form: {
        auditResult: "pass",
        auditComment: "",
      },
      tableData: [
        {
          town: "松花社区",
          projectName: "李家窑水库工程征地拆迁",
          village: "松花社区",
          time: "",
          owner: "陈向荣",
          idCard: "220102198512345678",
          contact: "",
          resettlementPeople: 1,
          additionalPeople: 2,
          totalPeople: 3,
          houseName: "陈向荣、李辉",
          ownerName: "",
          area: "160",
          totalCompensation: "54",
          firstPayment: "10",
          secondPayment: "46",
          totalPayment: "30",
          monthlyPayment: "38",
          remainingPayment: "69",
          totalPaid: "",
          hasError: false,
        },
        {
          town: "松花社区",
          projectName: "李家窑水库工程征地拆迁",
          village: "松花社区",
          time: "",
          owner: "席娟",
          idCard: "330105197803120987",
          contact: "",
          resettlementPeople: 1,
          additionalPeople: 1,
          totalPeople: 2,
          houseName: "周吉彬",
          ownerName: "",
          area: "215",
          totalCompensation: "43",
          firstPayment: "14",
          secondPayment: "2",
          totalPayment: "81",
          monthlyPayment: "41",
          remainingPayment: "17",
          totalPaid: "",
          hasError: true,
          errors: {
            idCard: "身份证号不合法",
            totalPayment: "金额计算异常",
          },
        },
        {
          town: "清泉村",
          projectName:
            "成都绿道二环线生态区公园工程(含川师)征地拆迁及前期公示",
          village: "清泉村",
          time: "",
          owner: "周忠心",
          idCard: "440203199000999876",
          contact: "",
          resettlementPeople: 1,
          additionalPeople: 1,
          totalPeople: 2,
          houseName: "周忠心、杨春云",
          ownerName: "",
          area: "103",
          totalCompensation: "88",
          firstPayment: "42",
          secondPayment: "14",
          totalPayment: "61",
          monthlyPayment: "35",
          remainingPayment: "26",
          totalPaid: "",
          hasError: false,
        },
        {
          town: "清泉村",
          projectName:
            "成都绿道二环线生态区公园工程(含川师)征地拆迁及前期公示",
          village: "清泉村",
          time: "",
          owner: "李辉",
          idCard: "440203199000999876",
          contact: "",
          resettlementPeople: 2,
          additionalPeople: 1,
          totalPeople: 3,
          houseName: "王强",
          ownerName: "",
          area: "302",
          totalCompensation: "49",
          firstPayment: "28",
          secondPayment: "10",
          totalPayment: "56",
          monthlyPayment: "29",
          remainingPayment: "4",
          totalPaid: "",
          hasError: false,
        },
      ],
    };
  },
  watch: {
    visible(val) {
      this.dialogVisible = val;
    },
    dialogVisible(val) {
      this.$emit("update:visible", val);
    },
    rowData: {
      handler(newVal) {
        if (newVal && Object.keys(newVal).length > 0) {
          // 如果有传入数据,可以在这里处理
        }
      },
      immediate: true,
    },
  },
  methods: {
    tableRowClassName({ row, rowIndex }) {
      if (row.hasError) {
        return "error-row";
      }
      return "";
    },
    cancelAudit() {
      this.dialogVisible = false;
      this.resetForm();
    },
    submitAudit() {
      // 提交审核
      this.$emit("audit-submit", {
        result: this.form.auditResult,
        comment: this.form.auditComment,
      });
      this.dialogVisible = false;
      this.resetForm();
    },
    resetForm() {
      this.form = {
        auditResult: "pass",
        auditComment: "",
      };
    },
  },
};
</script>
<style scoped>
.approval-content {
  display: flex;
  margin-bottom: 20px;
}
.table-container {
  flex: 1;
  margin-right: 20px;
  overflow-x: auto;
}
.approval-info {
  width: 250px;
  padding: 15px;
  border-radius: 4px;
  background-color: #f0f2f5;
}
.approver-timeline {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.timeline-item {
  display: flex;
  align-items: flex-start;
  margin-bottom: 15px;
}
.timeline-icon {
  margin-right: 10px;
}
.timeline-divider {
  width: 2px;
  height: 30px;
  background-color: #dcdfe6;
  margin-left: 15px;
  margin-bottom: 15px;
}
.timeline-content {
  flex: 1;
}
.info-box {
  background-color: #8e9aff;
  border-radius: 8px;
  padding: 6px 8px;
  color: white;
}
.info-line {
  display: flex;
  width: 100%;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
}
.approver-info,
.approval-time-info {
  display: flex;
  align-items: center;
  white-space: nowrap;
}
.approver-title,
.approval-time-title {
  font-weight: bold;
  margin-right: 2px;
  white-space: nowrap;
  font-size: 12px;
}
.approver-name,
.approval-time {
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.waiting-btn {
  background-color: #909399;
  color: white;
  border: none;
}
.warning-info {
  background-color: #fef0f0;
  padding: 10px 15px;
  border-radius: 4px;
  margin: 15px 0;
}
.warning-text {
  color: #f56c6c;
}
.audit-section {
  margin-top: 20px;
}
.audit-result {
  margin-bottom: 15px;
}
.result-title,
.comment-title {
  font-weight: bold;
  margin-bottom: 10px;
}
.dialog-footer {
  text-align: right;
}
</style>
<style>
/* 全局样式 */
.error-row {
  background-color: #ffecec !important;
}
</style>
src/views/placement-batch/components/exportMoneyApplay.vue
New file
@@ -0,0 +1,239 @@
<template>
  <el-dialog title="导入人员购房资金申请" :visible.sync="visible" width="600px" :close-on-click-modal="false" append-to-body>
    <el-form ref="form" :model="form" :rules="rules" label-width="120px">
      <el-form-item label="批次号" prop="batchNo">
        <el-input v-model="form.batchNo" placeholder="请输入" clearable></el-input>
      </el-form-item>
      <div>
      <el-form-item label="导入资金表" prop="moneyFile">
        <el-upload class="upload-container" :action="uploadUrl" :before-upload="beforeUpload"
          :on-success="handleMoneyFileSuccess" :on-error="handleUploadError" :file-list="moneyFileList" :limit="1">
          <div class="upload-area" @click="handleClickUpload">
            <i class="el-icon-folder"></i>
            <div class="upload-text">点击或将文件文件拖拽到这里上传</div>
            <div class="upload-tip">支持格式:.xlsx、.xls...</div>
          </div>
          <div slot="tip" class="el-upload__tip">
            已上传:
            <template v-if="moneyFileList.length">
              <div v-for="(file, index) in moneyFileList" :key="index" class="file-item">
                <i class="el-icon-document"></i>
                <span class="file-name">{{ file.name }}</span>
                <i class="el-icon-close" @click.stop="handleRemoveFile(file, 'money')"></i>
              </div>
            </template>
          </div>
        </el-upload>
      </el-form-item>
      <el-form-item label="导入购房表" prop="houseFile">
        <el-upload class="upload-container" :action="uploadUrl" :before-upload="beforeUpload"
          :on-success="handleHouseFileSuccess" :on-error="handleUploadError" :file-list="houseFileList" :limit="1">
          <div class="upload-area" @click="handleClickUpload">
            <i class="el-icon-folder"></i>
            <div class="upload-text">点击或将文件文件拖拽到这里上传</div>
            <div class="upload-tip">支持格式:.xlsx、.xls...</div>
          </div>
          <div slot="tip" class="el-upload__tip">
            已上传:
            <template v-if="houseFileList.length">
              <div v-for="(file, index) in houseFileList" :key="index" class="file-item">
                <i class="el-icon-document"></i>
                <span class="file-name">{{ file.name }}</span>
                <i class="el-icon-close" @click.stop="handleRemoveFile(file, 'house')"></i>
              </div>
            </template>
          </div>
        </el-upload>
      </el-form-item>
      </div>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="handleCancel">取 消</el-button>
      <el-button type="primary" @click="handleSubmit" :loading="loading">确 认</el-button>
    </div>
  </el-dialog>
</template>
<script>
export default {
  name: 'ExportMoneyApplay',
  props: {
    visible: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      loading: false,
      uploadUrl: '/api/upload', // 上传地址
      form: {
        batchNo: '',
        moneyFile: '',
        houseFile: ''
      },
      rules: {
        batchNo: [
          { required: true, message: '请输入批次号', trigger: 'blur' }
        ],
        moneyFile: [
          { required: true, message: '请上传资金表', trigger: 'change' }
        ],
        houseFile: [
          { required: true, message: '请上传购房表', trigger: 'change' }
        ]
      },
      moneyFileList: [],
      houseFileList: []
    }
  },
  methods: {
    // 上传前校验
    beforeUpload(file) {
      const isExcel = file.type === 'application/vnd.ms-excel' ||
        file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      const isLt10M = file.size / 1024 / 1024 < 10
      if (!isExcel) {
        this.$message.error('上传文件只能是 Excel 格式!')
        return false
      }
      if (!isLt10M) {
        this.$message.error('上传文件大小不能超过 10MB!')
        return false
      }
      return true
    },
    // 资金表上传成功
    handleMoneyFileSuccess(response, file, fileList) {
      this.moneyFileList = fileList
      this.form.moneyFile = response.data
      this.$message.success('上传成功')
    },
    // 购房表上传成功
    handleHouseFileSuccess(response, file, fileList) {
      this.houseFileList = fileList
      this.form.houseFile = response.data
      this.$message.success('上传成功')
    },
    // 上传失败
    handleUploadError() {
      this.$message.error('上传失败')
    },
    // 移除文件
    handleRemoveFile(file, type) {
      if (type === 'money') {
        this.moneyFileList = []
        this.form.moneyFile = ''
      } else {
        this.houseFileList = []
        this.form.houseFile = ''
      }
    },
    // 点击上传区域
    handleClickUpload() {
      // 触发上传
    },
    // 取消
    handleCancel() {
      this.$emit('update:visible', false)
      this.resetForm()
    },
    // 提交
    handleSubmit() {
      this.$refs.form.validate(valid => {
        if (valid) {
          this.loading = true
          // TODO: 调用接口提交数据
          setTimeout(() => {
            this.loading = false
            this.$message.success('提交成功')
            this.$emit('update:visible', false)
            this.resetForm()
          }, 1000)
        }
      })
    },
    // 重置表单
    resetForm() {
      this.form = {
        batchNo: '',
        moneyFile: '',
        houseFile: ''
      }
      this.moneyFileList = []
      this.houseFileList = []
      this.$refs.form && this.$refs.form.resetFields()
    }
  }
}
</script>
<style lang="scss" scoped>
.upload-container {
  .upload-area {
    width: 100%;
    height: 120px;
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    color: #666;
    &:hover {
      border-color: #409EFF;
    }
    .el-icon-folder {
      font-size: 28px;
      color: #8c939d;
      margin-bottom: 10px;
    }
    .upload-text {
      font-size: 14px;
      margin-bottom: 5px;
    }
    .upload-tip {
      font-size: 12px;
      color: #999;
    }
  }
  .file-item {
    display: flex;
    align-items: center;
    margin-top: 8px;
    .el-icon-document {
      margin-right: 5px;
      color: #909399;
    }
    .file-name {
      flex: 1;
      color: #606266;
    }
    .el-icon-close {
      cursor: pointer;
      color: #909399;
      &:hover {
        color: #f56c6c;
      }
    }
  }
}
.dialog-footer {
  text-align: center;
}
</style>
src/views/placement-batch/index.vue
@@ -1,20 +1,237 @@
<template>
    <div>111</div>
  <div class="app-container">
    <!-- 搜索区域 -->
    <div class="filter-container">
      <el-form :inline="true" :model="queryParams" class="demo-form-inline">
        <el-form-item label="批次号">
          <el-input v-model="queryParams.batchNo" size="small" placeholder="请输入" clearable></el-input>
        </el-form-item>
        <el-form-item label="状态">
          <el-input v-model="queryParams.status" size="small" placeholder="请输入" clearable></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="small" @click="handleQuery">查询</el-button>
          <el-button type="primary" size="small" @click="handleAdd">添加</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 功能按钮区域 -->
    <div class="button-container">
      <el-button type="primary" size="small" @click="handleImportAll" >新增资金批次</el-button>
      <el-button type="success" size="small" @click="handleExportTemplate">下载资金导入模版</el-button>
      <el-button type="success" size="small" @click="handleImportTemplate">下载购房信息表导入模版</el-button>
    </div>
    <!-- 表格区域 -->
    <el-table
      v-loading="loading"
      :data="tableData"
      border
      style="width: 100%"
    >
      <el-table-column
        type="index"
        label="序号"
        width="50"
        align="center"
      />
      <el-table-column
        prop="batchNo"
        label="批次号"
        align="center"
      />
      <el-table-column
        prop="totalCount"
        label="申请总户数"
        align="center"
      />
      <el-table-column
        prop="approvedCount"
        label="申请总人数"
        align="center"
      />
      <el-table-column
        prop="compensationAmount"
        width="120"
        label="补偿资金总额(万元)"
        align="center"
      />
      <el-table-column
        prop="compensationArea"
        label="25%建筑面积"
        align="center"
      />
      <el-table-column
        prop="temporaryAmount"
        label="临时安置补助金额"
        align="center"
      />
      <el-table-column
        prop="temporaryPeriod"
        label="过渡期限"
        align="center"
      />
      <el-table-column
        prop="totalArea"
        label="总建筑面积"
        align="center"
      />
      <el-table-column
        prop="secondArea"
        label="二手房面积"
        align="center"
      />
      <el-table-column
        prop="newArea"
        label="新建住房面积"
        align="center"
      />
      <el-table-column
        prop="status"
        label="状态"
        align="center"
      />
      <el-table-column
        label="操作"
        align="center"
        width="200"
      >
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            @click="handleView(scope.row)"
          >申请详情</el-button>
          <el-button
            size="mini"
            type="text"
            @click="handleEdit(scope.row)"
          >编辑</el-button>
          <el-button
            size="mini"
            type="text"
            @click="handleDelete(scope.row)"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页区域 -->
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
    <export-money-applay :visible.sync="dialogVisible" />
  </div>
</template>
<script>
import ExportMoneyApplay from './components/exportMoneyApplay.vue'
export default {
    name: "RelocatablePersonnel",
    components: {},
    props: {},
    data() {
        return {};
  name: 'PlacementBatch',
  components: {
    ExportMoneyApplay
  },
  data() {
    return {
      // 遮罩层
      loading: false,
      // 弹窗
      dialogVisible:false,
      // 总条数
      total: 0,
      // 表格数据
      tableData: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        batchNo: undefined,
        status: undefined
      },
      dialogVisible: false
    }
  },
  created() {
    this.getList()
  },
  methods: {
    /** 查询列表 */
    getList() {
      this.loading = true
      // TODO: 调用接口获取数据
      setTimeout(() => {
        this.tableData = [
          {
            batchNo: '第202501批次',
            totalCount: '222',
            approvedCount: '222',
            compensationAmount: '',
            compensationArea: '',
            temporaryAmount: '',
            temporaryPeriod: '',
            totalArea: '828',
            secondArea: '',
            newArea: '',
            status: '申请详情'
          }
        ]
        this.total = 4
        this.loading = false
      }, 1000)
    },
    computed: {},
    watch: {},
    created() { },
    mounted() { },
    methods: {},
};
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    /** 新增按钮操作 */
    handleAdd() {
      // TODO: 实现新增逻辑
    },
    /** 导入资金批次 */
    handleImportAll() {
      // TODO: 实现导出逻辑
      this.dialogVisible = true
    },
    /** 下载模板 */
    handleExportTemplate() {
      // TODO: 实现下载模板逻辑
    },
    /** 下载临时安置模板 */
    handleImportTemplate() {
      // TODO: 实现下载临时安置模板逻辑
    },
    /** 查看详情按钮操作 */
    handleView(row) {
      // TODO: 实现查看详情逻辑
    },
    /** 编辑按钮操作 */
    handleEdit(row) {
      // TODO: 实现编辑逻辑
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      // TODO: 实现删除逻辑
    }
  }
}
</script>
<style scoped></style>
<style scoped>
.app-container {
  padding: 20px;
}
.filter-container {
  margin-bottom: 20px;
}
.button-container {
  margin-bottom: 20px;
}
</style>
src/views/placement-batch/person.vue
New file
@@ -0,0 +1,414 @@
<template>
    <div class="app-container">
      <!-- 搜索区域 -->
      <div class="filter-container">
        <el-form :inline="true" :model="queryParams" class="demo-form-inline">
          <el-form-item label="镇街">
            <el-input v-model="queryParams.town" size="small" placeholder="请输入" clearable></el-input>
          </el-form-item>
          <el-form-item label="所在村(社区)">
            <el-input v-model="queryParams.village" size="small" placeholder="请输入" clearable></el-input>
          </el-form-item>
          <el-form-item label="项目名称">
            <el-input v-model="queryParams.projectName" size="small" placeholder="请输入" clearable></el-input>
          </el-form-item>
          <el-form-item label="户主姓名">
            <el-input v-model="queryParams.householderName" size="small" placeholder="请输入" clearable></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" size="small" @click="handleQuery">查询</el-button>
            <el-button type="primary" plain size="small" @click="handleReset">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
      <!-- Tab切换区域 -->
      <div class="tab-container">
        <el-tabs v-model="activeTab" type="card" @tab-click="handleTabClick">
          <el-tab-pane label="资金表" name="fullReport"></el-tab-pane>
          <el-tab-pane label="购房信息表" name="houseInfo"></el-tab-pane>
        </el-tabs>
      </div>
      <!-- 统计卡片区域 -->
      <div class="statistics-container">
        <el-row :gutter="20">
          <el-col :span="6">
            <el-card class="statistics-card" shadow="hover">
              <div class="card-amount">2,183万元</div>
              <div class="card-title">补偿资金总金额</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card class="statistics-card" shadow="hover">
              <div class="card-amount">2,183万元</div>
              <div class="card-title">首付款总金额</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card class="statistics-card" shadow="hover">
              <div class="card-amount">2,183万元</div>
              <div class="card-title">过渡补贴总金额</div>
            </el-card>
          </el-col>
          <el-col :span="6">
            <el-card class="statistics-card" shadow="hover">
              <div class="card-amount">2,183万元</div>
              <div class="card-title">季度款总金额</div>
            </el-card>
          </el-col>
        </el-row>
      </div>
      <!-- 功能按钮区域 -->
      <div class="button-container">
        <el-button type="primary" size="small" @click="handleExport">新增安置户记录</el-button>
        <el-button type="success" size="small" @click="handleDownloadTemplate">下载导入模板</el-button>
        <el-button type="primary" size="small" @click="handleImport">批量导入</el-button>
        <el-button type="danger" size="small" @click="handleExportSelected">问题数据导出</el-button>
      </div>
      <div v-if="activeTab === 'fullReport'">
      <!-- 表格区域 -->
      <el-table
        v-loading="loading"
        :data="tableData"
        border
        style="width: 100%"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="index" label="序号" width="50" align="center" />
        <el-table-column prop="town" label="镇(街道)" min-width="120" align="center" />
        <el-table-column prop="projectName" label="拆迁项目名称" min-width="180" align="center" />
        <el-table-column prop="village" label="所在村(社区)" min-width="120" align="center" />
        <el-table-column prop="householderName" label="户主姓名" min-width="100" align="center" />
        <el-table-column prop="idCard" label="身份证号" min-width="180" align="center" />
        <el-table-column prop="familySize" label="应安置人数(人)" min-width="140" align="center" />
        <el-table-column label="所有家庭人员应安置面积(㎡)" min-width="160" align="center"/>
        <el-table-column label="补偿单位标准(万元)" min-width="160" align="center">
          <el-table-column prop="compensationAmount" label="新建商品住房、商业用房、停车位" min-width="160" align="center" />
          <el-table-column prop="buildingArea" label="二手住房" min-width="150" align="center" />
        </el-table-column>
        <el-table-column prop="compensationAmount" label="补偿资金总额(万元)" min-width="160" align="center" />
        <el-table-column prop="buildingArea" label="25%首付款(㎡)" min-width="150" align="center" />
        <el-table-column prop="temporaryAmount" label="每季度需支付款项(万元)" min-width="180" align="center" />
        <el-table-column prop="temporaryAmount" label="过渡补贴(万元)" min-width="180" align="center" />
        <el-table-column label="操作" fixed="right" width="180" align="center">
          <template slot-scope="scope">
            <el-button type="text" size="small" @click="handleView(scope.row)">详情</el-button>
            <el-button type="text" size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button type="text" size="small" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页区域 -->
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
      />
    </div>
    <div v-if="activeTab === 'houseInfo'">
      <!-- 购房信息表格 -->
      <el-table
        v-loading="loading"
        :data="houseTableData"
        border
        style="width: 100%"
      >
        <el-table-column type="index" label="序号" width="50" align="center" />
        <el-table-column prop="batchNo" label="镇(街道)" min-width="100" align="center" />
        <el-table-column prop="batchNo" label="拆迁项目名称" min-width="100" align="center" />
        <el-table-column prop="batchNo" label="所在村(社区)" min-width="100" align="center" />
        <el-table-column prop="batchNo" label="拆迁时间" min-width="100" align="center" />
        <el-table-column prop="householderName" label="户主姓名" min-width="100" align="center" />
        <el-table-column prop="idCard" label="身份证号" min-width="180" align="center" />
        <el-table-column prop="householderName" label="联系电话" min-width="100" align="center" />
        <el-table-column prop="householderName" label="本次安置人数(人)" min-width="100" align="center" >
          <el-table-column prop="householderName" label="集体经济组织成员" min-width="100" align="center" />
          <el-table-column prop="householderName" label="非集体经济组织成员" min-width="100" align="center" />
          <el-table-column prop="householderName" label="合计" min-width="100" align="center" />
        </el-table-column>
        <el-table-column prop="householderName" label="待安置家庭成员姓名" min-width="100" align="center" />
        <el-table-column prop="householderName" label="待安置人员应安置面积合计(㎡)" min-width="100" align="center" />
        <el-table-column prop="householderName" label="补偿金额(万元)" min-width="100" align="center" >
          <el-table-column prop="householderName" label="新建商品住房、商业用房、停车位" min-width="100" align="center" />
          <el-table-column prop="householderName" label="二手住房" min-width="100" align="center" />
          <el-table-column prop="householderName" label="合计" min-width="100" align="center" />
        </el-table-column>
        <el-table-column prop="householderName" label="25%首付款(万元)" min-width="100" align="center" />
        <el-table-column prop="householderName" label="每季度需支付款项(万元)" min-width="100" align="center" />
        <el-table-column prop="householderName" label="过渡补贴(万元)" min-width="100" align="center" />
        <el-table-column prop="householderName" label="备注" min-width="100" align="center" />
        <el-table-column prop="householderName" label="凭证发放时间" min-width="100" align="center" />
        <el-table-column prop="householderName" label="购房时间" min-width="100" align="center" />
        <el-table-column prop="householderName" label="成交金额(万元)" min-width="100" align="center" />
        <el-table-column prop="householderName" label="新建商品住房" min-width="100" align="center" >
          <el-table-column prop="householderName" label="楼盘名称" min-width="100" align="center" />
          <el-table-column prop="householderName" label="面积(㎡)" min-width="100" align="center" />
          <el-table-column prop="householderName" label="套数(套)" min-width="100" align="center" />
        </el-table-column>
        <el-table-column prop="householderName" label="二手住房" min-width="100" align="center" >
          <el-table-column prop="householderName" label="小区名称" min-width="100" align="center" />
          <el-table-column prop="householderName" label="面积(㎡)" min-width="100" align="center" />
          <el-table-column prop="householderName" label="套数(套)" min-width="100" align="center" />
        </el-table-column>
        <el-table-column prop="householderName" label="新建商业用房" min-width="100" align="center" >
          <el-table-column prop="householderName" label="楼盘名称" min-width="100" align="center" />
          <el-table-column prop="householderName" label="面积(㎡)" min-width="100" align="center" />
          <el-table-column prop="householderName" label="套数(套)" min-width="100" align="center" />
        </el-table-column>
        <el-table-column prop="householderName" label="新建停车位" min-width="100" align="center" >
          <el-table-column prop="householderName" label="楼盘名称" min-width="100" align="center" />
          <el-table-column prop="householderName" label="金额(万元)" min-width="100" align="center" />
          <el-table-column prop="householderName" label="个数(个)" min-width="100" align="center" />
        </el-table-column>
        <el-table-column prop="householderName" label="自主购房协议签订时间" min-width="100" align="center" />
        <el-table-column prop="householderName" label="25%补偿款及过渡补贴支付时间" min-width="100" align="center" />
        <el-table-column prop="householderName" label="剩余款项支付时间" min-width="100" align="center" >
          <el-table-column prop="householderName" label="第一年" min-width="100" align="center" />
          <el-table-column prop="householderName" label="第二年" min-width="100" align="center" />
          <el-table-column prop="householderName" label="第三年" min-width="100" align="center" />
          <el-table-column prop="householderName" label="第四年" min-width="100" align="center" />
        </el-table-column>
        <el-table-column prop="status" label="状态" min-width="80" align="center">
          <template slot-scope="scope">
            <el-tag :type="scope.row.status === '已通过' ? 'success' : 'info'">
              {{ scope.row.status }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" fixed="right" width="180" align="center">
          <template slot-scope="scope">
            <el-button type="text" size="small" @click="handleView(scope.row)">详情</el-button>
            <el-button type="text" size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button type="text" size="small" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页区域 -->
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getHouseList"
      />
    </div>
    </div>
  </template>
  <script>
  export default {
    name: 'PlacementPerson',
    components: {},
    data() {
      return {
        // 遮罩层
        loading: false,
        // 选中数组
        selectedRows: [],
        // 非单个禁用
        single: true,
        // 非多个禁用
        multiple: true,
        // 总条数
        total: 0,
        // 表格数据
        tableData: [
          {
            town: '长洲社区',
            projectName: '长洲水利工程征地拆迁',
            village: '和兴社区',
            householderName: '张三',
            idCard: '220102198512345678',
            familySize: 3,
            totalArea: 160,
            registeredArea: 120,
            measuredArea: 120,
            courtArea: 40,
            compensationAmount: 30,
            buildingArea: 38,
            temporaryAmount: 5
          }
        ],
        // 当前激活的tab
        activeTab: 'fullReport',
        // 查询参数
        queryParams: {
          pageNum: 1,
          pageSize: 10,
          town: undefined,
          village: undefined,
          projectName: undefined,
          householderName: undefined
        },
        // 购房信息表格数据
        houseTableData: [
          {
            householderName: '张三',
            idCard: '220102198512345678',
            familySize: 3,
            houseAddress: '长洲社区XX街道',
            houseType: '住宅',
            houseArea: 160,
            landArea: 100,
            compensationArea: 160,
            compensationAmount: 30,
            temporaryAmount: 5,
            temporaryPeriod: '12个月',
            newHouseArea: 0,
            secondHandArea: 160,
            totalArea: 160,
            status: '已通过'
          }
        ],
      }
    },
    created() {
      this.getList()
    },
    methods: {
      /** 查询列表 */
      getList() {
        this.loading = true
        // TODO: 调用接口获取数据
        setTimeout(() => {
          this.tableData = [
            {
              town: '长洲社区',
              projectName: '长洲水利工程征地拆迁',
              village: '和兴社区',
              householderName: '张三',
              idCard: '220102198512345678',
              familySize: 3,
              totalArea: 160,
              registeredArea: 120,
              measuredArea: 120,
              courtArea: 40,
              compensationAmount: 30,
              buildingArea: 38,
              temporaryAmount: 5
            }
          ]
          this.total = 4
          this.loading = false
        }, 1000)
      },
      /** 搜索按钮操作 */
      handleQuery() {
        this.queryParams.pageNum = 1
        this.getList()
      },
      /** 重置按钮操作 */
      handleReset() {
        this.queryParams = {
          pageNum: 1,
          pageSize: 10,
          town: undefined,
          village: undefined,
          projectName: undefined,
          householderName: undefined
        }
        this.getList()
      },
      /** Tab切换操作 */
      handleTabClick(tab) {
        if (tab.name === 'houseInfo') {
          this.getHouseList()
        } else {
          this.getList()
        }
      },
      /** 选择框变更 */
      handleSelectionChange(selection) {
        this.selectedRows = selection
        this.single = selection.length !== 1
        this.multiple = !selection.length
      },
      /** 新增按钮操作 */
      handleAdd() {
        // TODO: 实现新增逻辑
      },
      /** 导出操作 */
      handleExport() {
        // TODO: 实现导出逻辑
      },
      /** 下载模板 */
      handleDownloadTemplate() {
        // TODO: 实现下载模板逻辑
      },
      /** 导入操作 */
      handleImport() {
        // TODO: 实现导入逻辑
      },
      /** 导出选中记录 */
      handleExportSelected() {
        // TODO: 实现导出选中记录逻辑
      },
      /** 查看详情按钮操作 */
      handleView(row) {
        // TODO: 实现查看详情逻辑
      },
      /** 编辑按钮操作 */
      handleEdit(row) {
        // TODO: 实现编辑逻辑
      },
      /** 删除按钮操作 */
      handleDelete(row) {
        // TODO: 实现删除逻辑
      },
      /** 获取购房信息列表 */
      getHouseList() {
        this.loading = true
        // TODO: 调用接口获取购房信息数据
        setTimeout(() => {
          this.loading = false
        }, 1000)
      },
    }
  }
  </script>
  <style scoped>
  .app-container {
    padding: 20px;
  }
  .filter-container {
    margin-bottom: 20px;
  }
  .tab-container {
    margin-bottom: 20px;
  }
  .statistics-container {
    margin-bottom: 20px;
  }
  .statistics-card {
    text-align: center;
    color: #666;
  }
  .card-amount {
    font-size: 24px;
    color: #409EFF;
    margin-bottom: 10px;
  }
  .card-title {
    font-size: 14px;
  }
  .button-container {
    margin-bottom: 20px;
  }
  .area-value {
    cursor: pointer;
    color: #409EFF;
    text-decoration: underline;
  }
  .el-table {
    margin-bottom: 20px;
  }
  </style>
src/views/relocatablePersonnel/add.vue
New file
@@ -0,0 +1,476 @@
<template>
    <div class="app-container">
        <el-form ref="form" :model="form" :rules="rules" label-width="180px" class="custom-form" label-position="top">
            <!-- 第一排5个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="项目名称" prop="projectName">
                            <el-input v-model="form.projectName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="项目启动时间" prop="startTime">
                            <el-date-picker v-model="form.startTime" type="date" placeholder="选择日期" :disabled="isView"
                                style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="镇(街道)" prop="street">
                            <el-select v-model="form.street" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option v-for="item in streetOptions" :key="item.dictCode" :label="item.dictLabel"
                                    :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="所在村(社区)" prop="community">
                            <el-input v-model="form.community" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="组" prop="groupName">
                            <el-input v-model="form.groupName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <!-- 户主信息2个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="5" class="form-col-container">
                    <div class="form-col-half">
                        <el-form-item label="户主姓名" prop="householdHead">
                            <el-input v-model="form.householdHead" placeholder="请输入" :disabled="isView"
                                style="width: 92%" />
                        </el-form-item>
                    </div>
                </el-col>
                <el-col :span="5" class="form-col-container">
                    <div class="form-col-half">
                        <el-form-item label="户主身份证号码" prop="idCard">
                            <el-input v-model="form.idCard" placeholder="请输入" :disabled="isView" style="width: 89%" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <!-- 后续每排5个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="家庭成员名字" prop="familyName">
                            <el-input v-model="form.familyName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="关系" prop="relation">
                            <el-select v-model="form.relation" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option v-for="item in relationOptions" :key="item.dictCode" :label="item.dictLabel"
                                    :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="人员类型" prop="personType">
                            <el-select v-model="form.personType" placeholder="请选择" :disabled="isView"
                                style="width: 100%">
                                <el-option v-for="item in personTypeOptions" :key="item.dictCode"
                                    :label="item.dictLabel" :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="身份证号码" prop="familyIdCard">
                            <el-input v-model="form.familyIdCard" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="年龄" prop="age">
                            <el-input v-model="form.age" placeholder="根据身份证自动生成" disabled />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="性别" prop="sex">
                            <el-input v-model="form.sex" placeholder="根据身份证自动生成" disabled />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="出生年月日" prop="birthday">
                            <el-date-picker v-model="form.birthday" type="date" placeholder="选择日期" :disabled="isView"
                                style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="安置方式" prop="ways">
                            <el-select v-model="form.ways" placeholder="请选择" :disabled="isView"
                                style="width: 100%">
                                <el-option label="统规统建" value="统规统建" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="联系电话" prop="mobile">
                            <el-input v-model="form.mobile" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="原始拆迁时领取过渡费时间" prop="originCollectionTime">
                            <el-date-picker v-model="form.originCollectionTime" type="date" placeholder="选择日期"
                                :disabled="isView" style="width: 100%" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="上次过渡费发放时间(起)" prop="lastBeginTime">
                            <el-date-picker v-model="form.lastBeginTime" type="date" placeholder="选择日期"
                                :disabled="isView" style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="上次过渡费发放时间(止)" prop="lastEndTime">
                            <el-date-picker v-model="form.lastEndTime" type="date" placeholder="选择日期" :disabled="isView"
                                :picker-options="endDateOptions" style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="安置状态">
                            <el-select v-model="form.status" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option label="已安置" :value="1" />
                                <el-option label="未安置" :value="0" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="剩余未安置面积" prop="noHouseArea">
                            <el-input v-model="form.noHouseArea" placeholder="请输入" :disabled="isView">
                                <template slot="append">m²</template>
                            </el-input>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="剩余未安置商铺面积" prop="noShopArea">
                            <el-input v-model="form.noShopArea" placeholder="请输入" :disabled="isView">
                                <template slot="append">m²</template>
                            </el-input>
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24">
                    <el-form-item label="备注">
                        <el-input type="textarea" v-model="form.remark" :disabled="isView" />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24">
                    <el-form-item>
                        <el-button v-if="!isView" type="primary" @click="submitForm">保存</el-button>
                        <el-button @click="cancel">返回</el-button>
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
    </div>
</template>
<script>
import { update, getDetail, add, getDictData } from '@/api/placement'
export default {
    name: 'PersonnelForm',
    data() {
        // 身份证号码验证
        const validateIdCard = (rule, value, callback) => {
            const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
            if (!reg.test(value)) {
                callback(new Error('请输入正确的身份证号码'))
            } else {
                callback()
            }
        }
        // 手机号验证
        const validatePhone = (rule, value, callback) => {
            const reg = /^1[3-9]\d{9}$/
            if (!reg.test(value)) {
                callback(new Error('请输入正确的手机号码'))
            } else {
                callback()
            }
        }
        // 日期止不能小于日期起
        const validateEndDate = (rule, value, callback) => {
            if (value && this.form.lastBeginTime && value < this.form.lastBeginTime) {
                callback(new Error('结束时间不能早于开始时间'))
            } else {
                callback()
            }
        }
        return {
            isView: false,
            form: {
                projectName: undefined,
                startTime: undefined,
                street: undefined,
                community: undefined,
                groupName: undefined,
                householdHead: undefined,
                idCard: undefined,
                familyName: undefined,
                relation: undefined,
                personType: undefined,
                familyIdCard: undefined,
                age: undefined,
                sex: undefined,
                birthday: undefined,
                ways: undefined,
                originCollectionTime: undefined,
                lastBeginTime: undefined,
                lastEndTime: undefined,
                noHouseArea: undefined,
                noShopArea: undefined,
                mobile: undefined,
                status: undefined,
                remark: undefined
            },
            endDateOptions: {
                disabledDate: (time) => {
                    if (this.form.lastBeginTime) {
                        return time.getTime() < this.form.lastBeginTime.getTime()
                    }
                    return false
                }
            },
            streetOptions: [],
            relationOptions: [],
            personTypeOptions: [],
            rules: {
                projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
                startTime: [{ required: true, message: '请选择项目启动时间', trigger: 'change' }],
                street: [{ required: true, message: '请输入镇(街道)', trigger: 'blur' }],
                community: [{ required: true, message: '请输入所在村(社区)', trigger: 'blur' }],
                groupName: [{ required: true, message: '请输入组', trigger: 'blur' }],
                householdHead: [{ required: true, message: '请输入户主姓名', trigger: 'blur' }],
                idCard: [
                    { required: true, message: '请输入身份证号码', trigger: 'blur' },
                    { validator: validateIdCard, trigger: 'blur' }
                ],
                familyName: [{ required: true, message: '请输入家庭成员名字', trigger: 'blur' }],
                relation: [{ required: true, message: '请选择关系', trigger: 'change' }],
                personType: [{ required: true, message: '请选择人员类型', trigger: 'change' }],
                familyIdCard: [
                    { required: true, message: '请输入身份证号码', trigger: 'blur' },
                    { validator: validateIdCard, trigger: 'blur' }
                ],
                age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
                sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
                birthday: [{ required: true, message: '请选择出生年月日', trigger: 'change' }],
                ways: [{ required: true, message: '请选择安置方式', trigger: 'change' }],
                mobile: [
                    { required: true, message: '请输入联系电话', trigger: 'blur' },
                    { validator: validatePhone, trigger: 'blur' }
                ],
                originCollectionTime: [{ required: true, message: '请选择原始拆迁时领取过渡费时间', trigger: 'change' }],
                lastBeginTime: [{ required: true, message: '请选择上次过渡费发放时间(起)', trigger: 'change' }],
                lastEndTime: [
                    { required: true, message: '请选择结束时间', trigger: 'change' },
                    { validator: validateEndDate, trigger: 'change' }
                ],
                noHouseArea: [{ required: true, message: '请输入剩余未安置面积', trigger: 'blur' }]
            }
        }
    },
    created() {
        // 镇(街道)
        getDictData('street').then(response => {
            this.streetOptions = response.data
        })
        // 关系
        getDictData('relation ').then(response => {
            this.relationOptions = response.data
        })
        // 人员类型
        getDictData('person_type').then(response => {
            this.personTypeOptions = response.data
        })
        const id = this.$route.query.id
        const type = this.$route.query.type
        if (id) {
            this.isView = type === 'view'
            this.getInfo(id)
        }
    },
    watch: {
        'form.familyIdCard': {
            handler(newVal) {
                if (newVal && this.isValidIdCard(newVal)) {
                    this.form.sex = this.getsexFromIdCard(newVal)
                    this.form.age = this.getAgeFromIdCard(newVal)
                }
            },
            immediate: true
        },
        'form.lastBeginTime': {
            handler(newVal) {
                // 当开始时间变化时,如果结束时间小于开始时间,清空结束时间
                if (newVal && this.form.lastEndTime && this.form.lastEndTime < newVal) {
                    this.form.lastEndTime = null
                }
            }
        }
    },
    methods: {
        getInfo(id) {
            getDetail({ id }).then(response => {
                this.form = response.data
            })
        },
        submitForm() {
            this.$refs.form.validate(valid => {
                if (valid) {
                    const submitMethod = this.form.id ? update : add
                    submitMethod(this.form).then(() => {
                        this.$modal.msgSuccess('操作成功')
                        this.goBack()
                    })
                }
            })
        },
        cancel() {
            this.goBack()
        },
        goBack() {
            this.$router.go(-1)
        },
        // 验证身份证号码
        isValidIdCard(idCard) {
            const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
            return reg.test(idCard)
        },
        // 从身份证号获取性别
        getsexFromIdCard(idCard) {
            if (idCard.length === 15) {
                return parseInt(idCard.charAt(14)) % 2 === 0 ? '女' : '男'
            } else if (idCard.length === 18) {
                return parseInt(idCard.charAt(16)) % 2 === 0 ? '女' : '男'
            }
            return ''
        },
        // 从身份证号获取年龄
        getAgeFromIdCard(idCard) {
            let birthYear, birthMonth, birthDay
            if (idCard.length === 15) {
                birthYear = '19' + idCard.substring(6, 8)
                birthMonth = idCard.substring(8, 10)
                birthDay = idCard.substring(10, 12)
            } else if (idCard.length === 18) {
                birthYear = idCard.substring(6, 10)
                birthMonth = idCard.substring(10, 12)
                birthDay = idCard.substring(12, 14)
            } else {
                return ''
            }
            const today = new Date()
            const birthday = new Date(birthYear, birthMonth - 1, birthDay)
            let age = today.getFullYear() - birthday.getFullYear()
            const monthDiff = today.getMonth() - birthday.getMonth()
            if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthday.getDate())) {
                age--
            }
            return age.toString()
        }
    }
}
</script>
<style scoped>
.app-container {
    padding: 20px;
}
.custom-form {
    width: 100%;
}
.form-row {
    margin-bottom: 18px;
}
.form-col-container {
    display: flex;
    justify-content: flex-start;
    flex-wrap: nowrap;
    gap: 20px;
    /* 设置列之间的间距 */
}
.form-col {
    flex: 1;
    min-width: 0;
    /* 防止flex项目溢出 */
}
.form-col-half {
    flex: 1;
    min-width: 0;
}
/* 确保所有输入控件宽度一致 */
:deep(.el-input),
:deep(.el-select),
:deep(.el-date-picker) {
    width: 100% !important;
}
:deep(.el-input__inner),
:deep(.el-select .el-input__inner),
:deep(.el-date-picker .el-input__inner) {
    width: 100% !important;
}
/* 确保日期选择器的宽度与其他输入框一致 */
:deep(.el-date-editor.el-input) {
    width: 100% !important;
}
/* 确保带单位的输入框宽度一致 */
:deep(.el-input-group__append) {
    padding: 0 10px;
}
/* 设置表单项标签样式 */
:deep(.el-form-item__label) {
    line-height: 20px;
    padding-bottom: 8px;
    color: #606266;
}
/* 调整表单项间距 */
:deep(.el-form-item) {
    margin-bottom: 18px;
}
/* 确保textarea的宽度正确 */
:deep(.el-textarea) {
    width: 100%;
}
</style>
src/views/relocatablePersonnel/detail.vue
@@ -1,20 +1,476 @@
<template>
  <div>22222</div>
    <div class="app-container">
        <el-form ref="form" :model="form" :rules="rules" label-width="180px" class="custom-form" label-position="top">
            <!-- 第一排5个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="项目名称" prop="projectName">
                            <el-input v-model="form.projectName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="项目启动时间" prop="startTime">
                            <el-date-picker v-model="form.startTime" type="date" placeholder="选择日期" :disabled="isView"
                                style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="镇(街道)" prop="street">
                            <el-select v-model="form.street" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option v-for="item in streetOptions" :key="item.dictCode" :label="item.dictLabel"
                                    :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="所在村(社区)" prop="community">
                            <el-input v-model="form.community" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="组" prop="groupName">
                            <el-input v-model="form.groupName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <!-- 户主信息2个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="5" class="form-col-container">
                    <div class="form-col-half">
                        <el-form-item label="户主姓名" prop="householdHead">
                            <el-input v-model="form.householdHead" placeholder="请输入" :disabled="isView"
                                style="width: 92%" />
                        </el-form-item>
                    </div>
                </el-col>
                <el-col :span="5" class="form-col-container">
                    <div class="form-col-half">
                        <el-form-item label="户主身份证号码" prop="idCard">
                            <el-input v-model="form.idCard" placeholder="请输入" :disabled="isView" style="width: 89%" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <!-- 后续每排5个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="家庭成员名字" prop="familyName">
                            <el-input v-model="form.familyName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="关系" prop="relation">
                            <el-select v-model="form.relation" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option v-for="item in relationOptions" :key="item.dictCode" :label="item.dictLabel"
                                    :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="人员类型" prop="personType">
                            <el-select v-model="form.personType" placeholder="请选择" :disabled="isView"
                                style="width: 100%">
                                <el-option v-for="item in personTypeOptions" :key="item.dictCode"
                                    :label="item.dictLabel" :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="身份证号码" prop="familyIdCard">
                            <el-input v-model="form.familyIdCard" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="年龄" prop="age">
                            <el-input v-model="form.age" placeholder="根据身份证自动生成" disabled />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="性别" prop="sex">
                            <el-input v-model="form.sex" placeholder="根据身份证自动生成" disabled />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="出生年月日" prop="birthday">
                            <el-date-picker v-model="form.birthday" type="date" placeholder="选择日期" :disabled="isView"
                                style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="安置方式" prop="ways">
                            <el-select v-model="form.ways" placeholder="请选择" :disabled="isView"
                                style="width: 100%">
                                <el-option label="统规统建" value="统规统建" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="联系电话" prop="mobile">
                            <el-input v-model="form.mobile" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="原始拆迁时领取过渡费时间" prop="originCollectionTime">
                            <el-date-picker v-model="form.originCollectionTime" type="date" placeholder="选择日期"
                                :disabled="isView" style="width: 100%" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="上次过渡费发放时间(起)" prop="lastBeginTime">
                            <el-date-picker v-model="form.lastBeginTime" type="date" placeholder="选择日期"
                                :disabled="isView" style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="上次过渡费发放时间(止)" prop="lastEndTime">
                            <el-date-picker v-model="form.lastEndTime" type="date" placeholder="选择日期" :disabled="isView"
                                :picker-options="endDateOptions" style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="安置状态">
                            <el-select v-model="form.status" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option label="已安置" :value="1" />
                                <el-option label="未安置" :value="0" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="剩余未安置面积" prop="noHouseArea">
                            <el-input v-model="form.noHouseArea" placeholder="请输入" :disabled="isView">
                                <template slot="append">m²</template>
                            </el-input>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="剩余未安置商铺面积" prop="noShopArea">
                            <el-input v-model="form.noShopArea" placeholder="请输入" :disabled="isView">
                                <template slot="append">m²</template>
                            </el-input>
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24">
                    <el-form-item label="备注">
                        <el-input type="textarea" v-model="form.remark" :disabled="isView" />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24">
                    <el-form-item>
                        <el-button v-if="!isView" type="primary" @click="submitForm">保存</el-button>
                        <el-button @click="cancel">返回</el-button>
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
    </div>
</template>
<script>
import { update, getDetail, add, getDictData } from '@/api/placement'
export default {
  name: "RelocatablePersonnelDetail",
  components: {},
  props: {},
  data() {
    return {};
  },
  computed: {},
  watch: {},
  created() { },
  mounted() { },
  methods: {},
};
    name: 'PersonnelForm',
    data() {
        // 身份证号码验证
        const validateIdCard = (rule, value, callback) => {
            const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
            if (!reg.test(value)) {
                callback(new Error('请输入正确的身份证号码'))
            } else {
                callback()
            }
        }
        // 手机号验证
        const validatePhone = (rule, value, callback) => {
            const reg = /^1[3-9]\d{9}$/
            if (!reg.test(value)) {
                callback(new Error('请输入正确的手机号码'))
            } else {
                callback()
            }
        }
        // 日期止不能小于日期起
        const validateEndDate = (rule, value, callback) => {
            if (value && this.form.lastBeginTime && value < this.form.lastBeginTime) {
                callback(new Error('结束时间不能早于开始时间'))
            } else {
                callback()
            }
        }
        return {
            isView: false,
            form: {
                projectName: undefined,
                startTime: undefined,
                street: undefined,
                community: undefined,
                groupName: undefined,
                householdHead: undefined,
                idCard: undefined,
                familyName: undefined,
                relation: undefined,
                personType: undefined,
                familyIdCard: undefined,
                age: undefined,
                sex: undefined,
                birthday: undefined,
                ways: undefined,
                originCollectionTime: undefined,
                lastBeginTime: undefined,
                lastEndTime: undefined,
                noHouseArea: undefined,
                noShopArea: undefined,
                mobile: undefined,
                status: undefined,
                remark: undefined
            },
            endDateOptions: {
                disabledDate: (time) => {
                    if (this.form.lastBeginTime) {
                        return time.getTime() < this.form.lastBeginTime.getTime()
                    }
                    return false
                }
            },
            streetOptions: [],
            relationOptions: [],
            personTypeOptions: [],
            rules: {
                projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
                startTime: [{ required: true, message: '请选择项目启动时间', trigger: 'change' }],
                street: [{ required: true, message: '请输入镇(街道)', trigger: 'blur' }],
                community: [{ required: true, message: '请输入所在村(社区)', trigger: 'blur' }],
                groupName: [{ required: true, message: '请输入组', trigger: 'blur' }],
                householdHead: [{ required: true, message: '请输入户主姓名', trigger: 'blur' }],
                idCard: [
                    { required: true, message: '请输入身份证号码', trigger: 'blur' },
                    { validator: validateIdCard, trigger: 'blur' }
                ],
                familyName: [{ required: true, message: '请输入家庭成员名字', trigger: 'blur' }],
                relation: [{ required: true, message: '请选择关系', trigger: 'change' }],
                personType: [{ required: true, message: '请选择人员类型', trigger: 'change' }],
                familyIdCard: [
                    { required: true, message: '请输入身份证号码', trigger: 'blur' },
                    { validator: validateIdCard, trigger: 'blur' }
                ],
                age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
                sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
                birthday: [{ required: true, message: '请选择出生年月日', trigger: 'change' }],
                ways: [{ required: true, message: '请选择安置方式', trigger: 'change' }],
                mobile: [
                    { required: true, message: '请输入联系电话', trigger: 'blur' },
                    { validator: validatePhone, trigger: 'blur' }
                ],
                originCollectionTime: [{ required: true, message: '请选择原始拆迁时领取过渡费时间', trigger: 'change' }],
                lastBeginTime: [{ required: true, message: '请选择上次过渡费发放时间(起)', trigger: 'change' }],
                lastEndTime: [
                    { required: true, message: '请选择结束时间', trigger: 'change' },
                    { validator: validateEndDate, trigger: 'change' }
                ],
                noHouseArea: [{ required: true, message: '请输入剩余未安置面积', trigger: 'blur' }]
            }
        }
    },
    created() {
        // 镇(街道)
        getDictData('street').then(response => {
            this.streetOptions = response.data
        })
        // 关系
        getDictData('relation ').then(response => {
            this.relationOptions = response.data
        })
        // 人员类型
        getDictData('person_type').then(response => {
            this.personTypeOptions = response.data
        })
        const id = this.$route.query.id
        const type = this.$route.query.type
        if (id) {
            this.isView = type === 'view'
            this.getInfo(id)
        }
    },
    watch: {
        'form.familyIdCard': {
            handler(newVal) {
                if (newVal && this.isValidIdCard(newVal)) {
                    this.form.sex = this.getsexFromIdCard(newVal)
                    this.form.age = this.getAgeFromIdCard(newVal)
                }
            },
            immediate: true
        },
        'form.lastBeginTime': {
            handler(newVal) {
                // 当开始时间变化时,如果结束时间小于开始时间,清空结束时间
                if (newVal && this.form.lastEndTime && this.form.lastEndTime < newVal) {
                    this.form.lastEndTime = null
                }
            }
        }
    },
    methods: {
        getInfo(id) {
            getDetail({ id }).then(response => {
                this.form = response.data
            })
        },
        submitForm() {
            this.$refs.form.validate(valid => {
                if (valid) {
                    const submitMethod = this.form.id ? update : add
                    submitMethod(this.form).then(() => {
                        this.$modal.msgSuccess('操作成功')
                        this.goBack()
                    })
                }
            })
        },
        cancel() {
            this.goBack()
        },
        goBack() {
            this.$router.go(-1)
        },
        // 验证身份证号码
        isValidIdCard(idCard) {
            const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
            return reg.test(idCard)
        },
        // 从身份证号获取性别
        getsexFromIdCard(idCard) {
            if (idCard.length === 15) {
                return parseInt(idCard.charAt(14)) % 2 === 0 ? '女' : '男'
            } else if (idCard.length === 18) {
                return parseInt(idCard.charAt(16)) % 2 === 0 ? '女' : '男'
            }
            return ''
        },
        // 从身份证号获取年龄
        getAgeFromIdCard(idCard) {
            let birthYear, birthMonth, birthDay
            if (idCard.length === 15) {
                birthYear = '19' + idCard.substring(6, 8)
                birthMonth = idCard.substring(8, 10)
                birthDay = idCard.substring(10, 12)
            } else if (idCard.length === 18) {
                birthYear = idCard.substring(6, 10)
                birthMonth = idCard.substring(10, 12)
                birthDay = idCard.substring(12, 14)
            } else {
                return ''
            }
            const today = new Date()
            const birthday = new Date(birthYear, birthMonth - 1, birthDay)
            let age = today.getFullYear() - birthday.getFullYear()
            const monthDiff = today.getMonth() - birthday.getMonth()
            if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthday.getDate())) {
                age--
            }
            return age.toString()
        }
    }
}
</script>
<style scoped></style>
<style scoped>
.app-container {
    padding: 20px;
}
.custom-form {
    width: 100%;
}
.form-row {
    margin-bottom: 18px;
}
.form-col-container {
    display: flex;
    justify-content: flex-start;
    flex-wrap: nowrap;
    gap: 20px;
    /* 设置列之间的间距 */
}
.form-col {
    flex: 1;
    min-width: 0;
    /* 防止flex项目溢出 */
}
.form-col-half {
    flex: 1;
    min-width: 0;
}
/* 确保所有输入控件宽度一致 */
:deep(.el-input),
:deep(.el-select),
:deep(.el-date-picker) {
    width: 100% !important;
}
:deep(.el-input__inner),
:deep(.el-select .el-input__inner),
:deep(.el-date-picker .el-input__inner) {
    width: 100% !important;
}
/* 确保日期选择器的宽度与其他输入框一致 */
:deep(.el-date-editor.el-input) {
    width: 100% !important;
}
/* 确保带单位的输入框宽度一致 */
:deep(.el-input-group__append) {
    padding: 0 10px;
}
/* 设置表单项标签样式 */
:deep(.el-form-item__label) {
    line-height: 20px;
    padding-bottom: 8px;
    color: #606266;
}
/* 调整表单项间距 */
:deep(.el-form-item) {
    margin-bottom: 18px;
}
/* 确保textarea的宽度正确 */
:deep(.el-textarea) {
    width: 100%;
}
</style>
src/views/relocatablePersonnel/edit.vue
New file
@@ -0,0 +1,476 @@
<template>
    <div class="app-container">
        <el-form ref="form" :model="form" :rules="rules" label-width="180px" class="custom-form" label-position="top">
            <!-- 第一排5个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="项目名称" prop="projectName">
                            <el-input v-model="form.projectName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="项目启动时间" prop="startTime">
                            <el-date-picker v-model="form.startTime" type="date" placeholder="选择日期" :disabled="isView"
                                style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="镇(街道)" prop="street">
                            <el-select v-model="form.street" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option v-for="item in streetOptions" :key="item.dictCode" :label="item.dictLabel"
                                    :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="所在村(社区)" prop="community">
                            <el-input v-model="form.community" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="组" prop="groupName">
                            <el-input v-model="form.groupName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <!-- 户主信息2个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="5" class="form-col-container">
                    <div class="form-col-half">
                        <el-form-item label="户主姓名" prop="householdHead">
                            <el-input v-model="form.householdHead" placeholder="请输入" :disabled="isView"
                                style="width: 92%" />
                        </el-form-item>
                    </div>
                </el-col>
                <el-col :span="5" class="form-col-container">
                    <div class="form-col-half">
                        <el-form-item label="户主身份证号码" prop="idCard">
                            <el-input v-model="form.idCard" placeholder="请输入" :disabled="isView" style="width: 89%" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <!-- 后续每排5个 -->
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="家庭成员名字" prop="familyName">
                            <el-input v-model="form.familyName" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="关系" prop="relation">
                            <el-select v-model="form.relation" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option v-for="item in relationOptions" :key="item.dictCode" :label="item.dictLabel"
                                    :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="人员类型" prop="personType">
                            <el-select v-model="form.personType" placeholder="请选择" :disabled="isView"
                                style="width: 100%">
                                <el-option v-for="item in personTypeOptions" :key="item.dictCode"
                                    :label="item.dictLabel" :value="item.dictLabel" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="身份证号码" prop="familyIdCard">
                            <el-input v-model="form.familyIdCard" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="年龄" prop="age">
                            <el-input v-model="form.age" placeholder="根据身份证自动生成" disabled />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="性别" prop="sex">
                            <el-input v-model="form.sex" placeholder="根据身份证自动生成" disabled />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="出生年月日" prop="birthday">
                            <el-date-picker v-model="form.birthday" type="date" placeholder="选择日期" :disabled="isView"
                                style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="安置方式" prop="ways">
                            <el-select v-model="form.ways" placeholder="请选择" :disabled="isView"
                                style="width: 100%">
                                <el-option label="统规统建" value="统规统建" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="联系电话" prop="mobile">
                            <el-input v-model="form.mobile" placeholder="请输入" :disabled="isView" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="原始拆迁时领取过渡费时间" prop="originCollectionTime">
                            <el-date-picker v-model="form.originCollectionTime" type="date" placeholder="选择日期"
                                :disabled="isView" style="width: 100%" />
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24" class="form-col-container">
                    <div class="form-col">
                        <el-form-item label="上次过渡费发放时间(起)" prop="lastBeginTime">
                            <el-date-picker v-model="form.lastBeginTime" type="date" placeholder="选择日期"
                                :disabled="isView" style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="上次过渡费发放时间(止)" prop="lastEndTime">
                            <el-date-picker v-model="form.lastEndTime" type="date" placeholder="选择日期" :disabled="isView"
                                :picker-options="endDateOptions" style="width: 100%" />
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="安置状态">
                            <el-select v-model="form.status" placeholder="请选择" :disabled="isView" style="width: 100%">
                                <el-option label="已安置" :value="1" />
                                <el-option label="未安置" :value="0" />
                            </el-select>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="剩余未安置面积" prop="noHouseArea">
                            <el-input v-model="form.noHouseArea" placeholder="请输入" :disabled="isView">
                                <template slot="append">m²</template>
                            </el-input>
                        </el-form-item>
                    </div>
                    <div class="form-col">
                        <el-form-item label="剩余未安置商铺面积" prop="noShopArea">
                            <el-input v-model="form.noShopArea" placeholder="请输入" :disabled="isView">
                                <template slot="append">m²</template>
                            </el-input>
                        </el-form-item>
                    </div>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24">
                    <el-form-item label="备注">
                        <el-input type="textarea" v-model="form.remark" :disabled="isView" />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row type="flex" justify="start" class="form-row">
                <el-col :span="24">
                    <el-form-item>
                        <el-button v-if="!isView" type="primary" @click="submitForm">保存</el-button>
                        <el-button @click="cancel">返回</el-button>
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
    </div>
</template>
<script>
import { update, getDetail, add, getDictData } from '@/api/placement'
export default {
    name: 'PersonnelForm',
    data() {
        // 身份证号码验证
        const validateIdCard = (rule, value, callback) => {
            const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
            if (!reg.test(value)) {
                callback(new Error('请输入正确的身份证号码'))
            } else {
                callback()
            }
        }
        // 手机号验证
        const validatePhone = (rule, value, callback) => {
            const reg = /^1[3-9]\d{9}$/
            if (!reg.test(value)) {
                callback(new Error('请输入正确的手机号码'))
            } else {
                callback()
            }
        }
        // 日期止不能小于日期起
        const validateEndDate = (rule, value, callback) => {
            if (value && this.form.lastBeginTime && value < this.form.lastBeginTime) {
                callback(new Error('结束时间不能早于开始时间'))
            } else {
                callback()
            }
        }
        return {
            isView: false,
            form: {
                projectName: undefined,
                startTime: undefined,
                street: undefined,
                community: undefined,
                groupName: undefined,
                householdHead: undefined,
                idCard: undefined,
                familyName: undefined,
                relation: undefined,
                personType: undefined,
                familyIdCard: undefined,
                age: undefined,
                sex: undefined,
                birthday: undefined,
                ways: undefined,
                originCollectionTime: undefined,
                lastBeginTime: undefined,
                lastEndTime: undefined,
                noHouseArea: undefined,
                noShopArea: undefined,
                mobile: undefined,
                status: undefined,
                remark: undefined
            },
            endDateOptions: {
                disabledDate: (time) => {
                    if (this.form.lastBeginTime) {
                        return time.getTime() < this.form.lastBeginTime.getTime()
                    }
                    return false
                }
            },
            streetOptions: [],
            relationOptions: [],
            personTypeOptions: [],
            rules: {
                projectName: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
                startTime: [{ required: true, message: '请选择项目启动时间', trigger: 'change' }],
                street: [{ required: true, message: '请输入镇(街道)', trigger: 'blur' }],
                community: [{ required: true, message: '请输入所在村(社区)', trigger: 'blur' }],
                groupName: [{ required: true, message: '请输入组', trigger: 'blur' }],
                householdHead: [{ required: true, message: '请输入户主姓名', trigger: 'blur' }],
                idCard: [
                    { required: true, message: '请输入身份证号码', trigger: 'blur' },
                    { validator: validateIdCard, trigger: 'blur' }
                ],
                familyName: [{ required: true, message: '请输入家庭成员名字', trigger: 'blur' }],
                relation: [{ required: true, message: '请选择关系', trigger: 'change' }],
                personType: [{ required: true, message: '请选择人员类型', trigger: 'change' }],
                familyIdCard: [
                    { required: true, message: '请输入身份证号码', trigger: 'blur' },
                    { validator: validateIdCard, trigger: 'blur' }
                ],
                age: [{ required: true, message: '请输入年龄', trigger: 'blur' }],
                sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
                birthday: [{ required: true, message: '请选择出生年月日', trigger: 'change' }],
                ways: [{ required: true, message: '请选择安置方式', trigger: 'change' }],
                mobile: [
                    { required: true, message: '请输入联系电话', trigger: 'blur' },
                    { validator: validatePhone, trigger: 'blur' }
                ],
                originCollectionTime: [{ required: true, message: '请选择原始拆迁时领取过渡费时间', trigger: 'change' }],
                lastBeginTime: [{ required: true, message: '请选择上次过渡费发放时间(起)', trigger: 'change' }],
                lastEndTime: [
                    { required: true, message: '请选择结束时间', trigger: 'change' },
                    { validator: validateEndDate, trigger: 'change' }
                ],
                noHouseArea: [{ required: true, message: '请输入剩余未安置面积', trigger: 'blur' }]
            }
        }
    },
    created() {
        // 镇(街道)
        getDictData('street').then(response => {
            this.streetOptions = response.data
        })
        // 关系
        getDictData('relation ').then(response => {
            this.relationOptions = response.data
        })
        // 人员类型
        getDictData('person_type').then(response => {
            this.personTypeOptions = response.data
        })
        const id = this.$route.query.id
        const type = this.$route.query.type
        if (id) {
            this.isView = type === 'view'
            this.getInfo(id)
        }
    },
    watch: {
        'form.familyIdCard': {
            handler(newVal) {
                if (newVal && this.isValidIdCard(newVal)) {
                    this.form.sex = this.getsexFromIdCard(newVal)
                    this.form.age = this.getAgeFromIdCard(newVal)
                }
            },
            immediate: true
        },
        'form.lastBeginTime': {
            handler(newVal) {
                // 当开始时间变化时,如果结束时间小于开始时间,清空结束时间
                if (newVal && this.form.lastEndTime && this.form.lastEndTime < newVal) {
                    this.form.lastEndTime = null
                }
            }
        }
    },
    methods: {
        getInfo(id) {
            getDetail({ id }).then(response => {
                this.form = response.data
            })
        },
        submitForm() {
            this.$refs.form.validate(valid => {
                if (valid) {
                    const submitMethod = this.form.id ? update : add
                    submitMethod(this.form).then(() => {
                        this.$modal.msgSuccess('操作成功')
                        this.goBack()
                    })
                }
            })
        },
        cancel() {
            this.goBack()
        },
        goBack() {
            this.$router.go(-1)
        },
        // 验证身份证号码
        isValidIdCard(idCard) {
            const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
            return reg.test(idCard)
        },
        // 从身份证号获取性别
        getsexFromIdCard(idCard) {
            if (idCard.length === 15) {
                return parseInt(idCard.charAt(14)) % 2 === 0 ? '女' : '男'
            } else if (idCard.length === 18) {
                return parseInt(idCard.charAt(16)) % 2 === 0 ? '女' : '男'
            }
            return ''
        },
        // 从身份证号获取年龄
        getAgeFromIdCard(idCard) {
            let birthYear, birthMonth, birthDay
            if (idCard.length === 15) {
                birthYear = '19' + idCard.substring(6, 8)
                birthMonth = idCard.substring(8, 10)
                birthDay = idCard.substring(10, 12)
            } else if (idCard.length === 18) {
                birthYear = idCard.substring(6, 10)
                birthMonth = idCard.substring(10, 12)
                birthDay = idCard.substring(12, 14)
            } else {
                return ''
            }
            const today = new Date()
            const birthday = new Date(birthYear, birthMonth - 1, birthDay)
            let age = today.getFullYear() - birthday.getFullYear()
            const monthDiff = today.getMonth() - birthday.getMonth()
            if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthday.getDate())) {
                age--
            }
            return age.toString()
        }
    }
}
</script>
<style scoped>
.app-container {
    padding: 20px;
}
.custom-form {
    width: 100%;
}
.form-row {
    margin-bottom: 18px;
}
.form-col-container {
    display: flex;
    justify-content: flex-start;
    flex-wrap: nowrap;
    gap: 20px;
    /* 设置列之间的间距 */
}
.form-col {
    flex: 1;
    min-width: 0;
    /* 防止flex项目溢出 */
}
.form-col-half {
    flex: 1;
    min-width: 0;
}
/* 确保所有输入控件宽度一致 */
:deep(.el-input),
:deep(.el-select),
:deep(.el-date-picker) {
    width: 100% !important;
}
:deep(.el-input__inner),
:deep(.el-select .el-input__inner),
:deep(.el-date-picker .el-input__inner) {
    width: 100% !important;
}
/* 确保日期选择器的宽度与其他输入框一致 */
:deep(.el-date-editor.el-input) {
    width: 100% !important;
}
/* 确保带单位的输入框宽度一致 */
:deep(.el-input-group__append) {
    padding: 0 10px;
}
/* 设置表单项标签样式 */
:deep(.el-form-item__label) {
    line-height: 20px;
    padding-bottom: 8px;
    color: #606266;
}
/* 调整表单项间距 */
:deep(.el-form-item) {
    margin-bottom: 18px;
}
/* 确保textarea的宽度正确 */
:deep(.el-textarea) {
    width: 100%;
}
</style>
src/views/relocatablePersonnel/index.vue
@@ -1,28 +1,199 @@
<template>
    <div>
        <el-button type="primary" @click="toDetail">Primary</el-button>
    <div class="app-container">
        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
            <el-form-item label="拆迁项目" prop="projectName">
                <el-input v-model="queryParams.projectName" placeholder="请输入" clearable style="width: 240px"
                    @keyup.enter.native="handleQuery" />
            </el-form-item>
            <el-form-item label="镇街" prop="street">
                <el-select v-model="queryParams.street" placeholder="请选择" style="width: 240px">
                    <el-option v-for="item in streetOptions" :key="item.dictCode" :label="item.dictLabel"
                        :value="item.dictLabel" />
                </el-select>
            </el-form-item>
            <el-form-item label="所属村(社区)" prop="community">
                <el-input v-model="queryParams.community" placeholder="请输入" clearable style="width: 240px"
                    @keyup.enter.native="handleQuery" />
            </el-form-item>
            <el-form-item label="户主姓名/身份证号" prop="headOrIdCard">
                <el-input v-model="queryParams.headOrIdCard" placeholder="请输入" clearable style="width: 240px"
                    @keyup.enter.native="handleQuery" />
            </el-form-item>
            <el-form-item>
                <el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery">搜索</el-button>
                <el-button icon="el-icon-refresh" size="small" @click="resetQuery">重置</el-button>
            </el-form-item>
        </el-form>
        <el-row :gutter="10" class="mb8">
            <el-col :span="1.5">
                <el-button type="primary" size="small" @click="handleAdd"
                    v-hasPermi="['system:role:add']">新增待安置人员</el-button>
            </el-col>
            <el-col :span="1.5">
                <el-button type="success" size="small" @click="download"
                    v-hasPermi="['system:role:add']">下载导入模板</el-button>
            </el-col>
            <el-col :span="1.5">
                <el-upload :headers="{ ...headers }" action="http://182.140.209.168:8888/api/placement/imports"
                    :show-file-list="false" :on-success="handleImportSuccess" :before-upload="beforeImportUpload">
                    <el-button type="primary" size="small">批量导入</el-button>
                </el-upload>
            </el-col>
            <right-toolbar @queryTable="getList"></right-toolbar>
        </el-row>
        <el-table v-loading="loading" :data="listData">
            <el-table-column label="序号" type="index" width="50" />
            <el-table-column label="项目名称" prop="projectName" :show-overflow-tooltip="true" width="120" />
            <el-table-column label="项目启动时间" prop="startTime" width="150" />
            <el-table-column label="镇街" prop="street" :show-overflow-tooltip="true" width="150" />
            <el-table-column label="村社区" prop="community" width="100" />
            <el-table-column label="组" prop="groupName" width="100" />
            <el-table-column label="户主姓名" prop="householdHead" width="180" />
            <el-table-column label="户主身份证号码" prop="idCard" width="180" />
            <el-table-column label="家庭成员名字" prop="familyName" />
            <el-table-column label="关系" prop="relation" />
            <el-table-column label="人员性质" prop="personType" width="180" />
            <el-table-column label="身份证号码" prop="familyIdCard" width="180" />
            <el-table-column label="年龄" prop="age" />
            <el-table-column label="性别" prop="sex" />
            <el-table-column label="出生年月日" prop="birthday" width="180" />
            <el-table-column label="安置方式" prop="ways" width="180" />
            <el-table-column label="原始拆迁时领取过渡费时间" prop="originCollectionTime" width="180" />
            <el-table-column label="上次过渡费发放时间(起)" prop="lastBeginTime" width="180" />
            <el-table-column label="上次过渡费发放时间(止)" prop="lastEndTime" width="180" />
            <el-table-column label="剩余未安置面积(㎡)" prop="noHouseArea" width="180" />
            <el-table-column label="剩余未安置商铺面积(㎡)" prop="noShopArea" width="180" />
            <el-table-column label="联系电话" prop="mobile" width="180" />
            <el-table-column label="备注" prop="remark" :show-overflow-tooltip="true" width="180" />
            <el-table-column label="安置状态" fixed="right" prop="status">
                <template slot-scope="{row}">
                    <el-tag :type="row.status == 1 ? 'success' : 'danger'">
                        {{ row.status == 1 ? '已安置' : '未安置' }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column label="操作" fixed="right" width="180">
                <template slot-scope="{row}">
                    <el-button size="small" type="text" @click="handleUpdate(row, 'view')"
                        v-hasPermi="['system:role:edit']">详情</el-button>
                    <el-button size="small" type="text" @click="handleUpdate(row, 'edit')"
                        v-hasPermi="['system:role:edit']">修改</el-button>
                    <el-button size="small" type="text" @click="handleDelete(row)"
                        v-hasPermi="['system:role:remove']">删除</el-button>
                </template>
            </el-table-column>
        </el-table>
        <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
            :limit.sync="queryParams.pageSize" @pagination="getList" />
    </div>
</template>
<script>
import { getListData, downloadTemplate, del, getDictData } from "@/api/placement";
import { getToken } from '@/utils/auth'
export default {
    name: "RelocatablePersonnelList",
    components: {},
    props: {},
    name: "RelocatablePersonnel",
    data() {
        return {};
        return {
            // 遮罩层
            loading: true,
            // 角色列表
            listData: [],
            // 总条数
            total: 0,
            // 查询参数
            queryParams: {
                pageNum: 1,
                pageSize: 10,
                headOrIdCard: undefined,
                projectName: undefined,
                street: undefined,
                community: undefined
            },
            headers: {
                'Authorization': 'Bearer ' + getToken(),
            },
            streetOptions: [],
        };
    },
    computed: {},
    watch: {},
    created() { },
    mounted() { },
    created() {
        // 镇(街道)
        getDictData('street').then(response => {
            this.streetOptions = response.data
        })
        this.getList();
    },
    methods: {
        toDetail() {
            this.$router.push({
                path: "detail",
        /** 查询角色列表 */
        getList() {
            this.loading = true;
            getListData(this.queryParams).then(response => {
                this.listData = response.data.records;
                this.total = response.data.total;
                this.loading = false;
            });
        }
    },
        },
        /** 搜索按钮操作 */
        handleQuery() {
            this.queryParams.pageNum = 1;
            this.getList();
        },
        /** 重置按钮操作 */
        resetQuery() {
            this.dateRange = [];
            this.resetForm("queryForm");
            this.handleQuery();
        },
        /** 下载模板 */
        download() {
            downloadTemplate().then(response => {
                const url = window.URL.createObjectURL(new Blob([response.data]));
                const link = document.createElement('a');
                link.href = url;
                link.setAttribute('download', 'template.xlsx');
                document.body.appendChild(link);
                link.click();
                this.$message.success('下载成功');
            });
        },
        /** 新增按钮操作 */
        handleAdd() {
            this.$router.push('add')
        },
        /** 修改按钮操作 */
        handleUpdate(row, type) {
            this.$router.push({ path: type === 'view' ? 'detail' : 'edit', query: { id: row.id, type } })
        },
        /** 删除按钮操作 */
        handleDelete(row) {
            this.$modal.confirm('是否确认删除').then(() => {
                return del({ id: row.id });
            }).then(() => {
                this.getList();
                this.$modal.msgSuccess("删除成功");
            }).catch(() => { });
        },
        handleImportSuccess(response, file, fileList) {
            if (response.code == 200) {
                this.$message.success('导入成功');
            } else {
                this.$message.error(response.msg);
            }
        },
        handleImportError(error, file, fileList) {
            this.$message.error('导入失败');
        },
        beforeImportUpload(file) {
            const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
            if (!isExcel) {
                this.$message.error('请上传xlsx文件');
            }
            return isExcel;
        },
    }
};
</script>
<style scoped></style>
</script>
vue.config.js
@@ -7,7 +7,7 @@
const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
const name = process.env.VUE_APP_TITLE || '崇州自主安置管理后台' // 网页标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口