1
0

2 Ревизии dad5324766 ... 374c263a4a

Автор SHA1 Съобщение Дата
  dengweize 374c263a4a Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_adminUI преди 1 месец
  dengweize e1f19289c5 金牛ipad审核页面 преди 1 месец
променени са 3 файла, в които са добавени 1483 реда и са изтрити 0 реда
  1. 86 0
      src/api/qw/applyIpad.js
  2. 9 0
      src/api/qw/qwIpadServer.js
  3. 1388 0
      src/views/qw/applyIpad/index.vue

+ 86 - 0
src/api/qw/applyIpad.js

@@ -0,0 +1,86 @@
+import request from '@/utils/request'
+
+// 查询分配记录列表
+export function listRecords(query) {
+  return request({
+    url: '/qw/records/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询分配记录详细
+export function getRecords(id) {
+  return request({
+    url: '/qw/records/' + id,
+    method: 'get'
+  })
+}
+
+// 新增分配记录
+export function addRecords(data) {
+  return request({
+    url: '/qw/records',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改分配记录
+export function updateRecords(data) {
+  return request({
+    url: '/qw/records',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除分配记录
+export function delRecords(id) {
+  return request({
+    url: '/qw/records/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出分配记录
+export function exportRecords(query) {
+  return request({
+    url: '/qw/records/export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function apply(applyCount) {
+  return request({
+    url: '/qw/records/apply',
+    method: 'get',
+    params: applyCount
+  })
+}
+// 新增分配记录
+//@PostMapping("/batchUpdate")
+// public AjaxResult batchUpdate(@RequestBody Long[] ids)
+//后端接收结构
+export function batchUpdate(data) {
+  return request({
+    url: '/qw/records/batchUpdate',
+    method: 'post',
+    data: data
+  })
+}
+// 获取服务器信息
+export function getServerInfo(id) {
+  return request({
+    url: '/qw/records/server/' + id,
+    method: 'get'
+  })
+}
+export function release(data) {
+  return request({
+    url: '/qw/records/release',
+    method: 'post',
+    data: data
+  })
+}

+ 9 - 0
src/api/qw/qwIpadServer.js

@@ -50,4 +50,13 @@ export function exportQwIpadServer(query) {
     method: 'get',
     params: query
   })
+}
+
+// 新增ipad服务器
+export function release(data) {
+  return request({
+    url: '/qw/records/release',
+    method: 'post',
+    data: data
+  })
 }

+ 1388 - 0
src/views/qw/applyIpad/index.vue

@@ -0,0 +1,1388 @@
+<template>
+  <div class="app-container">
+    <!-- 数据统计卡片 -->
+    <div class="statistics-cards">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon pending">
+                <i class="el-icon-time"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.pending }}</div>
+                <div class="stat-label">待审核</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon approved">
+                <i class="el-icon-check"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.approved }}</div>
+                <div class="stat-label">已通过</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon rejected">
+                <i class="el-icon-close"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.rejected }}</div>
+                <div class="stat-label">已拒绝</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon total">
+                <i class="el-icon-data-line"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.total }}</div>
+                <div class="stat-label">总申请数</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+
+    <!-- 搜索表单 -->
+    <el-card class="search-card" shadow="hover">
+      <div class="search-header">
+        <div class="search-title">
+          <i class="el-icon-search"></i>
+          <span>筛选条件</span>
+        </div>
+        <el-button type="text" @click="toggleSearch">
+          {{ showSearch ? '收起' : '展开' }}
+          <i :class="showSearch ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
+        </el-button>
+      </div>
+
+      <el-collapse-transition>
+        <el-form v-show="showSearch" :model="queryParams" ref="queryForm" :inline="true" label-width="80px"
+          class="search-form">
+          <el-row :gutter="20">
+            <el-col :span="6">
+              <el-form-item label="公司名称" prop="companyName">
+                <el-input v-model="queryParams.companyName" placeholder="请输入公司名称" clearable
+                  prefix-icon="el-icon-office-building" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="提交单号" prop="applicationNumber">
+                <el-input v-model="queryParams.applicationNumber" placeholder="请输入提交单号" clearable
+                  prefix-icon="el-icon-document" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="申请数量" prop="applyQuantity">
+                <el-input v-model="queryParams.applyQuantity" placeholder="请输入申请数量" clearable
+                  prefix-icon="el-icon-s-data" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="审核状态" prop="auditStatus">
+                <el-select v-model="queryParams.auditStatus" placeholder="请选择审核状态" clearable class="search-select">
+                  <el-option label="待审核" value="0" />
+                  <el-option label="审核通过" value="1" />
+                  <el-option label="审核拒绝" value="2" />
+                  <el-option label="部分分配" value="3" />
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row :gutter="20">
+            <el-col :span="6">
+              <el-form-item label="提交时间" prop="submitTime">
+                <el-date-picker clearable v-model="queryParams.submitTime" type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择提交时间" class="search-date">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="审核时间" prop="reviewTime">
+                <el-date-picker clearable v-model="queryParams.reviewTime" type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择审核时间" class="search-date">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="实际分配" prop="allocatedQuantity">
+                <el-input v-model="queryParams.allocatedQuantity" placeholder="请输入实际分配数量" clearable
+                  prefix-icon="el-icon-s-marketing" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item>
+                <el-button type="primary" icon="el-icon-search" @click="handleQuery" class="search-btn">
+                  搜索
+                </el-button>
+                <el-button icon="el-icon-refresh" @click="resetQuery" class="reset-btn">
+                  重置
+                </el-button>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+      </el-collapse-transition>
+    </el-card>
+
+    <!-- 批量操作工具栏 -->
+    <div class="batch-toolbar" v-show="selectedRows.length > 0">
+      <el-card class="batch-card" shadow="hover">
+        <div class="batch-content">
+          <div class="batch-info">
+            <i class="el-icon-warning-outline"></i>
+            <span>已选择 {{ selectedRows.length }} 项</span>
+          </div>
+          <div class="batch-actions">
+            <el-button size="small" @click="batchApprove" v-if="canBatchApprove" type="success">
+              <i class="el-icon-check"></i> 批量通过
+            </el-button>
+            <el-button size="small" @click="batchReject" v-if="canBatchReject" type="danger">
+              <i class="el-icon-close"></i> 批量拒绝
+            </el-button>
+            <el-button size="small" @click="handleBatchSync" type="warning">
+              <i class="el-icon-refresh"></i> 批量同步
+            </el-button>
+            <el-button size="small" @click="clearSelection">
+              <i class="el-icon-close"></i> 清空选择
+            </el-button>
+          </div>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <el-card class="action-card" shadow="never">
+      <div class="action-bar">
+        <div class="action-group">
+          <el-button type="primary" icon="el-icon-plus" @click="handleAdd" class="action-btn"
+            >
+            申请iPad
+          </el-button>
+
+          <el-button type="success" icon="el-icon-edit" @click="handleUpdate" :disabled="single" class="action-btn"
+            >
+            修改
+          </el-button>
+
+          <el-dropdown @command="handleBatchCommand" class="action-dropdown">
+            <el-button type="warning" class="action-btn">
+              批量操作<i class="el-icon-arrow-down el-icon--right"></i>
+            </el-button>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item command="sync">
+                批量同步
+              </el-dropdown-item>
+              <el-dropdown-item command="export">
+                导出数据
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </div>
+
+        <div class="action-right">
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 数据表格 -->
+    <el-card class="table-card" shadow="hover">
+      <el-table border v-loading="loading" :data="recordsList" @selection-change="handleSelectionChange"
+        class="modern-table" :header-cell-class-name="headerCellClass" :cell-class-name="cellClass"
+        @row-click="handleRowClick">
+
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="公司名称" align="center" prop="companyName" min-width="150">
+          <template slot-scope="scope">
+            <div class="company-name">
+              <i class="el-icon-office-building"></i>
+              {{ scope.row.companyName }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="申请数量" align="center" prop="applyQuantity" width="100">
+          <template slot-scope="scope">
+            <el-tag type="info" effect="plain">{{ scope.row.applyQuantity }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="实际分配数量" align="center" prop="allocatedQuantity" width="120">
+          <template slot-scope="scope">
+            <el-tag type="success" effect="plain">{{ scope.row.allocatedQuantity || 0 }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="提交时间" align="center" prop="submitTime" width="180">
+          <template slot-scope="scope">
+            <div class="time-info">
+              <i class="el-icon-time"></i>
+              <span>{{ parseTime(scope.row.submitTime) }}</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="审核时间" align="center" prop="reviewTime" width="180">
+          <template slot-scope="scope">
+            <div class="time-info" v-if="scope.row.reviewTime">
+              <i class="el-icon-check"></i>
+              <span>{{ parseTime(scope.row.reviewTime) }}</span>
+            </div>
+            <span v-else class="no-data">-</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="审核状态" align="center" prop="auditStatus" width="120">
+          <template slot-scope="scope">
+            <div class="status-wrapper">
+              <el-tag :class="getStatusClass(scope.row.auditStatus)"
+                :effect="scope.row.auditStatus === 1 ? 'dark' : 'light'">
+                <i :class="getStatusIcon(scope.row.auditStatus)"></i>
+                {{ getStatusText(scope.row.auditStatus) }}
+              </el-tag>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="拒绝原因" align="center" prop="rejectionReason" min-width="150">
+          <template slot-scope="scope">
+            <el-tooltip :content="scope.row.rejectionReason" placement="top" v-if="scope.row.rejectionReason">
+              <span class="rejection-reason">{{ scope.row.rejectionReason }}</span>
+            </el-tooltip>
+            <span v-else class="no-data">-</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="操作" align="center" width="180" fixed="right">
+          <template slot-scope="scope">
+            <div class="action-buttons">
+              <el-tooltip content="同步数据" placement="top">
+                <el-button type="text" icon="el-icon-refresh" class="action-icon-btn sync-btn"
+                  @click="handleSingleSync(scope.row)" />
+              </el-tooltip>
+
+              <el-tooltip content="释放管理" placement="top"
+                v-if="scope.row.auditStatus == 1 || scope.row.auditStatus == 3">
+                <el-button type="text" icon="el-icon-unlock" class="action-icon-btn release-btn"
+                  @click="handleRelease(scope.row)" />
+              </el-tooltip>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 分页 -->
+      <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+        @pagination="getList" class="pagination-wrapper" />
+    </el-card>
+
+    <!-- 申请iPad对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="600px" :close-on-click-modal="false"
+      custom-class="modern-dialog" append-to-body>
+      <div class="dialog-content">
+        <div class="form-header">
+          <i class="el-icon-mobile-phone"></i>
+          <span>请填写申请信息</span>
+        </div>
+
+        <el-form ref="form" :model="form" :rules="rules" label-width="100px" class="modern-form">
+          <el-form-item label="申请地区" prop="area">
+            <el-input v-model="form.area" placeholder="请输入申请地区,如:广州、上海、重庆、北京等"
+              prefix-icon="el-icon-location" class="area-input" />
+            <div class="form-tip">
+              <i class="el-icon-info"></i>
+              请填写申请iPad使用的地区
+            </div>
+          </el-form-item>
+          <el-form-item label="申请数量" prop="applyQuantity">
+            <el-input-number v-model="form.applyQuantity" :min="1" :max="100" controls-position="right"
+              class="number-input" placeholder="请输入申请数量" />
+            <div class="form-tip">
+              <i class="el-icon-info"></i>
+              建议根据实际需求申请合理数量
+            </div>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="cancel" class="cancel-btn">取 消</el-button>
+        <el-button type="primary" @click="submitForm" :loading="submitting" class="confirm-btn">
+          {{ submitting ? '提交中...' : '确定申请' }}
+        </el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 释放信息抽屉 -->
+    <el-drawer title="服务器分配信息" :visible.sync="releaseOpen" direction="rtl" size="70%" :before-close="handleDrawerClose"
+      custom-class="modern-drawer">
+      <div class="drawer-content">
+        <el-table :data="serverInfoList" border v-loading="releaseLoading" class="server-table">
+          <el-table-column label="访问地址" align="center" prop="accessUrl" min-width="200">
+            <template slot-scope="scope">
+              <a :href="scope.row.accessUrl" target="_blank" class="access-url">
+                <i class="el-icon-link"></i>
+                {{ scope.row.accessUrl }}
+              </a>
+            </template>
+          </el-table-column>
+          <el-table-column label="已分配座位数" align="center" prop="allocatedSeats" width="120">
+            <template slot-scope="scope">
+              <el-tag type="primary">{{ scope.row.allocatedSeats }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="分配时间" align="center" prop="allocatedTime" width="180">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.allocatedTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="分配状态" align="center" prop="allocationStatus" width="100">
+            <template slot-scope="scope">
+              <el-tag :type="scope.row.allocationStatus === 1 ? 'success' : 'info'">
+                {{ scope.row.allocationStatus === 1 ? '有效' : '已释放' }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="IP地址" align="center" prop="ipAddress" width="120" />
+          <el-table-column label="端口" align="center" prop="port" width="80" />
+          <el-table-column label="地区" align="center" prop="region" width="100" />
+          <el-table-column label="创建时间" align="center" prop="createdTime" width="180">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.createdTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="120">
+            <template slot-scope="scope">
+              <el-button size="mini" type="primary" @click="handleReleaseSeats(scope.row)"
+                :disabled="scope.row.allocationStatus !== 1" class="release-seats-btn">
+                释放座位
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-drawer>
+
+    <!-- 释放座位数量输入弹窗 -->
+    <el-dialog title="释放座位" :visible.sync="releaseSeatsOpen" width="400px" custom-class="release-dialog" append-to-body>
+      <el-form :model="releaseForm" :rules="releaseRules" ref="releaseForm" label-width="100px">
+        <el-form-item label="释放数量" prop="releaseCount">
+          <el-input-number v-model="releaseForm.releaseCount" :min="1" :max="releaseForm.maxSeats" placeholder="请输入释放数量"
+            controls-position="right" style="width: 100%" />
+          <div class="form-tip">
+            <i class="el-icon-info"></i>
+            最大可释放数量:{{ releaseForm.maxSeats }}
+          </div>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="releaseSeatsOpen = false">取 消</el-button>
+        <el-button type="primary" @click="submitReleaseSeats()">确 定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRecords, getServerInfo, getRecords, delRecords, release, updateRecords, exportRecords, apply, batchUpdate } from "@/api/qw/applyIpad";
+
+export default {
+  name: "Records",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 提交状态
+      submitting: false,
+      // 选中数组
+      ids: [],
+      // 选中的行数据
+      selectedRows: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 分配记录表格数据
+      recordsList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        companyId: null,
+        companyName: null,
+        applicationNumber: null,
+        applyQuantity: null,
+        allocatedQuantity: null,
+        submitTime: null,
+        reviewTime: null,
+        auditStatus: null,
+        rejectionReason: null,
+        createdTime: null,
+        updatedTime: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        area: [
+          { required: true, message: "申请地区不能为空", trigger: "blur" }
+        ],
+        applyQuantity: [
+          { required: true, message: "申请数量不能为空", trigger: "blur" },
+          { pattern: /^[1-9]\d*$/, message: "申请数量必须为正整数", trigger: "blur" }
+        ]
+      },
+      // 释放抽屉显示状态
+      releaseOpen: false,
+      // 释放信息加载状态
+      releaseLoading: false,
+      // 服务器信息列表
+      serverInfoList: [],
+      // 释放座位弹窗显示状态
+      releaseSeatsOpen: false,
+      // 释放座位表单
+      releaseForm: {
+        releaseCount: null,
+        maxSeats: 0,
+        currentServer: null
+      },
+      // 释放座位表单校验规则
+      releaseRules: {
+        releaseCount: [
+          { required: true, message: "释放数量不能为空", trigger: "blur" },
+          { type: 'number', min: 1, message: "释放数量必须大于0", trigger: "blur" },
+          {
+            validator: (rule, value, callback) => {
+              if (value > this.releaseForm.maxSeats) {
+                callback(new Error(`释放数量不能超过${this.releaseForm.maxSeats}`));
+              } else {
+                callback();
+              }
+            },
+            trigger: "blur"
+          }
+        ]
+      },
+      // 当前选中的申请记录ID
+      currentRecordId: null,
+      // 统计数据
+      statistics: {
+        pending: 0,
+        approved: 0,
+        rejected: 0,
+        total: 0
+      }
+    };
+  },
+  computed: {
+    // 是否可以批量审核通过
+    canBatchApprove() {
+      return this.selectedRows.some(row => row.auditStatus === 0);
+    },
+    // 是否可以批量审核拒绝
+    canBatchReject() {
+      return this.selectedRows.some(row => row.auditStatus === 0);
+    }
+  },
+  created() {
+    this.getList();
+    this.calculateStatistics();
+    // 添加键盘事件监听
+    document.addEventListener('keydown', this.handleKeydown);
+  },
+  beforeDestroy() {
+    document.removeEventListener('keydown', this.handleKeydown);
+  },
+  methods: {
+    /** 查询分配记录列表 */
+    getList() {
+      this.loading = true;
+      listRecords(this.queryParams).then(response => {
+        this.recordsList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+        this.calculateStatistics();
+      });
+    },
+
+    /** 计算统计数据 */
+    calculateStatistics() {
+      this.statistics = {
+        pending: this.recordsList.filter(item => item.auditStatus === 0).length,
+        approved: this.recordsList.filter(item => item.auditStatus === 1).length,
+        rejected: this.recordsList.filter(item => item.auditStatus === 2).length,
+        total: this.recordsList.length
+      };
+    },
+
+    /** 键盘事件处理 */
+    handleKeydown(e) {
+      // Ctrl + N: 新建申请
+      if (e.ctrlKey && e.key === 'n') {
+        e.preventDefault();
+        this.handleAdd();
+      }
+      // Ctrl + E: 导出数据
+      if (e.ctrlKey && e.key === 'e') {
+        e.preventDefault();
+        this.handleExport();
+      }
+      // F5: 刷新数据
+      if (e.key === 'F5') {
+        e.preventDefault();
+        this.getList();
+      }
+    },
+
+    /** 切换搜索显示 */
+    toggleSearch() {
+      this.showSearch = !this.showSearch;
+    },
+
+    /** 表格头部样式 */
+    headerCellClass({ row, column, rowIndex, columnIndex }) {
+      return 'modern-header';
+    },
+
+    /** 表格单元格样式 */
+    cellClass({ row, column, rowIndex, columnIndex }) {
+      return 'modern-cell';
+    },
+
+    /** 行点击事件 */
+    handleRowClick(row, column, event) {
+      // 可以添加行点击后的处理逻辑
+    },
+
+    /** 获取状态样式类 */
+    getStatusClass(status) {
+      const statusMap = {
+        0: 'status-pending',
+        1: 'status-approved',
+        2: 'status-rejected',
+        3: 'status-partial'
+      };
+      return statusMap[status] || '';
+    },
+
+    /** 获取状态图标 */
+    getStatusIcon(status) {
+      const iconMap = {
+        0: 'el-icon-time',
+        1: 'el-icon-check',
+        2: 'el-icon-close',
+        3: 'el-icon-warning'
+      };
+      return iconMap[status] || 'el-icon-question';
+    },
+
+    /** 获取状态文本 */
+    getStatusText(status) {
+      const textMap = {
+        0: '待审核',
+        1: '审核通过',
+        2: '审核拒绝',
+        3: '部分分配'
+      };
+      return textMap[status] || '-';
+    },
+
+    /** 批量命令处理 */
+    handleBatchCommand(command) {
+      if (command === 'sync') {
+        this.handleBatchSync();
+      } else if (command === 'export') {
+        this.handleExport();
+      }
+    },
+
+    /** 批量审核通过 */
+    batchApprove() {
+      const pendingRows = this.selectedRows.filter(row => row.auditStatus === 0);
+      if (pendingRows.length === 0) {
+        this.msgWarning('没有可审核通过的记录');
+        return;
+      }
+
+      this.$confirm(`确认审核通过选中的 ${pendingRows.length} 条记录?`, '批量审核', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        // 这里调用批量审核通过的API
+        this.msgSuccess('批量审核通过成功');
+        this.getList();
+      });
+    },
+
+    /** 批量审核拒绝 */
+    batchReject() {
+      const pendingRows = this.selectedRows.filter(row => row.auditStatus === 0);
+      if (pendingRows.length === 0) {
+        this.msgWarning('没有可审核拒绝的记录');
+        return;
+      }
+
+      this.$confirm(`确认审核拒绝选中的 ${pendingRows.length} 条记录?`, '批量审核', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        // 这里调用批量审核拒绝的API
+        this.msgSuccess('批量审核拒绝成功');
+        this.getList();
+      });
+    },
+
+    /** 清空选择 */
+    clearSelection() {
+      this.$refs.multipleTable && this.$refs.multipleTable.clearSelection();
+      this.selectedRows = [];
+      this.ids = [];
+    },
+
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        area: null,
+        applyQuantity: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.selectedRows = selection;
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "申请iPad";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getRecords(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改分配记录";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          this.submitting = true;
+          // 调用apply接口,传递申请数量和地区作为参数对象
+          apply({
+            applyCount: this.form.applyQuantity,
+            area: this.form.area
+          }).then(response => {
+            this.msgSuccess("申请成功");
+            this.open = false;
+            this.getList();
+          }).catch(() => {
+            // this.msgError("申请失败");
+          }).finally(() => {
+            this.submitting = false;
+          });
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除分配记录编号为"' + ids + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delRecords(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => { });
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有分配记录数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportRecords(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => { });
+    },
+    /** 单个同步按钮操作 */
+    handleSingleSync(row) {
+      const id = row.id;
+      this.$confirm('是否确认同步编号为"' + id + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return batchUpdate([id]);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("同步成功");
+      }).catch(() => { });
+    },
+    /** 批量同步按钮操作 */
+    handleBatchSync() {
+      const ids = this.ids;
+      this.$confirm('是否确认同步选中的' + ids.length + '条数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return batchUpdate(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("批量同步成功");
+      }).catch(() => { });
+    },
+    /** 释放按钮操作 */
+    handleRelease(row) {
+      this.releaseLoading = true;
+      this.releaseOpen = true;
+      this.serverInfoList = [];
+      this.currentRecordId = row.id;
+
+      // 调用getServerInfo接口获取服务器信息
+      getServerInfo(row.id).then(response => {
+        this.serverInfoList = response.data || [];
+        this.releaseLoading = false;
+      }).catch(error => {
+        this.releaseLoading = false;
+        this.msgError("获取服务器信息失败");
+      });
+    },
+
+    /** 抽屉关闭处理 */
+    handleDrawerClose(done) {
+      this.releaseOpen = false;
+      done();
+    },
+
+    /** 释放座位按钮操作 */
+    handleReleaseSeats(server) {
+      this.releaseForm = {
+        releaseCount: null,
+        maxSeats: server.allocatedSeats || 0,
+        currentServer: server
+      };
+
+      this.releaseSeatsOpen = true;
+      this.$nextTick(() => {
+        this.$refs.releaseForm && this.$refs.releaseForm.clearValidate();
+      });
+    },
+
+    /** 提交释放座位 */
+    submitReleaseSeats() {
+      this.$refs.releaseForm.validate(valid => {
+        if (valid) {
+          // 根据后端ServerParam类结构组装参数
+          const params = {
+            ipadServerId: this.releaseForm.currentServer.ipadRecordId, // 服务器ID
+            recordId: this.currentRecordId,                 // 记录ID
+            releaseCount: this.releaseForm.releaseCount,    // 释放数量
+            ipAddress: this.releaseForm.currentServer.ipAddress, // iPad地址
+            port: this.releaseForm.currentServer.port       // 端口号
+          };
+
+          // 调用release接口
+          release(params).then(response => {
+            this.msgSuccess("释放成功");
+            this.releaseSeatsOpen = false;
+            // 重新加载服务器信息
+            this.handleRelease({ id: this.currentRecordId });
+          }).catch(error => {
+            this.msgError("释放失败");
+          });
+        }
+      });
+    },
+
+    /** 重置释放座位表单 */
+    resetReleaseForm() {
+      this.releaseForm = {
+        releaseCount: null,
+        maxSeats: 0,
+        currentServer: null
+      };
+      this.$refs.releaseForm && this.$refs.releaseForm.clearValidate();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  padding: 20px;
+  background: #f0f2f5;
+  min-height: calc(100vh - 84px);
+}
+
+// 统计卡片样式
+.statistics-cards {
+  margin-bottom: 20px;
+
+  .stat-card {
+    border-radius: 12px;
+    border: none;
+    transition: all 0.3s ease;
+
+    &:hover {
+      transform: translateY(-5px);
+      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
+    }
+
+    .stat-content {
+      display: flex;
+      align-items: center;
+      padding: 10px;
+
+      .stat-icon {
+        width: 60px;
+        height: 60px;
+        border-radius: 12px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-right: 15px;
+        font-size: 24px;
+        color: white;
+
+        &.pending {
+          background: #409eff;
+        }
+
+        &.approved {
+          background: #67c23a;
+        }
+
+        &.rejected {
+          background: #f56c6c;
+        }
+
+        &.total {
+          background: #909399;
+        }
+      }
+
+      .stat-info {
+        flex: 1;
+
+        .stat-value {
+          font-size: 28px;
+          font-weight: bold;
+          color: #2c3e50;
+          line-height: 1;
+        }
+
+        .stat-label {
+          font-size: 14px;
+          color: #7f8c8d;
+          margin-top: 5px;
+        }
+      }
+    }
+  }
+}
+
+// 搜索卡片样式
+.search-card {
+  border-radius: 12px;
+  margin-bottom: 20px;
+  border: none;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s ease;
+
+  &:hover {
+    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
+  }
+
+  .search-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-bottom: 15px;
+    border-bottom: 1px solid #ebeef5;
+    margin-bottom: 20px;
+
+    .search-title {
+      display: flex;
+      align-items: center;
+      font-size: 16px;
+      font-weight: 600;
+      color: #2c3e50;
+
+      i {
+        margin-right: 8px;
+        color: #409eff;
+      }
+    }
+  }
+
+  .search-form {
+
+    .search-input,
+    .search-select,
+    .search-date {
+      width: 100%;
+    }
+
+    .search-btn,
+    .reset-btn {
+      border-radius: 8px;
+      font-weight: 500;
+      transition: all 0.3s ease;
+    }
+
+    .search-btn:hover {
+      background-color: #66b1ff;
+    }
+
+    .reset-btn:hover {
+      color: #409eff;
+      border-color: #c6e2ff;
+      background-color: #ecf5ff;
+    }
+  }
+}
+
+// 批量操作工具栏
+.batch-toolbar {
+  margin-bottom: 20px;
+
+  .batch-card {
+    border-radius: 12px;
+    border: none;
+    background: #fdf6ec;
+
+    .batch-content {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .batch-info {
+        display: flex;
+        align-items: center;
+        color: #f39c12;
+        font-weight: 500;
+
+        i {
+          margin-right: 8px;
+          font-size: 18px;
+        }
+      }
+
+      .batch-actions {
+        display: flex;
+        gap: 10px;
+
+        .el-button {
+          border-radius: 6px;
+          font-weight: 500;
+        }
+      }
+    }
+  }
+}
+
+// 操作按钮区域
+.action-card {
+  border-radius: 12px;
+  margin-bottom: 20px;
+  border: none;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+
+  .action-bar {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .action-group {
+      display: flex;
+      gap: 15px;
+
+      .action-btn {
+        border-radius: 4px;
+        font-weight: 500;
+        transition: all 0.3s ease;
+
+        &:hover {
+          opacity: 0.8;
+        }
+      }
+    }
+  }
+}
+
+// 表格卡片样式
+.table-card {
+  border-radius: 12px;
+  border: none;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s ease;
+
+  &:hover {
+    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
+  }
+
+  .modern-table {
+    border-radius: 8px;
+    overflow: hidden;
+
+    ::v-deep .modern-header {
+      background: #f5f7fa;
+      color: #606266;
+      font-weight: 600;
+    }
+
+    ::v-deep .modern-cell {
+      .company-name {
+        display: flex;
+        align-items: center;
+
+        i {
+          margin-right: 5px;
+          color: #409eff;
+        }
+      }
+
+      .time-info {
+        display: flex;
+        align-items: center;
+        font-size: 12px;
+
+        i {
+          margin-right: 5px;
+          color: #909399;
+        }
+      }
+
+      .no-data {
+        color: #c0c4cc;
+      }
+
+      .rejection-reason {
+        max-width: 150px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        display: inline-block;
+      }
+    }
+
+    ::v-deep .el-table__row {
+      transition: all 0.3s ease;
+
+      &:hover {
+        background-color: #f5f7fa;
+      }
+    }
+
+    .action-buttons {
+      display: flex;
+      justify-content: center;
+      gap: 10px;
+
+      .action-icon-btn {
+        width: 32px;
+        height: 32px;
+        border-radius: 6px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        transition: all 0.3s ease;
+
+        &:hover {
+          transform: scale(1.1);
+        }
+
+        &.sync-btn {
+          color: #409eff;
+
+          &:hover {
+            background: rgba(64, 158, 255, 0.1);
+          }
+        }
+
+        &.release-btn {
+          color: #e6a23c;
+
+          &:hover {
+            background: rgba(230, 162, 60, 0.1);
+          }
+        }
+      }
+    }
+  }
+
+  .pagination-wrapper {
+    margin-top: 20px;
+    text-align: right;
+  }
+}
+
+// 状态标签样式
+.status-wrapper {
+  .el-tag {
+    border-radius: 20px;
+    padding: 4px 12px;
+    font-weight: 500;
+    border: none;
+
+    i {
+      margin-right: 5px;
+    }
+
+    &.status-pending {
+      background-color: #e1f3d8;
+      color: #67c23a;
+      border-color: #e1f3d8;
+    }
+
+    &.status-approved {
+      background-color: #f0f9ff;
+      color: #409eff;
+      border-color: #f0f9ff;
+    }
+
+    &.status-rejected {
+      background-color: #fef0f0;
+      color: #f56c6c;
+      border-color: #fef0f0;
+    }
+
+    &.status-partial {
+      background-color: #fdf6ec;
+      color: #e6a23c;
+      border-color: #fdf6ec;
+    }
+  }
+}
+
+// 对话框样式
+::v-deep .modern-dialog {
+  border-radius: 12px;
+
+  .el-dialog__header {
+    background: #f5f7fa;
+    color: #606266;
+    border-radius: 12px 12px 0 0;
+    padding: 20px;
+
+    .el-dialog__title {
+      font-weight: 600;
+    }
+  }
+
+  .el-dialog__body {
+    padding: 30px 20px;
+  }
+
+  .dialog-content {
+    .form-header {
+      display: flex;
+      align-items: center;
+      margin-bottom: 20px;
+      padding-bottom: 15px;
+      border-bottom: 1px solid #ebeef5;
+
+      i {
+        margin-right: 10px;
+        color: #409eff;
+        font-size: 20px;
+      }
+
+      span {
+        font-size: 16px;
+        font-weight: 600;
+        color: #2c3e50;
+      }
+    }
+
+    .modern-form {
+      .area-input {
+        width: 100%;
+      }
+      
+      .number-input {
+        width: 100%;
+      }
+
+      .form-tip {
+        display: flex;
+        align-items: center;
+        color: #909399;
+        font-size: 12px;
+        margin-top: 5px;
+
+        i {
+          margin-right: 5px;
+        }
+      }
+    }
+  }
+
+  .dialog-footer {
+    text-align: right;
+    padding: 15px 20px;
+    border-top: 1px solid #ebeef5;
+
+    .cancel-btn,
+    .confirm-btn {
+      border-radius: 8px;
+      font-weight: 500;
+      transition: all 0.3s ease;
+    }
+
+    .confirm-btn:hover {
+      background-color: #66b1ff;
+    }
+  }
+}
+
+// 抽屉样式
+::v-deep .modern-drawer {
+  .el-drawer__header {
+    background: #f5f7fa;
+    color: #606266;
+    padding: 20px;
+    margin-bottom: 0;
+
+    span {
+      font-weight: 600;
+    }
+  }
+
+  .drawer-content {
+    padding: 20px;
+
+    .server-table {
+      border-radius: 8px;
+      overflow: hidden;
+
+      .access-url {
+        color: #409eff;
+        text-decoration: none;
+
+        &:hover {
+          text-decoration: underline;
+        }
+
+        i {
+          margin-right: 5px;
+        }
+      }
+
+      .release-seats-btn {
+        border-radius: 6px;
+        font-weight: 500;
+      }
+    }
+  }
+}
+
+// 释放对话框样式
+::v-deep .release-dialog {
+  border-radius: 12px;
+
+  .el-dialog__header {
+    background: #f5f7fa;
+    color: #606266;
+    border-radius: 12px 12px 0 0;
+
+    .el-dialog__title {
+      font-weight: 600;
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 768px) {
+  .app-container {
+    padding: 10px;
+  }
+
+  .statistics-cards {
+    .el-col {
+      margin-bottom: 10px;
+    }
+  }
+
+  .search-form {
+    .el-col {
+      margin-bottom: 10px;
+    }
+  }
+
+  .action-bar {
+    flex-direction: column;
+    align-items: stretch;
+
+    .action-group {
+      margin-bottom: 10px;
+      justify-content: center;
+    }
+  }
+
+  .batch-content {
+    flex-direction: column;
+    align-items: flex-start;
+
+    .batch-actions {
+      margin-top: 10px;
+      flex-wrap: wrap;
+    }
+  }
+}
+</style>