Bläddra i källkod

wuzhen 更新页面修复

wuzhen 1 år sedan
förälder
incheckning
ff261194e3

+ 10 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/ZsjyGraduateInfo.java

@@ -189,6 +189,16 @@ public class ZsjyGraduateInfo extends TenantEntity implements Serializable {
      */
     private String workCity;
 
+    /**
+     * 工作地点
+     */
+    private String workLocation;
+
+    /**
+     * 完整地址
+     */
+    private String fullAddress;
+
     /**
      * 月薪范围 (1-3000以下 2-3000-5000 3-5000-8000 4-8000-12000 5-12000以上)
      */

+ 10 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/domain/bo/ZsjyGraduateInfoBo.java

@@ -220,6 +220,16 @@ public class ZsjyGraduateInfoBo extends BaseEntity {
      */
     private String workCity;
 
+    /**
+     * 工作地点
+     */
+    private String workLocation;
+
+    /**
+     * 完整地址
+     */
+    private String fullAddress;
+
     /**
      * 月薪范围 (1-3000以下 2-3000-5000 3-5000-8000 4-8000-12000 5-12000以上)
      */

+ 25 - 5
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyGraduateInfoServiceImpl.java

@@ -43,7 +43,10 @@ public class ZsjyGraduateInfoServiceImpl implements IZsjyGraduateInfoService {
      */
     @Override
     public ZsjyGraduateInfoVo queryById(Long id) {
-        return baseMapper.selectVoById(id);
+        ZsjyGraduateInfoBo bo = new ZsjyGraduateInfoBo();
+        bo.setId(id);
+        List<ZsjyGraduateInfoVo> list = baseMapper.selectGraduateInfoVoList(bo);
+        return list.isEmpty() ? null : list.get(0);
     }
 
     /**
@@ -55,8 +58,8 @@ public class ZsjyGraduateInfoServiceImpl implements IZsjyGraduateInfoService {
      */
     @Override
     public TableDataInfo<ZsjyGraduateInfoVo> queryPageList(ZsjyGraduateInfoBo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<ZsjyGraduateInfo> lqw = buildQueryWrapper(bo);
-        Page<ZsjyGraduateInfoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        Page<ZsjyGraduateInfoVo> page = pageQuery.build();
+        IPage<ZsjyGraduateInfoVo> result = baseMapper.selectGraduateInfoPageList(page, bo);
         return TableDataInfo.build(result);
     }
 
@@ -68,8 +71,7 @@ public class ZsjyGraduateInfoServiceImpl implements IZsjyGraduateInfoService {
      */
     @Override
     public List<ZsjyGraduateInfoVo> queryList(ZsjyGraduateInfoBo bo) {
-        LambdaQueryWrapper<ZsjyGraduateInfo> lqw = buildQueryWrapper(bo);
-        return baseMapper.selectVoList(lqw);
+        return baseMapper.selectGraduateInfoVoList(bo);
     }
 
     /**
@@ -211,6 +213,24 @@ public class ZsjyGraduateInfoServiceImpl implements IZsjyGraduateInfoService {
                 throw new RuntimeException("升学状态下,升学院校不能为空");
             }
         }
+
+        // 自动设置组合字段
+        // 设置工作地点(工作省份 + 工作城市)
+        if (StringUtils.isNotBlank(entity.getWorkProvince()) || StringUtils.isNotBlank(entity.getWorkCity())) {
+            String workLocation = StringUtils.defaultString(entity.getWorkProvince(), "") +
+                                StringUtils.defaultString(entity.getWorkCity(), "");
+            entity.setWorkLocation(workLocation);
+        }
+
+        // 设置完整地址(省份 + 城市 + 区县 + 详细地址)
+        if (StringUtils.isNotBlank(entity.getProvince()) || StringUtils.isNotBlank(entity.getCity()) ||
+            StringUtils.isNotBlank(entity.getDistrict()) || StringUtils.isNotBlank(entity.getDetailAddress())) {
+            String fullAddress = StringUtils.defaultString(entity.getProvince(), "") +
+                                StringUtils.defaultString(entity.getCity(), "") +
+                                StringUtils.defaultString(entity.getDistrict(), "") +
+                                StringUtils.defaultString(entity.getDetailAddress(), "");
+            entity.setFullAddress(fullAddress);
+        }
     }
 
     /**

+ 6 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyGraduateInfoMapper.xml

@@ -139,6 +139,9 @@
     <select id="selectGraduateInfoPageList" resultMap="ZsjyGraduateInfoVoResult">
         <include refid="selectZsjyGraduateInfoVo"/>
         <if test="bo != null">
+            <if test="bo.id != null">
+                and g.id = #{bo.id}
+            </if>
             <if test="bo.studentNo != null and bo.studentNo != ''">
                 and g.student_no like concat('%', #{bo.studentNo}, '%')
             </if>
@@ -239,6 +242,9 @@
     <!-- 查询毕业生信息列表(非分页) -->
     <select id="selectGraduateInfoVoList" parameterType="org.dromara.zsjy.domain.bo.ZsjyGraduateInfoBo" resultMap="ZsjyGraduateInfoVoResult">
         <include refid="selectZsjyGraduateInfoVo"/>
+        <if test="id != null">
+            and g.id = #{id}
+        </if>
         <if test="studentNo != null and studentNo != ''">
             and g.student_no like concat('%', #{studentNo}, '%')
         </if>

+ 2 - 1
web/src/api/zsjy/graduateInfo.ts

@@ -1,12 +1,13 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
 import { GraduateInfoVO, GraduateInfoForm, GraduateInfoQuery, GraduateStatisticsVO } from '@/api/zsjy/types';
+import { TableDataInfo } from '@/api/types';
 
 /**
  * 查询毕业生信息列表
  * @param query 查询参数
  */
-export const listGraduateInfo = (query?: GraduateInfoQuery): AxiosPromise<GraduateInfoVO[]> => {
+export const listGraduateInfo = (query?: GraduateInfoQuery): AxiosPromise<TableDataInfo<GraduateInfoVO[]>> => {
   return request({
     url: '/zsjy/graduate/list',
     method: 'get',

+ 2 - 0
web/src/api/zsjy/types.ts

@@ -654,6 +654,7 @@ export interface GraduateInfoForm {
   city?: string;
   district?: string;
   detailAddress?: string;
+  fullAddress?: string;
   postalCode?: string;
   employmentStatus?: string;
   employmentCompany?: string;
@@ -661,6 +662,7 @@ export interface GraduateInfoForm {
   jobPosition?: string;
   workProvince?: string;
   workCity?: string;
+  workLocation?: string;
   salaryRange?: string;
   furtherSchool?: string;
   furtherMajor?: string;

+ 216 - 235
web/src/views/cw/application/index.vue

@@ -100,7 +100,9 @@
               <el-date-picker v-model="queryParams.year" type="year" placeholder="选择年份" value-format="YYYY" style="width: 100%" />
             </el-form-item>
           </el-col>
-          <el-col :span="18">
+        </el-row>
+        <el-row>
+          <el-col :span="24" class="search-btn-container">
             <el-form-item>
               <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
               <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -110,30 +112,31 @@
       </el-form>
     </el-card>
 
-    <!-- 操作按钮区域 -->
-    <el-card class="button-card">
+    <el-card shadow="never" class="button-card table-card">
       <template #header>
-        <div class="card-header">
-          <span class="toolbar-title">项目申报管理</span>
-          <div class="toolbar-actions">
-            <el-button type="primary" icon="Plus" @click="handleAdd" v-hasPermi="['cw:application:add']">新增申报</el-button>
-            <el-button type="success" icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['cw:application:edit']">修改</el-button>
-            <el-button type="danger" icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['cw:application:remove']">删除</el-button>
-            <el-button type="info" icon="Upload" @click="handleSubmit" :disabled="multiple" v-hasPermi="['cw:application:submit']"
-              >提交审批</el-button
-            >
-            <el-button type="warning" icon="Download" @click="handleExport" v-hasPermi="['cw:application:export']">导出</el-button>
-            <right-toolbar :showSearch="showSearch" @update:showSearch="showSearch = $event" @queryTable="getList"></right-toolbar>
-          </div>
-        </div>
+        <el-row ref="toolbarRef" :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['cw:application:add']">新增申报</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['cw:application:edit']">修改</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['cw:application:remove']">删除</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="info" plain icon="Upload" @click="handleSubmit" :disabled="multiple" v-hasPermi="['cw:application:submit']">提交审批</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['cw:application:export']">导出</el-button>
+          </el-col>
+          <right-toolbar :showSearch="showSearch" @update:showSearch="showSearch = $event" @queryTable="getList"></right-toolbar>
+        </el-row>
       </template>
-    </el-card>
 
-    <!-- 数据表格区域 -->
-    <el-card class="table-card">
       <div class="table-container">
-        <el-table v-loading="loading" :data="applicationList" @selection-change="handleSelectionChange" class="scroll-table">
-          <el-table-column type="selection" width="55" align="center" />
+        <el-table v-loading="loading" border :data="applicationList" @selection-change="handleSelectionChange" style="width: 100%" :scroll-x="true" class="scroll-table">
+          <el-table-column type="selection" width="55" align="center" fixed="left" />
           <el-table-column label="申报编号" align="center" prop="applicationNo" min-width="140" />
           <el-table-column label="项目名称" align="center" prop="projectName" min-width="180" show-overflow-tooltip />
           <el-table-column label="项目负责人" align="center" prop="principal" min-width="100" />
@@ -156,41 +159,38 @@
               <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
             </template>
           </el-table-column>
-          <el-table-column label="操作" align="center" width="280" class-name="small-padding fixed-width">
+          <el-table-column label="操作" align="center" width="280" fixed="right" class-name="small-padding fixed-width">
             <template #default="scope">
               <div class="action-buttons">
                 <el-tooltip content="查看详情" placement="top">
-                  <el-button type="primary" icon="View" circle size="small" @click="handleView(scope.row)" v-hasPermi="['cw:application:query']" />
+                  <el-button link type="info" icon="View" @click="handleView(scope.row)" v-hasPermi="['cw:application:query']" />
                 </el-tooltip>
                 <el-tooltip content="编辑" placement="top" v-if="['draft', 'returned'].includes(scope.row.approvalStatus)">
-                  <el-button type="success" icon="Edit" circle size="small" @click="handleUpdate(scope.row)" v-hasPermi="['cw:application:edit']" />
+                  <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['cw:application:edit']" />
                 </el-tooltip>
                 <el-tooltip content="提交审批" placement="top" v-if="['draft', 'returned'].includes(scope.row.approvalStatus)">
                   <el-button
+                    link
                     type="warning"
                     icon="Upload"
-                    circle
-                    size="small"
                     @click="handleSubmit(scope.row)"
                     v-hasPermi="['cw:application:submit']"
                   />
                 </el-tooltip>
                 <el-tooltip content="撤回" placement="top" v-if="scope.row.approvalStatus === 'submitted'">
                   <el-button
+                    link
                     type="info"
                     icon="RefreshLeft"
-                    circle
-                    size="small"
                     @click="handleWithdraw(scope.row)"
                     v-hasPermi="['cw:application:withdraw']"
                   />
                 </el-tooltip>
                 <el-tooltip content="删除" placement="top" v-if="['draft', 'cancelled', 'returned'].includes(scope.row.approvalStatus)">
                   <el-button
+                    link
                     type="danger"
                     icon="Delete"
-                    circle
-                    size="small"
                     @click="handleDelete(scope.row)"
                     v-hasPermi="['cw:application:remove']"
                   />
@@ -237,7 +237,7 @@
   </div>
 </template>
 
-<script>
+<script lang="ts">
 import {
   listProjectApplication,
   getProjectApplication,
@@ -553,252 +553,238 @@ export default {
 </script>
 
 <style scoped lang="scss">
-/* 继承后勤管理模块的样式风格 */
+/* 按照满意度调查页面样式重写 */
 .page-container {
+  background-color: #f5f5f5;
+  min-height: calc(100vh - 84px);
   padding: 8px;
+}
 
-  /* 统计卡片样式 */
-  .stats-row {
-    margin-bottom: 20px;
-  }
-
-  .stat-card {
-    border-radius: 12px;
-    transition: all 0.3s ease;
-    height: 90px;
-    cursor: pointer;
-
-    &:hover {
-      transform: translateY(-2px);
-      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
-    }
-
-    .stat-content {
-      display: flex;
-      align-items: center;
-      padding: 5px 16px;
-      height: 100%;
-      box-sizing: border-box;
-
-      .stat-icon {
-        font-size: 28px;
-        margin-right: 15px;
-        opacity: 0.9;
-      }
-
-      .stat-info {
-        flex: 1;
+/* 统计卡片样式 */
+.stats-row {
+  margin-bottom: 20px;
+}
 
-        .stat-value {
-          font-size: 24px;
-          font-weight: bold;
-          line-height: 1;
-          margin-bottom: 4px;
-        }
+.stat-card {
+  border-radius: 12px;
+  transition: all 0.3s ease;
+  height: 90px;
+  cursor: pointer;
 
-        .stat-label {
-          font-size: 14px;
-          opacity: 0.8;
-          line-height: 1;
-        }
-      }
-    }
+  &:hover {
+    transform: translateY(-2px);
+    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
+  }
 
-    &.stat-card-primary {
-      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-      color: white;
+  .stat-content {
+    display: flex;
+    align-items: center;
+    padding: 5px 16px;
+    height: 100%;
+    box-sizing: border-box;
+
+    .stat-icon {
+      font-size: 28px;
+      margin-right: 15px;
+      opacity: 0.9;
     }
 
-    &.stat-card-success {
-      background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
-      color: white;
-    }
+    .stat-info {
+      flex: 1;
 
-    &.stat-card-warning {
-      background: linear-gradient(135deg, #ff9a56 0%, #ffad56 100%);
-      color: white;
-    }
+      .stat-value {
+        font-size: 24px;
+        font-weight: bold;
+        line-height: 1;
+        margin-bottom: 4px;
+      }
 
-    &.stat-card-info {
-      background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
-      color: #333;
+      .stat-label {
+        font-size: 14px;
+        opacity: 0.8;
+        line-height: 1;
+      }
     }
   }
 
-  /* 表格卡片布局 - 参考后勤管理功能 */
-  .table-card {
-    margin-top: 0;
+  &.stat-card-primary {
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    color: white;
   }
 
-  .table-card :deep(.el-card__body) {
-    padding: 0px 20px 20px 20px !important;
+  &.stat-card-success {
+    background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+    color: white;
   }
 
-  /* 移除按钮栏底部边框 */
-  .button-card :deep(.el-card__header) {
-    border-bottom: none !important;
+  &.stat-card-warning {
+    background: linear-gradient(135deg, #ff9a56 0%, #ffad56 100%);
+    color: white;
   }
 
-  .card-header {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
+  &.stat-card-info {
+    background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
+    color: #333;
+  }
+}
 
-    .toolbar-title {
-      font-size: 18px;
-      font-weight: 600;
-      color: #1e293b;
-      display: flex;
-      align-items: center;
-
-      &::before {
-        content: '';
-        width: 4px;
-        height: 20px;
-        background: linear-gradient(135deg, rgb(93, 135, 255), rgb(73, 190, 255));
-        border-radius: 2px;
-        margin-right: 12px;
-      }
-    }
+/* 搜索按钮居中样式 */
+.search-btn-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 10px;
 
-    .toolbar-actions {
-      display: flex;
-      gap: 12px;
-      align-items: center;
-    }
+  .el-form-item {
+    margin-bottom: 0 !important;
   }
+}
 
-  /* 表格主体 */
-  .table-container {
-    width: 100%;
-    margin-bottom: 0;
-  }
+/* 卡片样式 */
+:deep(.el-card) {
+  border: 1px solid #e4e7ed;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
+}
 
-  /* 表格样式 - 参考后勤管理功能 */
-  .scroll-table {
-    width: 100%;
+/* 表格卡片头部样式 */
+.table-card :deep(.el-card__header) {
+  background-color: #fafafa;
+  border-bottom: 1px solid #ebeef5;
+  padding: 18px 20px;
+}
 
-    :deep(.el-table__header-wrapper) {
-      .el-table__header {
-        th {
-          background-color: #f8f9fa;
-          color: #333;
-          font-weight: 600;
-        }
+/* 表格卡片内容样式 */
+.table-card :deep(.el-card__body) {
+  padding: 0px 20px 20px 20px !important;
+}
+
+/* 表格样式 */
+.scroll-table {
+  width: 100%;
+
+  :deep(.el-table__header-wrapper) {
+    .el-table__header {
+      th {
+        background-color: #fafafa;
+        color: #333;
+        font-weight: 600;
       }
     }
+  }
 
-    :deep(.el-table__body-wrapper) {
-      .el-table__row {
-        &:hover {
-          background-color: #f5f7fa;
-        }
+  :deep(.el-table__body-wrapper) {
+    .el-table__row {
+      &:hover {
+        background-color: #f5f7fa;
       }
     }
   }
+}
 
-  /* 表格横向滚动条样式优化 - 参考后勤管理功能 */
-  .scroll-table :deep(.el-table__body-wrapper) {
-    overflow-x: auto !important;
-    overflow-y: auto;
-    scrollbar-width: thin;
-    scrollbar-color: #409eff #f0f0f0;
-  }
+/* 表格横向滚动条样式优化 */
+.scroll-table :deep(.el-table__body-wrapper) {
+  overflow-x: auto !important;
+  overflow-y: auto;
+  scrollbar-width: thin;
+  scrollbar-color: #409eff #f0f0f0;
+}
 
-  .scroll-table :deep(.el-table__header-wrapper) {
-    overflow-x: hidden;
-  }
+.scroll-table :deep(.el-table__header-wrapper) {
+  overflow-x: hidden;
+}
 
-  /* Webkit 浏览器的横向滚动条样式 */
-  .scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar {
-    height: 12px !important;
-    width: 12px !important;
-  }
+/* Webkit 浏览器的横向滚动条样式 */
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar {
+  height: 12px !important;
+  width: 12px !important;
+}
 
-  .scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-track {
-    background: #f0f0f0 !important;
-    border-radius: 6px !important;
-    border: 1px solid #e4e7ed !important;
-  }
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-track {
+  background: #f0f0f0 !important;
+  border-radius: 6px !important;
+  border: 1px solid #e4e7ed !important;
+}
 
-  .scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb {
-    background: #409eff !important;
-    border-radius: 6px !important;
-    border: 2px solid #f0f0f0 !important;
-    min-height: 20px !important;
-  }
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb {
+  background: #409eff !important;
+  border-radius: 6px !important;
+  border: 2px solid #f0f0f0 !important;
+  min-height: 20px !important;
+}
 
-  .scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb:hover {
-    background: #337ecc !important;
-  }
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb:hover {
+  background: #337ecc !important;
+}
 
-  .scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb:active {
-    background: #2b6cb0 !important;
-  }
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb:active {
+  background: #2b6cb0 !important;
+}
 
-  .scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-corner {
-    background: #f0f0f0;
-  }
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-corner {
+  background: #f0f0f0;
+}
 
-  /* 固定列样式优化 */
-  .scroll-table :deep(.el-table__fixed-right) {
-    box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
-  }
+/* 固定列样式优化 */
+.scroll-table :deep(.el-table__fixed-right) {
+  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
+}
 
-  .scroll-table :deep(.el-table__fixed-left) {
-    box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
-  }
+.scroll-table :deep(.el-table__fixed-left) {
+  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
+}
 
-  /* 确保固定列在滚动时有正确的背景色 */
-  .scroll-table :deep(.el-table__fixed-right .el-table__cell),
-  .scroll-table :deep(.el-table__fixed-left .el-table__cell) {
-    background-color: #fff;
-  }
+/* 确保固定列在滚动时有正确的背景色 */
+.scroll-table :deep(.el-table__fixed-right .el-table__cell),
+.scroll-table :deep(.el-table__fixed-left .el-table__cell) {
+  background-color: #fff;
+}
 
-  /* 表格行悬停效果在固定列上的同步 */
-  .scroll-table :deep(.el-table__row:hover .el-table__cell) {
-    background-color: #f5f7fa !important;
-  }
+/* 表格行悬停效果在固定列上的同步 */
+.scroll-table :deep(.el-table__row:hover .el-table__cell) {
+  background-color: #f5f7fa !important;
+}
 
-  /* 操作按钮样式 */
-  .action-buttons {
-    display: flex;
-    gap: 8px;
-    justify-content: center;
-    align-items: center;
-    white-space: nowrap;
-
-    .el-button {
-      width: 27px !important;
-      height: 27px !important;
-      padding: 0 !important;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-    }
-  }
+/* 操作按钮样式 */
+.action-buttons {
+  display: flex;
+  gap: 4px;
+  justify-content: center;
+  align-items: center;
+  white-space: nowrap;
+}
 
-  /* 金额文本样式 */
-  .amount-text {
-    font-weight: 600;
-    color: #e74c3c;
-  }
+/* 金额文本样式 */
+.amount-text {
+  font-weight: 600;
+  color: #e74c3c;
+}
 
-  /* 分页容器样式 - 参考后勤管理功能 */
-  .pagination-container {
-    display: flex;
-    justify-content: flex-end;
-    padding: 16px 20px 0 0 !important;
-    background-color: #fff;
-    margin-top: 0px !important;
-  }
+/* 分页容器样式 */
+.pagination-container {
+  display: flex;
+  justify-content: flex-end;
+  padding: 16px 20px 0 0 !important;
+  background-color: #fff;
+  margin-top: 0px !important;
+}
 
-  /* 对话框样式 */
-  .dialog-footer {
-    display: flex;
-    justify-content: flex-end;
-    gap: 10px;
-  }
+/* 对话框样式 */
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+/* 输入框样式 */
+:deep(.el-input .el-input__wrapper) {
+  border-radius: 4px;
+}
+
+:deep(.el-select .el-input__wrapper) {
+  border-radius: 4px;
+}
+
+:deep(.el-date-editor .el-input__wrapper) {
+  border-radius: 4px;
 }
 
 /* 响应式设计 */
@@ -811,11 +797,6 @@ export default {
         margin-bottom: 10px;
       }
     }
-
-    .toolbar-actions {
-      flex-direction: column;
-      gap: 8px !important;
-    }
   }
 }
 </style>

+ 311 - 67
web/src/views/cw/approvalRecord/index.vue

@@ -1,68 +1,106 @@
 <template>
-  <div class="app-container">
-    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
-      <el-form-item label="申报编号" prop="applicationNo">
-        <el-input v-model="queryParams.applicationNo" placeholder="请输入申报编号" clearable style="width: 200px" @keyup.enter="handleQuery" />
-      </el-form-item>
-      <el-form-item label="项目名称" prop="projectName">
-        <el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable style="width: 200px" @keyup.enter="handleQuery" />
-      </el-form-item>
-      <el-form-item label="申报人" prop="applicantName">
-        <el-input v-model="queryParams.applicantName" placeholder="请输入申报人" clearable style="width: 200px" @keyup.enter="handleQuery" />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
-
-    <!-- 快速操作按钮 -->
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
-        <el-button type="primary" plain icon="Check" @click="showPendingApprovals">待我审批</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="success" plain icon="CircleCheck" @click="showMyApprovals">我已审批</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="info" plain icon="Download" @click="handleExport">导出</el-button>
-      </el-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-    </el-row>
-
-    <!-- 数据表格 -->
-    <el-table v-loading="loading" :data="approvalRecordList" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="申报编号" align="center" prop="applicationNo" />
-      <el-table-column label="项目名称" align="center" prop="projectName" />
-      <el-table-column label="申报人" align="center" prop="applicantName" />
-      <el-table-column label="部门" align="center" prop="deptName" />
-      <el-table-column label="审批节点" align="center" prop="nodeName" />
-      <el-table-column label="审批状态" align="center" prop="nodeStatus">
-        <template #default="scope">
-          <dict-tag :options="cw_approval_status" :value="scope.row.nodeStatus" />
-        </template>
-      </el-table-column>
-      <el-table-column label="审批人" align="center" prop="approverName" />
-      <el-table-column label="审批意见" align="center" prop="approveOpinion" />
-      <el-table-column label="审批时间" align="center" prop="endTime" width="180">
-        <template #default="scope">
-          <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" align="center" width="160">
-        <template #default="scope">
-          <el-tooltip content="查看详情" placement="top">
-            <el-button link type="info" icon="View" @click="handleDetail(scope.row)"></el-button>
-          </el-tooltip>
-          <el-tooltip content="审批" placement="top" v-if="scope.row.nodeStatus === 'waiting'">
-            <el-button link type="success" icon="Check" @click="handleApprove(scope.row)"></el-button>
-          </el-tooltip>
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+  <div class="p-2 page-container">
+    <transition :enter-active-class="animate.searchAnimate.enter" :leave-active-class="animate.searchAnimate.leave">
+      <div ref="searchRef" v-show="showSearch" class="mb-[10px]">
+        <el-card shadow="hover">
+          <el-form ref="queryFormRef" :model="queryParams" label-width="100px">
+            <el-row :gutter="20">
+              <el-col :span="6">
+                <el-form-item label="申报编号" prop="applicationNo">
+                  <el-input v-model="queryParams.applicationNo" placeholder="请输入申报编号" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="项目名称" prop="projectName">
+                  <el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="申报人" prop="applicantName">
+                  <el-input v-model="queryParams.applicantName" placeholder="请输入申报人" clearable @keyup.enter="handleQuery" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="审批状态" prop="nodeStatus">
+                  <el-select v-model="queryParams.nodeStatus" placeholder="请选择审批状态" clearable>
+                    <el-option v-for="dict in cw_approval_status" :key="dict.value" :label="dict.label" :value="dict.value" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col :span="24" class="search-btn-container">
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+                  <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </el-form>
+        </el-card>
+      </div>
+    </transition>
+
+    <el-card shadow="never" class="button-card table-card">
+      <template #header>
+        <el-row ref="toolbarRef" :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" plain icon="Check" @click="showPendingApprovals">待我审批</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="success" plain icon="CircleCheck" @click="showMyApprovals">我已审批</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="info" plain icon="Download" @click="handleExport">导出</el-button>
+          </el-col>
+          <right-toolbar :showSearch="showSearch" @update:showSearch="showSearch = $event" @queryTable="getList"></right-toolbar>
+        </el-row>
+      </template>
+
+      <div class="table-container">
+        <el-table
+          v-loading="loading"
+          border
+          :data="approvalRecordList"
+          @selection-change="handleSelectionChange"
+          style="width: 100%"
+          :scroll-x="true"
+          class="scroll-table"
+        >
+          <el-table-column type="selection" width="55" align="center" fixed="left" />
+          <el-table-column label="申报编号" align="center" prop="applicationNo" width="140" show-overflow-tooltip />
+          <el-table-column label="项目名称" align="center" prop="projectName" min-width="200" show-overflow-tooltip />
+          <el-table-column label="申报人" align="center" prop="applicantName" width="120" />
+          <el-table-column label="部门" align="center" prop="deptName" width="150" />
+          <el-table-column label="审批节点" align="center" prop="nodeName" width="120" />
+          <el-table-column label="审批状态" align="center" prop="nodeStatus" width="120">
+            <template #default="scope">
+              <dict-tag :options="cw_approval_status" :value="scope.row.nodeStatus" />
+            </template>
+          </el-table-column>
+          <el-table-column label="审批人" align="center" prop="approverName" width="120" />
+          <el-table-column label="审批意见" align="center" prop="approveOpinion" min-width="200" show-overflow-tooltip />
+          <el-table-column label="审批时间" align="center" prop="endTime" width="180">
+            <template #default="scope">
+              <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="280" fixed="right" class-name="small-padding fixed-width">
+            <template #default="scope">
+              <el-tooltip content="查看详情" placement="top">
+                <el-button link type="info" icon="View" @click="handleDetail(scope.row)" v-hasPermi="['cw:approval:query']"></el-button>
+              </el-tooltip>
+              <el-tooltip content="审批" placement="top" v-if="scope.row.nodeStatus === 'waiting'">
+                <el-button link type="success" icon="Check" @click="handleApprove(scope.row)" v-hasPermi="['cw:approval:process']"></el-button>
+              </el-tooltip>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pagination-container">
+        <pagination v-show="total > 0" :total="total" :page="queryParams.pageNum" :limit="queryParams.pageSize" @update:page="queryParams.pageNum = $event" @update:limit="queryParams.pageSize = $event" @pagination="getList" />
+      </div>
+    </el-card>
 
     <!-- 审批对话框 -->
     <el-dialog title="审批处理" v-model="approvalOpen" width="500px" append-to-body>
@@ -97,7 +135,7 @@
   </div>
 </template>
 
-<script>
+<script lang="ts">
 import { listApprovalRecord, exportApprovalRecord, approveApplication, getMyApprovals, getDepartmentApprovals } from '@/api/cw/approvalRecord';
 import { parseTime } from '@/utils/ruoyi';
 import ApplicationSummary from '../application/summary.vue';
@@ -129,6 +167,13 @@ export default {
       // 查看详情弹出层
       viewOpen: false,
       currentId: null,
+      // 动画配置
+      animate: {
+        searchAnimate: {
+          enter: 'animate__animated animate__fadeIn',
+          leave: 'animate__animated animate__fadeOut'
+        }
+      },
       // 字典数据
       cw_approval_status: [],
       // 查询参数
@@ -138,6 +183,7 @@ export default {
         applicationNo: '',
         projectName: '',
         applicantName: '',
+        nodeStatus: '',
         deptId: 'current'
       },
       // 审批表单
@@ -200,7 +246,7 @@ export default {
     },
     /** 重置按钮操作 */
     resetQuery() {
-      this.resetForm('queryRef');
+      this.resetForm('queryFormRef');
       this.handleQuery();
     },
     // 多选框选中数据
@@ -308,4 +354,202 @@ export default {
 };
 </script>
 
-<style scoped></style>
+<style scoped>
+/* 页面容器样式 */
+.page-container {
+  padding: 8px;
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
+
+/* 搜索按钮容器 - 右对齐 */
+.search-btn-container {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.search-btn-container .el-form-item {
+  margin-bottom: 0;
+}
+
+/* 表格卡片布局 */
+.table-card {
+  margin-top: 0;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
+}
+
+.table-card :deep(.el-card__body) {
+  padding: 0px 20px 20px 20px !important;
+}
+
+/* 表格容器 - 支持横向滚动 */
+.table-container {
+  width: 100%;
+  margin-bottom: 0;
+}
+
+/* 横向滚动表格样式 */
+.scroll-table {
+  width: 100%;
+}
+
+/* 表格横向滚动条样式优化 */
+.scroll-table :deep(.el-table__body-wrapper) {
+  overflow-x: auto !important; /* 自动显示横向滚动条 */
+  overflow-y: auto;
+}
+
+.scroll-table :deep(.el-table__header-wrapper) {
+  overflow-x: hidden;
+}
+
+/* 强制显示表格横向滚动条 - 适用于所有浏览器 */
+.scroll-table :deep(.el-table__body-wrapper) {
+  scrollbar-width: thin; /* Firefox */
+  scrollbar-color: #409eff #f0f0f0; /* Firefox - thumb track */
+}
+
+/* Webkit 浏览器的横向滚动条样式 */
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar {
+  height: 12px !important; /* 增加滚动条高度 */
+  width: 12px !important;
+}
+
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-track {
+  background: #f0f0f0 !important;
+  border-radius: 6px !important;
+  border: 1px solid #e4e7ed !important; /* 添加边框使其更明显 */
+}
+
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb {
+  background: #409eff !important; /* 使用主题色,更明显 */
+  border-radius: 6px !important;
+  border: 2px solid #f0f0f0 !important; /* 添加白色边框 */
+  min-height: 20px !important; /* 确保最小高度 */
+}
+
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb:hover {
+  background: #337ecc !important; /* 悬停时更深的蓝色 */
+}
+
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-thumb:active {
+  background: #2b6cb0 !important; /* 点击时的颜色 */
+}
+
+/* 确保滚动条始终可见的额外设置 */
+.scroll-table :deep(.el-table__body-wrapper)::-webkit-scrollbar-corner {
+  background: #f0f0f0;
+}
+
+/* 固定列样式优化 */
+.scroll-table :deep(.el-table__fixed-right) {
+  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
+}
+
+.scroll-table :deep(.el-table__fixed-left) {
+  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
+}
+
+/* 确保固定列在滚动时有正确的背景色 */
+.scroll-table :deep(.el-table__fixed-right .el-table__cell),
+.scroll-table :deep(.el-table__fixed-left .el-table__cell) {
+  background-color: #fff;
+}
+
+/* 表格行悬停效果在固定列上的同步 */
+.scroll-table :deep(.el-table__row:hover .el-table__cell) {
+  background-color: #f5f7fa !important;
+}
+
+/* 分页容器样式 */
+.pagination-container {
+  display: flex;
+  justify-content: flex-end;
+  padding: 16px 20px 0 0 !important;
+  background-color: #fff;
+  margin-top: 0px !important;
+}
+
+/* 移除按钮栏底部边框 */
+.button-card :deep(.el-card__header) {
+  border-bottom: none !important;
+  background-color: #fafafa;
+}
+
+/* 表格头部样式 */
+.scroll-table :deep(.el-table__header) {
+  th {
+    background: #fafafa !important;
+    color: #303133;
+    font-weight: 600;
+  }
+}
+
+/* 表格边框样式 */
+.scroll-table :deep(.el-table) {
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+/* 表格行样式 */
+.scroll-table :deep(.el-table__row) {
+  border-bottom: 1px solid #f0f2f5;
+}
+
+.scroll-table :deep(.el-table__row:hover) {
+  background-color: #f5f7fa !important;
+}
+
+/* 操作列按钮样式 */
+.scroll-table :deep(.el-button--link) {
+  padding: 4px 8px;
+  font-size: 14px;
+}
+
+/* Dialog footer样式 */
+.dialog-footer {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  gap: 12px;
+  width: 100%;
+}
+
+/* 动画效果 */
+.animate__animated {
+  animation-duration: 0.3s;
+}
+
+.animate__fadeIn {
+  animation-name: fadeIn;
+}
+
+.animate__fadeOut {
+  animation-name: fadeOut;
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+    transform: translateY(-10px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+@keyframes fadeOut {
+  from {
+    opacity: 1;
+    transform: translateY(0);
+  }
+  to {
+    opacity: 0;
+    transform: translateY(-10px);
+  }
+}
+</style>

+ 31 - 4
web/src/views/cw/financeApproval/index.vue

@@ -21,7 +21,9 @@
                   <el-input v-model="queryParams.applicantName" placeholder="请输入申报人姓名" clearable @keyup.enter="handleQuery" />
                 </el-form-item>
               </el-col>
-              <el-col :span="6">
+            </el-row>
+            <el-row>
+              <el-col :span="24" class="search-btn-container">
                 <el-form-item>
                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
                   <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -81,7 +83,7 @@
           <el-col :span="1.5">
             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['cw:approval:export']">导出</el-button>
           </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
+          <right-toolbar v-model="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
         </el-row>
       </template>
 
@@ -125,7 +127,7 @@
         </el-table-column>
       </el-table>
 
-      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+      <pagination v-show="total > 0" :total="total" :page="queryParams.pageNum" :limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
 
     <!-- 项目详情对话框 -->
@@ -227,7 +229,7 @@
   </div>
 </template>
 
-<script>
+<script lang="ts">
 import {
   listApprovalRecord,
   exportApprovalRecord,
@@ -707,4 +709,29 @@ export default {
 .animate__animated {
   animation-duration: 0.3s;
 }
+
+/* 搜索按钮容器样式 */
+.search-btn-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 10px;
+
+  .el-form-item {
+    margin-bottom: 0 !important;
+  }
+}
+
+/* 表格卡片布局 */
+.table-card {
+  margin-top: 0;
+}
+
+.table-card :deep(.el-card__body) {
+  padding: 0px 20px 20px 20px !important;
+}
+
+/* 移除按钮栏底部边框 */
+.button-card :deep(.el-card__header) {
+  border-bottom: none !important;
+}
 </style>

+ 31 - 4
web/src/views/cw/leaderApproval/index.vue

@@ -21,7 +21,9 @@
                   <el-input v-model="queryParams.applicantName" placeholder="请输入申报人姓名" clearable @keyup.enter="handleQuery" />
                 </el-form-item>
               </el-col>
-              <el-col :span="6">
+            </el-row>
+            <el-row>
+              <el-col :span="24" class="search-btn-container">
                 <el-form-item>
                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
                   <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -81,7 +83,7 @@
           <el-col :span="1.5">
             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['cw:approval:export']">导出</el-button>
           </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
+          <right-toolbar v-model="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
         </el-row>
       </template>
 
@@ -125,7 +127,7 @@
         </el-table-column>
       </el-table>
 
-      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+      <pagination v-show="total > 0" :total="total" :page="queryParams.pageNum" :limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
 
     <!-- 项目详情对话框 -->
@@ -202,7 +204,7 @@
   </div>
 </template>
 
-<script>
+<script lang="ts">
 import {
   getPendingApprovals,
   getApprovalHistory,
@@ -615,4 +617,29 @@ export default {
 .animate__animated {
   animation-duration: 0.3s;
 }
+
+/* 搜索按钮容器样式 */
+.search-btn-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 10px;
+
+  .el-form-item {
+    margin-bottom: 0 !important;
+  }
+}
+
+/* 表格卡片布局 */
+.table-card {
+  margin-top: 0;
+}
+
+.table-card :deep(.el-card__body) {
+  padding: 0px 20px 20px 20px !important;
+}
+
+/* 移除按钮栏底部边框 */
+.button-card :deep(.el-card__header) {
+  border-bottom: none !important;
+}
 </style>

+ 9 - 0
web/src/views/zsjy/enterprise/index.vue

@@ -504,4 +504,13 @@ onMounted(() => {
     color: #303133;
   }
 }
+.search-btn-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 10px;
+
+  .el-form-item {
+    margin-bottom: 0 !important;
+  }
+}
 </style>

+ 82 - 183
web/src/views/zsjy/graduateInfo/index.vue

@@ -65,13 +65,7 @@
 
             <!-- 第三行:搜索条件 + 操作按钮 -->
             <el-row :gutter="20">
-              <el-col :span="6">
-                <el-form-item label="审核状态" prop="auditStatus">
-                  <el-select v-model="queryParams.auditStatus" placeholder="请选择审核状态" clearable style="width: 100%">
-                    <el-option v-for="dict in zsjy_graduate_audit_status" :key="dict.value" :label="dict.label" :value="dict.value" />
-                  </el-select>
-                </el-form-item>
-              </el-col>
+              <!-- 审核状态搜索条件已隐藏 -->
               <el-col :span="6">
                 <el-form-item label="手机号码" prop="phoneNumber">
                   <el-input v-model="queryParams.phoneNumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
@@ -184,19 +178,7 @@
             </div>
           </el-card>
         </el-col>
-        <el-col :span="3">
-          <el-card shadow="hover" class="stat-card stat-card-warning">
-            <div class="stat-content">
-              <div class="stat-icon">
-                <el-icon><DocumentChecked /></el-icon>
-              </div>
-              <div class="stat-info">
-                <div class="stat-value">{{ pendingAuditCount || 0 }}</div>
-                <div class="stat-label">待审核</div>
-              </div>
-            </div>
-          </el-card>
-        </el-col>
+        <!-- 待审核统计卡片已隐藏 -->
         <el-col :span="3">
           <el-card shadow="hover" class="stat-card stat-card-primary" @click="handleStatistics">
             <div class="stat-content">
@@ -229,12 +211,7 @@
           <el-col :span="1.5">
             <el-button icon="Download" @click="handleExport" v-hasPermi="['zsjy:graduate:export']">导出</el-button>
           </el-col>
-          <el-col :span="1.5">
-            <el-button icon="Check" :disabled="multiple" @click="handleBatchAudit('1')" v-hasPermi="['zsjy:graduate:audit']">批量通过</el-button>
-          </el-col>
-          <el-col :span="1.5">
-            <el-button icon="Close" :disabled="multiple" @click="handleBatchAudit('2')" v-hasPermi="['zsjy:graduate:audit']">批量拒绝</el-button>
-          </el-col>
+          <!-- 批量审核按钮已隐藏 -->
           <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
         </el-row>
       </template>
@@ -274,19 +251,8 @@
           <el-table-column label="工作地点" align="center" prop="workLocation" width="140" show-overflow-tooltip />
           <el-table-column label="薪资范围" align="center" prop="salaryRangeName" width="120" />
           <el-table-column label="升学院校" align="center" prop="furtherSchool" width="160" show-overflow-tooltip />
-          <el-table-column label="审核状态" align="center" prop="auditStatus" width="100">
-            <template #default="scope">
-              <el-tag :type="getAuditStatusTagType(scope.row.auditStatus)" size="small">
-                {{ scope.row.auditStatusName }}
-              </el-tag>
-            </template>
-          </el-table-column>
-          <el-table-column label="审核时间" align="center" prop="auditTime" width="160">
-            <template #default="scope">
-              <span v-if="scope.row.auditTime">{{ proxy.parseTime(scope.row.auditTime, '{y}-{m}-{d} {h}:{i}') }}</span>
-              <span v-else>-</span>
-            </template>
-          </el-table-column>
+          <!-- 审核状态列已隐藏 -->
+          <!-- 审核时间列已隐藏 -->
           <el-table-column label="创建时间" align="center" prop="createTime" width="160">
             <template #default="scope">
               <span>{{ proxy.parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
@@ -300,9 +266,7 @@
               <el-tooltip content="编辑" placement="top">
                 <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['zsjy:graduate:edit']"></el-button>
               </el-tooltip>
-              <el-tooltip content="审核" placement="top" v-if="scope.row.auditStatus === '0'">
-                <el-button link type="success" icon="Check" @click="handleAudit(scope.row)" v-hasPermi="['zsjy:graduate:audit']"></el-button>
-              </el-tooltip>
+              <!-- 审核按钮已隐藏 -->
               <el-tooltip content="删除" placement="top">
                 <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['zsjy:graduate:remove']"></el-button>
               </el-tooltip>
@@ -483,39 +447,20 @@
           </div>
         </el-card>
 
-        <!-- 审核信息 -->
-        <el-card class="detail-card" shadow="never">
+        <!-- 审核信息已隐藏 -->
+        <!-- 备注信息 -->
+        <el-card class="detail-card" shadow="never" v-if="detailData.remark">
           <template #header>
             <div class="card-header">
               <div class="card-title">
-                <el-icon><DocumentChecked /></el-icon>
-                <span>审核信息</span>
+                <el-icon><Document /></el-icon>
+                <span>备注信息</span>
               </div>
             </div>
           </template>
           <div class="detail-grid">
-            <div class="detail-item">
-              <label>审核状态:</label>
-              <div class="detail-value">
-                <el-tag :type="getAuditStatusTagType(detailData.auditStatus)" size="small">
-                  {{ detailData.auditStatusName }}
-                </el-tag>
-              </div>
-            </div>
-            <div class="detail-item">
-              <label>审核人:</label>
-              <div class="detail-value">{{ detailData.auditByName || '-' }}</div>
-            </div>
-            <div class="detail-item">
-              <label>审核时间:</label>
-              <div class="detail-value">{{ detailData.auditTime ? proxy.parseTime(detailData.auditTime, '{y}-{m}-{d} {h}:{i}:{s}') : '-' }}</div>
-            </div>
             <div class="detail-item full-width">
-              <label>审核意见:</label>
-              <div class="detail-value description">{{ detailData.auditRemark || '-' }}</div>
-            </div>
-            <div class="detail-item full-width">
-              <label>备注信息:</label>
+              <label>备注:</label>
               <div class="detail-value description">{{ detailData.remark || '-' }}</div>
             </div>
           </div>
@@ -523,26 +468,7 @@
       </div>
     </el-dialog>
 
-    <!-- 审核弹窗 -->
-    <el-dialog title="审核毕业生信息" v-model="auditVisible" width="500px" :before-close="closeAudit">
-      <el-form ref="auditFormRef" :model="auditForm" label-width="100px">
-        <el-form-item label="审核状态" prop="auditStatus" required>
-          <el-radio-group v-model="auditForm.auditStatus">
-            <el-radio value="1">通过</el-radio>
-            <el-radio value="2">拒绝</el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="审核意见" prop="auditRemark">
-          <el-input v-model="auditForm.auditRemark" type="textarea" :rows="4" placeholder="请输入审核意见(选填)" maxlength="500" show-word-limit />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="closeAudit">取消</el-button>
-          <el-button type="primary" @click="submitAudit">确定</el-button>
-        </div>
-      </template>
-    </el-dialog>
+    <!-- 审核弹窗已隐藏 -->
   </div>
 </template>
 
@@ -553,18 +479,17 @@ import {
   getGraduateInfo,
   delGraduateInfo,
   exportGraduateInfo,
-  auditGraduateInfo,
-  batchAuditGraduateInfo,
-  getOverallStatistics,
-  getPendingAuditCount
+  getOverallStatistics
 } from '@/api/zsjy/graduateInfo';
 import { GraduateInfoVO, GraduateInfoQuery, GraduateStatisticsVO } from '@/api/zsjy/types';
 
 const { proxy } = getCurrentInstance() as any;
-const { sys_user_sex, zsjy_graduate_employment_status, zsjy_graduate_audit_status } = proxy.useDict(
+const { sys_user_sex, zsjy_education_level, zsjy_graduate_employment_status, zsjy_graduate_company_type, zsjy_graduate_salary_range } = proxy.useDict(
   'sys_user_sex',
+  'zsjy_education_level',
   'zsjy_graduate_employment_status',
-  'zsjy_graduate_audit_status'
+  'zsjy_graduate_company_type',
+  'zsjy_graduate_salary_range'
 );
 
 // 响应式数据
@@ -576,15 +501,8 @@ const single = ref(true);
 const multiple = ref(true);
 const total = ref(0);
 const statistics = ref<GraduateStatisticsVO>({});
-const pendingAuditCount = ref(0);
 const detailVisible = ref(false);
 const detailData = ref<GraduateInfoVO>();
-const auditVisible = ref(false);
-const auditForm = reactive({
-  id: '',
-  auditStatus: '1',
-  auditRemark: ''
-});
 const daterangeCreateTime = ref<[string, string]>(['', '']);
 
 // 查询参数
@@ -599,7 +517,6 @@ const queryParams = reactive<GraduateInfoQuery>({
   collegeName: '',
   majorName: '',
   employmentStatus: '',
-  auditStatus: '',
   phoneNumber: '',
   params: {}
 });
@@ -616,26 +533,46 @@ const getList = async () => {
 
   try {
     const response = await listGraduateInfo(queryParams);
-
-    // 检查响应数据格式并设置列表数据
-    if (response && response.rows !== undefined) {
-      // 处理 TableDataInfo 格式的数据 (直接从response获取)
-      graduateInfoList.value = response.rows || [];
-      total.value = response.total || 0;
-    } else if (response && response.data && response.data.rows !== undefined) {
-      // 处理嵌套在data中的 TableDataInfo 格式
-      graduateInfoList.value = response.data.rows || [];
-      total.value = response.data.total || 0;
-    } else if (response && Array.isArray(response)) {
-      // 处理直接返回的数组格式
-      graduateInfoList.value = response;
-      total.value = response.length;
-    } else if (response && response.data && Array.isArray(response.data)) {
-      // 处理嵌套的数组格式
-      graduateInfoList.value = response.data;
-      total.value = response.data.length;
+    console.log('API响应完整结构:', response); // 调试日志
+    console.log('响应类型:', typeof response); // 调试日志
+
+    // 根据request.ts的响应拦截器,response直接是TableDataInfo格式
+    if (response && typeof response === 'object') {
+      // 使用类型断言处理不同的响应格式
+      const responseData = response as any;
+
+      // 检查是否是TableDataInfo格式(直接有rows和total)
+      if (responseData.rows !== undefined) {
+        console.log('响应数据是TableDataInfo格式');
+        graduateInfoList.value = responseData.rows || [];
+        total.value = responseData.total || 0;
+      }
+      // 如果是R<TableDataInfo>格式(有data字段)
+      else if (responseData.data && responseData.data.rows !== undefined) {
+        console.log('响应数据是R<TableDataInfo>格式');
+        graduateInfoList.value = responseData.data.rows || [];
+        total.value = responseData.data.total || 0;
+      }
+      // 如果直接是数组
+      else if (Array.isArray(responseData)) {
+        console.log('响应数据是直接数组格式');
+        graduateInfoList.value = responseData;
+        total.value = responseData.length;
+      }
+      // 其他格式
+      else {
+        console.error('未知的响应数据格式:', responseData);
+        console.error('响应对象的属性:', Object.keys(responseData)); // 调试日志
+        graduateInfoList.value = [];
+        total.value = 0;
+      }
+      console.log('设置列表数据:', graduateInfoList.value.length, '条记录'); // 调试日志
+      if (graduateInfoList.value.length > 0) {
+        console.log('第一条数据示例:', graduateInfoList.value[0]);
+        console.log('第一条数据的employmentCompany:', graduateInfoList.value[0]?.employmentCompany);
+      }
     } else {
-      console.error('未知的响应数据格式:', response);
+      console.error('响应数据格式异常:', response);
       graduateInfoList.value = [];
       total.value = 0;
     }
@@ -652,11 +589,31 @@ const getList = async () => {
 /** 获取统计数据 */
 const getStatistics = async () => {
   try {
-    const [statsResponse, pendingResponse] = await Promise.all([getOverallStatistics(), getPendingAuditCount()]);
-    statistics.value = statsResponse.data;
-    pendingAuditCount.value = pendingResponse.data;
+    const statsResponse = await getOverallStatistics();
+    console.log('统计数据响应:', statsResponse); // 调试日志
+
+    // 根据后端Controller,统计接口返回R<GraduateStatisticsVO>格式
+    if (statsResponse && typeof statsResponse === 'object') {
+      // 使用类型断言处理响应格式
+      const statsData = statsResponse as any;
+
+      // 如果响应有data字段(R格式)
+      if (statsData.data !== undefined) {
+        console.log('统计数据是R格式');
+        statistics.value = statsData.data || {};
+      }
+      // 如果响应直接是统计对象
+      else {
+        console.log('统计数据是直接对象格式');
+        statistics.value = statsData;
+      }
+    } else {
+      statistics.value = {};
+    }
+    console.log('设置统计数据:', statistics.value); // 调试日志
   } catch (error) {
     console.error('获取统计数据失败:', error);
+    statistics.value = {};
   }
 };
 
@@ -709,53 +666,7 @@ const closeDetail = () => {
   detailData.value = undefined;
 };
 
-/** 审核按钮操作 */
-const handleAudit = (row: GraduateInfoVO) => {
-  auditForm.id = row.id as string;
-  auditForm.auditStatus = '1';
-  auditForm.auditRemark = '';
-  auditVisible.value = true;
-};
-
-/** 提交审核 */
-const submitAudit = async () => {
-  try {
-    await auditGraduateInfo(auditForm.id, auditForm.auditStatus, auditForm.auditRemark);
-    proxy.$modal.msgSuccess('审核成功');
-    closeAudit();
-    getList();
-    getStatistics();
-  } catch (error) {
-    proxy.$modal.msgError('审核失败');
-  }
-};
-
-/** 关闭审核弹窗 */
-const closeAudit = () => {
-  auditVisible.value = false;
-  auditForm.id = '';
-  auditForm.auditStatus = '1';
-  auditForm.auditRemark = '';
-};
-
-/** 批量审核操作 */
-const handleBatchAudit = async (auditStatus: string) => {
-  if (ids.value.length === 0) {
-    proxy.$modal.msgWarning('请选择要审核的数据');
-    return;
-  }
-
-  const statusText = auditStatus === '1' ? '通过' : '拒绝';
-  try {
-    await proxy.$modal.confirm(`确认要批量${statusText}选中的毕业生信息吗?`);
-    await batchAuditGraduateInfo(ids.value, auditStatus);
-    proxy.$modal.msgSuccess(`批量${statusText}成功`);
-    getList();
-    getStatistics();
-  } catch (error) {
-    // 用户取消操作
-  }
-};
+/** 审核相关功能已隐藏 */
 
 /** 删除按钮操作 */
 const handleDelete = async (row?: GraduateInfoVO) => {
@@ -809,19 +720,7 @@ const getEmploymentStatusTagType = (status: string) => {
   }
 };
 
-/** 获取审核状态标签类型 */
-const getAuditStatusTagType = (status: string) => {
-  switch (status) {
-    case '0':
-      return 'warning';
-    case '1':
-      return 'success';
-    case '2':
-      return 'danger';
-    default:
-      return '';
-  }
-};
+/** 审核状态标签类型函数已移除 */
 
 // 页面初始化
 onMounted(() => {

+ 221 - 217
web/src/views/zsjy/jobPosition/index.vue

@@ -1,15 +1,13 @@
 <template>
   <div class="p-2 page-container">
-    <!-- 搜索区域 -->
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
+      <div ref="searchRef" v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form ref="queryFormRef" :model="queryParams" label-width="100px">
-            <!-- 搜索条件 -->
             <el-row :gutter="20">
               <el-col :span="6">
                 <el-form-item label="所属企业" prop="enterpriseId">
-                  <el-select v-model="queryParams.enterpriseId" placeholder="请选择所属企业" clearable style="width: 100%" @change="handleQuery">
+                  <el-select v-model="queryParams.enterpriseId" placeholder="请选择所属企业" clearable>
                     <el-option v-for="item in enterpriseOptions" :key="item.id" :label="item.enterpriseName" :value="item.id" />
                   </el-select>
                 </el-form-item>
@@ -26,14 +24,46 @@
               </el-col>
               <el-col :span="6">
                 <el-form-item label="状态" prop="status">
-                  <el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 100%">
+                  <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
                     <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
                   </el-select>
                 </el-form-item>
               </el-col>
             </el-row>
-
-            <!-- 操作按钮行 -->
+            <el-row :gutter="20">
+              <el-col :span="6">
+                <el-form-item label="是否永久" prop="isPermanent">
+                  <el-select v-model="queryParams.isPermanent" placeholder="请选择是否永久" clearable>
+                    <el-option label="是" :value="1" />
+                    <el-option label="否" :value="0" />
+                  </el-select>
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="开始时间" prop="startDate">
+                  <el-date-picker
+                    clearable
+                    v-model="queryParams.startDate"
+                    type="date"
+                    value-format="YYYY-MM-DD"
+                    placeholder="请选择开始时间"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="6">
+                <el-form-item label="结束时间" prop="endDate">
+                  <el-date-picker
+                    clearable
+                    v-model="queryParams.endDate"
+                    type="date"
+                    value-format="YYYY-MM-DD"
+                    placeholder="请选择结束时间"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+              </el-col>
+            </el-row>
             <el-row>
               <el-col :span="24" class="search-btn-container">
                 <el-form-item>
@@ -47,39 +77,42 @@
       </div>
     </transition>
 
-    <!-- 操作按钮栏 -->
-    <el-card shadow="hover" class="button-card">
+    <el-card shadow="never" class="button-card table-card">
       <template #header>
-        <div class="card-header-vertical">
-          <div class="toolbar-title">招聘岗位列表</div>
-          <div class="button-group">
+        <el-row ref="toolbarRef" :gutter="10" class="mb8">
+          <el-col :span="1.5">
             <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['zsjy:position:add']">新增</el-button>
-            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['zsjy:position:edit']">修改</el-button>
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['zsjy:position:remove']"
-              >删除</el-button
-            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['zsjy:position:edit']">修改</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['zsjy:position:remove']">删除</el-button>
+          </el-col>
+          <el-col :span="1.5">
             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['zsjy:position:export']">导出</el-button>
-            <el-button type="info" plain icon="Fold" @click="toggleSearch">
-              <span v-if="showSearch">隐藏</span>
-              <span v-else>展开</span>
-              搜索
-            </el-button>
-          </div>
-        </div>
+          </el-col>
+          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
       </template>
-    </el-card>
 
-    <!-- 表格区域 -->
-    <el-card shadow="hover" class="table-card">
       <div class="table-container">
-        <el-table v-loading="loading" :data="jobPositionList" @selection-change="handleSelectionChange" class="scroll-table" stripe border>
+        <el-table
+          v-loading="loading"
+          border
+          :data="jobPositionList"
+          @selection-change="handleSelectionChange"
+          style="width: 100%"
+          :scroll-x="true"
+          class="scroll-table"
+        >
           <el-table-column type="selection" width="55" align="center" fixed="left" />
-          <el-table-column label="企业名称" align="center" prop="enterpriseName" min-width="150" show-overflow-tooltip />
+          <el-table-column label="所属企业" align="center" prop="enterpriseName" min-width="150" show-overflow-tooltip />
           <el-table-column label="岗位名称" align="center" prop="positionName" min-width="150" show-overflow-tooltip />
-          <el-table-column label="工作地址" align="center" prop="workAddress" min-width="180" show-overflow-tooltip />
-          <el-table-column label="工作时间" align="center" prop="workTime" min-width="120" show-overflow-tooltip />
-          <el-table-column label="薪资" align="center" prop="salary" min-width="120" />
-          <el-table-column label="有效期" align="center" min-width="180">
+          <el-table-column label="工作地址" align="center" prop="workAddress" min-width="200" show-overflow-tooltip />
+          <el-table-column label="工作时间" align="center" prop="workTime" width="180" show-overflow-tooltip />
+          <el-table-column label="薪资" align="center" prop="salary" width="150" show-overflow-tooltip />
+          <el-table-column label="有效期" align="center" width="200">
             <template #default="scope">
               <span v-if="scope.row.isPermanent === 1">永久有效</span>
               <span v-else>{{ scope.row.startDate }} ~ {{ scope.row.endDate }}</span>
@@ -91,54 +124,28 @@
             </template>
           </el-table-column>
           <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
-          <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180" fixed="right">
+          <el-table-column label="操作" align="center" width="280" fixed="right" class-name="small-padding fixed-width">
             <template #default="scope">
               <el-tooltip content="查看" placement="top">
-                <el-button
-                  link
-                  type="primary"
-                  icon="View"
-                  size="default"
-                  style="font-size: 16px; margin-right: 8px; color: blue"
-                  @click="handleDetail(scope.row)"
-                  v-hasPermi="['zsjy:position:query']"
-                ></el-button>
+                <el-button link type="info" icon="View" @click="handleDetail(scope.row)" v-hasPermi="['zsjy:position:query']"></el-button>
               </el-tooltip>
               <el-tooltip content="修改" placement="top">
-                <el-button
-                  link
-                  type="primary"
-                  icon="Edit"
-                  size="default"
-                  style="font-size: 16px; margin-right: 8px"
-                  @click="handleUpdate(scope.row)"
-                  v-hasPermi="['zsjy:position:edit']"
-                ></el-button>
+                <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['zsjy:position:edit']"></el-button>
               </el-tooltip>
               <el-tooltip content="删除" placement="top">
-                <el-button
-                  link
-                  type="danger"
-                  icon="Delete"
-                  size="default"
-                  style="font-size: 16px"
-                  @click="handleDelete(scope.row)"
-                  v-hasPermi="['zsjy:position:remove']"
-                ></el-button>
+                <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['zsjy:position:remove']"></el-button>
               </el-tooltip>
             </template>
           </el-table-column>
         </el-table>
       </div>
-
-      <!-- 分页 -->
       <div class="pagination-container">
         <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
       </div>
     </el-card>
 
-    <!-- 新增/修改对话框 -->
-    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
+    <!-- 添加或修改招聘岗位对话框 -->
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body>
       <el-form ref="jobPositionFormRef" :model="form" :rules="rules" label-width="100px">
         <el-row :gutter="20">
           <el-col :span="12">
@@ -217,7 +224,7 @@
       </el-form>
       <template #footer>
         <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
           <el-button @click="cancel">取 消</el-button>
         </div>
       </template>
@@ -253,58 +260,30 @@
 </template>
 
 <script setup name="JobPosition" lang="ts">
-import { getCurrentInstance, ComponentInternalInstance, ref, reactive, toRefs, onMounted } from 'vue';
-import { FormInstance } from 'element-plus';
-import {
-  listJobPosition,
-  getJobPosition,
-  delJobPosition,
-  addJobPosition,
-  updateJobPosition,
-  exportJobPosition,
-  listEnterpriseOptions
-} from '@/api/zsjy/jobPosition';
+import { listJobPosition, getJobPosition, delJobPosition, addJobPosition, updateJobPosition, exportJobPosition, listEnterpriseOptions } from '@/api/zsjy/jobPosition';
 import { JobPositionVO, JobPositionForm, JobPositionQuery } from '@/api/zsjy/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-// 字典数据
 const { sys_normal_disable } = toRefs<any>(proxy?.useDict('sys_normal_disable'));
 
-// 表格数据
 const jobPositionList = ref<JobPositionVO[]>([]);
-const total = ref(0);
-const loading = ref(false);
+const buttonLoading = ref(false);
+const loading = ref(true);
 const showSearch = ref(true);
 const ids = ref<Array<string | number>>([]);
 const single = ref(true);
 const multiple = ref(true);
+const total = ref(0);
 
-// 表单相关
-const open = ref(false);
-const title = ref('');
-const jobPositionFormRef = ref<FormInstance>();
-const queryFormRef = ref<FormInstance>();
-
-// 企业选项
-const enterpriseOptions = ref<any[]>([]);
+const queryFormRef = ref<ElFormInstance>();
+const jobPositionFormRef = ref<ElFormInstance>();
 
-// 日期范围
-const dateRange = ref<[string, string]>([]);
-
-// 查询参数
-const queryParams = ref<JobPositionQuery>({
-  pageNum: 1,
-  pageSize: 10,
-  enterpriseId: undefined,
-  positionName: undefined,
-  workAddress: undefined,
-  status: undefined,
-  isPermanent: undefined
+const dialog = reactive<DialogOption>({
+  visible: false,
+  title: ''
 });
 
-// 表单参数
-const form = ref<JobPositionForm>({
+const initFormData: JobPositionForm = {
   id: undefined,
   enterpriseId: '',
   positionName: '',
@@ -317,17 +296,37 @@ const form = ref<JobPositionForm>({
   isPermanent: 0,
   status: '0',
   remark: ''
+};
+
+const data = reactive<PageData<JobPositionForm, JobPositionQuery>>({
+  form: { ...initFormData },
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    enterpriseId: undefined,
+    positionName: undefined,
+    workAddress: undefined,
+    status: undefined,
+    isPermanent: undefined,
+    params: {}
+  },
+  rules: {
+    enterpriseId: [{ required: true, message: '请选择所属企业', trigger: 'change' }],
+    positionName: [{ required: true, message: '岗位名称不能为空', trigger: 'blur' }],
+    workAddress: [{ required: true, message: '工作地址不能为空', trigger: 'blur' }],
+    workTime: [{ required: true, message: '工作时间不能为空', trigger: 'blur' }],
+    salary: [{ required: true, message: '薪资不能为空', trigger: 'blur' }],
+    status: [{ required: true, message: '状态不能为空', trigger: 'change' }]
+  }
 });
 
-// 表单校验规则
-const rules = {
-  enterpriseId: [{ required: true, message: '请选择所属企业', trigger: 'change' }],
-  positionName: [{ required: true, message: '岗位名称不能为空', trigger: 'blur' }],
-  workAddress: [{ required: true, message: '工作地址不能为空', trigger: 'blur' }],
-  workTime: [{ required: true, message: '工作时间不能为空', trigger: 'blur' }],
-  salary: [{ required: true, message: '薪资不能为空', trigger: 'blur' }],
-  status: [{ required: true, message: '状态不能为空', trigger: 'change' }]
-};
+const { queryParams, form, rules } = toRefs(data);
+
+// 企业选项
+const enterpriseOptions = ref<any[]>([]);
+
+// 日期范围
+const dateRange = ref<[string, string] | []>([]);
 
 // 详情数据
 const detailOpen = ref(false);
@@ -360,11 +359,6 @@ const resetQuery = () => {
   handleQuery();
 };
 
-/** 切换搜索显示 */
-const toggleSearch = () => {
-  showSearch.value = !showSearch.value;
-};
-
 /** 多选框选中数据 */
 const handleSelectionChange = (selection: JobPositionVO[]) => {
   ids.value = selection.map((item) => item.id);
@@ -374,22 +368,22 @@ const handleSelectionChange = (selection: JobPositionVO[]) => {
 
 /** 新增按钮操作 */
 const handleAdd = () => {
-  resetForm();
-  open.value = true;
-  title.value = '添加招聘岗位';
+  reset();
+  dialog.visible = true;
+  dialog.title = '添加招聘岗位';
 };
 
 /** 修改按钮操作 */
 const handleUpdate = async (row?: JobPositionVO) => {
-  resetForm();
+  reset();
   const id = row?.id || ids.value[0];
   const res = await getJobPosition(id);
   Object.assign(form.value, res.data);
   if (!form.value.isPermanent) {
     dateRange.value = [form.value.startDate, form.value.endDate];
   }
-  open.value = true;
-  title.value = '修改招聘岗位';
+  dialog.visible = true;
+  dialog.title = '修改招聘岗位';
 };
 
 /** 详情按钮操作 */
@@ -412,6 +406,8 @@ const handlePermanentChange = (val: number) => {
 const submitForm = () => {
   jobPositionFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
+      buttonLoading.value = true;
+
       // 处理日期范围
       if (form.value.isPermanent === 0 && dateRange.value && dateRange.value.length === 2) {
         form.value.startDate = dateRange.value[0];
@@ -419,14 +415,13 @@ const submitForm = () => {
       }
 
       if (form.value.id) {
-        await updateJobPosition(form.value);
-        proxy?.$modal.msgSuccess('修改成功');
+        await updateJobPosition(form.value).finally(() => (buttonLoading.value = false));
       } else {
-        await addJobPosition(form.value);
-        proxy?.$modal.msgSuccess('新增成功');
+        await addJobPosition(form.value).finally(() => (buttonLoading.value = false));
       }
-      open.value = false;
-      getList();
+      proxy?.$modal.msgSuccess('操作成功');
+      dialog.visible = false;
+      await getList();
     }
   });
 };
@@ -434,27 +429,31 @@ const submitForm = () => {
 /** 删除按钮操作 */
 const handleDelete = async (row?: JobPositionVO) => {
   const jobIds = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除选中的招聘岗位?');
+  await proxy?.$modal.confirm('是否确认删除选中的招聘岗位?').finally(() => (loading.value = false));
   await delJobPosition(jobIds);
   proxy?.$modal.msgSuccess('删除成功');
-  getList();
+  await getList();
 };
 
 /** 导出按钮操作 */
-const handleExport = async () => {
-  await proxy?.$modal.confirm('是否确认导出所有招聘岗位数据?');
-  await exportJobPosition(queryParams.value);
-  proxy?.$modal.msgSuccess('导出成功');
+const handleExport = () => {
+  proxy?.download(
+    'zsjy/position/export',
+    {
+      ...queryParams.value
+    },
+    `jobPosition_${new Date().getTime()}.xlsx`
+  );
 };
 
 /** 取消按钮 */
 const cancel = () => {
-  open.value = false;
-  resetForm();
+  reset();
+  dialog.visible = false;
 };
 
 /** 表单重置 */
-const resetForm = () => {
+const reset = () => {
   form.value = {
     id: undefined,
     enterpriseId: '',
@@ -480,102 +479,107 @@ onMounted(() => {
 });
 </script>
 
-<style scoped lang="scss">
-// 继承后勤管理的样式
+<style scoped>
 .page-container {
-  .search-btn-container {
-    text-align: right;
-  }
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
 
-  .button-card {
-    margin-bottom: 20px;
-    padding: 20px;
-    background-color: #fff;
-    border-radius: 8px;
-    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  }
+.search-btn-container {
+  text-align: center;
+  margin-top: 10px;
+}
 
-  .card-header-vertical {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
+.button-card {
+  margin-top: 10px;
+}
 
-  .toolbar-title {
-    font-size: 18px;
-    font-weight: bold;
-    color: #303133;
-  }
+.table-card {
+  background-color: #fff;
+}
 
-  .button-group {
-    display: flex;
-    align-items: center;
-    gap: 10px;
-  }
+.table-container {
+  overflow-x: auto;
+}
 
-  .table-card {
-    margin-bottom: 20px;
-    padding: 20px;
-    background-color: #fff;
-    border-radius: 8px;
-    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  }
+.scroll-table {
+  min-width: 100%;
+}
 
-  .table-container {
-    overflow-x: auto;
-  }
+.pagination-container {
+  margin-top: 20px;
+  text-align: right;
+}
 
-  .scroll-table {
-    width: 100%;
-  }
+.dialog-footer {
+  text-align: center;
+}
 
-  .pagination-container {
-    text-align: right;
-    padding-top: 20px;
-  }
+:deep(.el-card__header) {
+  padding: 15px 20px;
+  border-bottom: 1px solid #ebeef5;
+  background-color: #fafafa;
+}
 
-  .dialog-footer {
-    text-align: right;
-  }
+:deep(.el-table) {
+  border-radius: 4px;
+}
 
-  // 表格适应性样式
-  :deep(.el-table) {
-    .el-table__cell {
-      padding: 8px 0;
-    }
-  }
+:deep(.el-table th) {
+  background-color: #fafafa;
+  color: #606266;
+  font-weight: 500;
+}
 
-  // 响应式表格
-  :deep(.el-table__body-wrapper) {
-    overflow-x: auto;
-  }
+:deep(.el-button--plain) {
+  border-color: #dcdfe6;
+  color: #606266;
+}
 
-  // 表格列宽自适应
-  .el-table {
-    width: 100%;
-    table-layout: auto;
-  }
+:deep(.el-button--plain:hover) {
+  border-color: #409eff;
+  color: #409eff;
 }
 
-// 操作按钮样式
-.action-buttons {
-  display: flex;
-  gap: 8px;
-  justify-content: center;
-  align-items: center;
-  white-space: nowrap;
+:deep(.el-button--primary.is-plain) {
+  border-color: #409eff;
+  color: #409eff;
 }
 
-// 描述列表样式优化
-:deep(.el-descriptions) {
-  .el-descriptions__label {
-    font-weight: 600;
-    color: #606266;
-    width: 120px;
-  }
+:deep(.el-button--success.is-plain) {
+  border-color: #67c23a;
+  color: #67c23a;
+}
 
-  .el-descriptions__content {
-    color: #303133;
-  }
+:deep(.el-button--danger.is-plain) {
+  border-color: #f56c6c;
+  color: #f56c6c;
+}
+
+:deep(.el-button--warning.is-plain) {
+  border-color: #e6a23c;
+  color: #e6a23c;
+}
+
+:deep(.el-form-item__label) {
+  color: #606266;
+  font-weight: 500;
+}
+
+:deep(.el-input__wrapper) {
+  border-radius: 4px;
+}
+
+:deep(.el-select .el-input__wrapper) {
+  border-radius: 4px;
+}
+
+:deep(.el-date-editor .el-input__wrapper) {
+  border-radius: 4px;
+}
+.exclusive-relation-text {
+  color: #909399;
+  line-height: 1.2;
+  word-break: break-word;
 }
 </style>

+ 141 - 148
web/src/views/zsjy/recruitmentPoster/index.vue

@@ -2,10 +2,9 @@
   <div class="p-2 page-container">
     <!-- 搜索区域 -->
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
-      <div v-show="showSearch" class="mb-[10px]">
+      <div ref="searchRef" v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
           <el-form ref="queryFormRef" :model="queryParams" label-width="100px">
-            <!-- 搜索条件 -->
             <el-row :gutter="20">
               <el-col :span="6">
                 <el-form-item label="所属企业" prop="enterpriseId">
@@ -40,7 +39,9 @@
                   </el-select>
                 </el-form-item>
               </el-col>
-              <el-col :span="6">
+            </el-row>
+            <el-row>
+              <el-col :span="24" class="search-btn-container">
                 <el-form-item>
                   <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
                   <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -52,32 +53,35 @@
       </div>
     </transition>
 
-    <!-- 操作按钮栏 -->
-    <el-card shadow="hover" class="button-card">
+    <el-card shadow="never" class="button-card table-card">
       <template #header>
-        <div class="card-header-vertical">
-          <div class="toolbar-title">招聘海报列表</div>
-          <div class="button-group">
+        <el-row ref="toolbarRef" :gutter="10" class="mb8">
+          <el-col :span="1.5">
             <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['zsjy:poster:add']">新增</el-button>
+          </el-col>
+          <el-col :span="1.5">
             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['zsjy:poster:edit']">修改</el-button>
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['zsjy:poster:remove']"
-              >删除</el-button
-            >
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['zsjy:poster:remove']">删除</el-button>
+          </el-col>
+          <el-col :span="1.5">
             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['zsjy:poster:export']">导出</el-button>
-            <el-button type="info" plain icon="Fold" @click="toggleSearch">
-              <span v-if="showSearch">隐藏</span>
-              <span v-else>展开</span>
-              搜索
-            </el-button>
-          </div>
-        </div>
+          </el-col>
+          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+        </el-row>
       </template>
-    </el-card>
 
-    <!-- 表格区域 -->
-    <el-card shadow="hover" class="table-card">
       <div class="table-container">
-        <el-table v-loading="loading" :data="posterList" @selection-change="handleSelectionChange" class="scroll-table" stripe border>
+        <el-table
+          v-loading="loading"
+          border
+          :data="posterList"
+          @selection-change="handleSelectionChange"
+          style="width: 100%"
+          :scroll-x="true"
+          class="scroll-table"
+        >
           <el-table-column type="selection" width="55" align="center" fixed="left" />
           <el-table-column label="企业名称" align="center" prop="enterpriseName" min-width="150" show-overflow-tooltip />
           <el-table-column label="海报类型" align="center" prop="posterType" width="120">
@@ -116,47 +120,21 @@
             </template>
           </el-table-column>
           <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
-          <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180" fixed="right">
+          <el-table-column label="操作" align="center" width="280" fixed="right" class-name="small-padding fixed-width">
             <template #default="scope">
               <el-tooltip content="预览" placement="top">
-                <el-button
-                  link
-                  type="primary"
-                  icon="View"
-                  size="default"
-                  style="font-size: 16px; margin-right: 8px; color: blue"
-                  @click="handlePreview(scope.row)"
-                  v-hasPermi="['zsjy:poster:query']"
-                ></el-button>
+                <el-button link type="info" icon="View" @click="handlePreview(scope.row)" v-hasPermi="['zsjy:poster:query']"></el-button>
               </el-tooltip>
               <el-tooltip content="修改" placement="top">
-                <el-button
-                  link
-                  type="primary"
-                  icon="Edit"
-                  size="default"
-                  style="font-size: 16px; margin-right: 8px"
-                  @click="handleUpdate(scope.row)"
-                  v-hasPermi="['zsjy:poster:edit']"
-                ></el-button>
+                <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['zsjy:poster:edit']"></el-button>
               </el-tooltip>
               <el-tooltip content="删除" placement="top">
-                <el-button
-                  link
-                  type="danger"
-                  icon="Delete"
-                  size="default"
-                  style="font-size: 16px"
-                  @click="handleDelete(scope.row)"
-                  v-hasPermi="['zsjy:poster:remove']"
-                ></el-button>
+                <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['zsjy:poster:remove']"></el-button>
               </el-tooltip>
             </template>
           </el-table-column>
         </el-table>
       </div>
-
-      <!-- 分页 -->
       <div class="pagination-container">
         <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
       </div>
@@ -376,11 +354,6 @@ const resetQuery = () => {
   handleQuery();
 };
 
-/** 切换搜索显示 */
-const toggleSearch = () => {
-  showSearch.value = !showSearch.value;
-};
-
 /** 企业选择改变 */
 const handleEnterpriseChange = (val: number | string) => {
   queryParams.value.positionId = undefined;
@@ -533,128 +506,148 @@ onMounted(() => {
 });
 </script>
 
-<style scoped lang="scss">
-// 继承后勤管理的样式
+<style scoped>
 .page-container {
-  .search-btn-container {
-    text-align: right;
-  }
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
 
-  .button-card {
-    margin-bottom: 20px;
-    padding: 20px;
-    background-color: #fff;
-    border-radius: 8px;
-    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  }
+.search-btn-container {
+  text-align: center;
+  margin-top: 10px;
+}
 
-  .card-header-vertical {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
+.button-card {
+  margin-top: 10px;
+}
 
-  .toolbar-title {
-    font-size: 18px;
-    font-weight: bold;
-    color: #303133;
-  }
+.table-card {
+  background-color: #fff;
+}
 
-  .button-group {
-    display: flex;
-    align-items: center;
-    gap: 10px;
-  }
+.table-container {
+  overflow-x: auto;
+}
 
-  .table-card {
-    margin-bottom: 20px;
-    padding: 20px;
-    background-color: #fff;
-    border-radius: 8px;
-    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  }
+.scroll-table {
+  min-width: 100%;
+}
 
-  .table-container {
-    overflow-x: auto;
-  }
+.pagination-container {
+  margin-top: 20px;
+  text-align: right;
+}
 
-  .scroll-table {
-    width: 100%;
-  }
+.dialog-footer {
+  text-align: center;
+}
 
-  .pagination-container {
-    text-align: right;
-    padding-top: 20px;
-  }
+:deep(.el-card__header) {
+  padding: 15px 20px;
+  border-bottom: 1px solid #ebeef5;
+  background-color: #fafafa;
+}
 
-  .dialog-footer {
-    text-align: right;
-  }
+:deep(.el-table) {
+  border-radius: 4px;
+}
 
-  // 表格适应性样式
-  :deep(.el-table) {
-    .el-table__cell {
-      padding: 8px 0;
-    }
-  }
+:deep(.el-table th) {
+  background-color: #fafafa;
+  color: #606266;
+  font-weight: 500;
+}
 
-  // 响应式表格
-  :deep(.el-table__body-wrapper) {
-    overflow-x: auto;
-  }
+:deep(.el-button--plain) {
+  border-color: #dcdfe6;
+  color: #606266;
+}
 
-  // 表格列宽自适应
-  .el-table {
-    width: 100%;
-    table-layout: auto;
-  }
+:deep(.el-button--plain:hover) {
+  border-color: #409eff;
+  color: #409eff;
 }
 
-// 操作按钮样式
-.action-buttons {
-  display: flex;
-  gap: 8px;
-  justify-content: center;
-  align-items: center;
-  white-space: nowrap;
+:deep(.el-button--primary.is-plain) {
+  border-color: #409eff;
+  color: #409eff;
 }
 
-// 描述列表样式优化
-:deep(.el-descriptions) {
-  .el-descriptions__label {
-    font-weight: 600;
-    color: #606266;
-    width: 120px;
-  }
+:deep(.el-button--success.is-plain) {
+  border-color: #67c23a;
+  color: #67c23a;
+}
 
-  .el-descriptions__content {
-    color: #303133;
-  }
+:deep(.el-button--danger.is-plain) {
+  border-color: #f56c6c;
+  color: #f56c6c;
+}
+
+:deep(.el-button--warning.is-plain) {
+  border-color: #e6a23c;
+  color: #e6a23c;
+}
+
+:deep(.el-form-item__label) {
+  color: #606266;
+  font-weight: 500;
+}
+
+:deep(.el-input__wrapper) {
+  border-radius: 4px;
+}
+
+:deep(.el-select .el-input__wrapper) {
+  border-radius: 4px;
 }
 
-// 海报预览样式
+:deep(.el-date-editor .el-input__wrapper) {
+  border-radius: 4px;
+}
+
+/* 海报预览样式 */
 .poster-preview-container {
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: 20px;
+}
 
-  .poster-image-section {
-    display: flex;
-    justify-content: center;
-    padding: 20px;
-    background: #f5f7fa;
-    border-radius: 8px;
-  }
+.poster-image-section {
+  display: flex;
+  justify-content: center;
+  padding: 20px;
+  background: #f5f7fa;
+  border-radius: 8px;
+}
 
-  .poster-info-section {
-    width: 100%;
-    max-width: 600px;
-  }
+.poster-info-section {
+  width: 100%;
+  max-width: 600px;
 }
 
 .no-poster-tip {
   padding: 40px;
   text-align: center;
 }
+
+/* 描述列表样式优化 */
+:deep(.el-descriptions) .el-descriptions__label {
+  font-weight: 600;
+  color: #606266;
+  width: 120px;
+}
+
+:deep(.el-descriptions) .el-descriptions__content {
+  color: #303133;
+}
+.search-btn-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 10px;
+
+  .el-form-item {
+    margin-bottom: 0 !important;
+  }
+}
 </style>