fix: 修复API接口规范和数据获取问题

1. 修复前端从res.rows改为res.data获取数据
2. 更新API接口基础规范文档:
   - 添加系统基础模块规范
   - 添加租户过滤规范
   - 统一返回值规范
   - 完善代码生成规范
This commit is contained in:
zlwu committed 2025-07-09 20:53:29 +08:00
1 parent 9b8e437c31
commit a4247ea901
2 files changed
+382 -33

No files matched your search

+189 -33
View File
@@ -37,23 +37,26 @@
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['hq:hallReservation:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['hq:hallReservation:edit']"
>修改</el-button
>
<el-button icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['hq:hallReservation:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['hq:hallReservation:remove']"
>删除</el-button
>
<el-button icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['hq:hallReservation:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button icon="Download" @click="handleExport" v-hasPermi="['hq:hallReservation:export']">导出</el-button>
<el-button icon="Download" @click="handleExport" v-hasPermi="['hq:hallReservation:export']">导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="hallReservationList" @selection-change="handleSelectionChange" style="margin-bottom: 0">
<el-table
v-loading="loading"
border
:data="hallReservationList"
@selection-change="handleSelectionChange"
style="margin-bottom: 0"
@row-dblclick="handleView"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="报告厅ID" align="center" prop="hallId" />
<el-table-column label="报告厅名称" align="center" prop="hallName" />
@@ -78,13 +81,9 @@
:hide-after="100"
effect="dark"
>
<span class="purpose-text">
{{
scope.row.reservationPurpose && scope.row.reservationPurpose.length > 100
? scope.row.reservationPurpose.substring(0, 100) + '...'
: scope.row.reservationPurpose
}}
</span>
<div class="purpose-text">
{{ scope.row.reservationPurpose }}
</div>
</el-tooltip>
</template>
</el-table-column>
@@ -110,17 +109,13 @@
:hide-after="100"
effect="dark"
>
<span class="audit-remark-text">
{{
scope.row.auditRemark && scope.row.auditRemark.length > 100
? scope.row.auditRemark.substring(0, 100) + '...'
: scope.row.auditRemark
}}
</span>
<div class="audit-remark-text">
{{ scope.row.auditRemark }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220" fixed="right">
<template #default="scope">
<!-- 查看按钮,所有记录都可以查看 -->
<el-tooltip content="查看" placement="top">
@@ -206,9 +201,9 @@
</el-select>
</el-form-item>
<!-- 报告厅图片展示区域 -->
<el-form-item label="报告厅图片" v-if="selectedHallImages.length > 0">
<el-form-item label="报告厅图片">
<div class="selected-hall-images">
<div class="image-gallery">
<div class="image-gallery" v-if="selectedHallImages.length > 0">
<div v-for="(image, index) in selectedHallImages" :key="index" class="image-item" @click="previewImage(image, index)">
<img :src="image" class="gallery-image" @error="handleImageError" />
<div class="image-overlay">
@@ -216,6 +211,10 @@
</div>
</div>
</div>
<div v-else class="no-images-placeholder">
<el-icon><Picture /></el-icon>
<span>暂无图片</span>
</div>
</div>
</el-form-item>
<el-form-item label="预约开始时间" prop="startTime">
@@ -226,6 +225,7 @@
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择预约开始时间"
style="width: 100%"
@change="handleStartTimeChange"
>
</el-date-picker>
</el-form-item>
@@ -269,9 +269,9 @@
<span class="form-text">{{ viewForm.hallName }}</span>
</el-form-item>
<!-- 报告厅图片展示区域 -->
<el-form-item label="报告厅图片" v-if="viewHallImages.length > 0">
<el-form-item label="报告厅图片">
<div class="view-hall-images">
<div class="image-gallery">
<div class="image-gallery" v-if="viewHallImages.length > 0">
<div v-for="(image, index) in viewHallImages" :key="index" class="image-item" @click="previewImage(image, index)">
<img :src="image" class="gallery-image" @error="handleImageError" />
<div class="image-overlay">
@@ -279,6 +279,10 @@
</div>
</div>
</div>
<div v-else class="no-images-placeholder">
<el-icon><Picture /></el-icon>
<span>暂无图片</span>
</div>
</div>
</el-form-item>
<el-form-item label="预约开始时间">
@@ -301,6 +305,19 @@
<el-form-item label="预约状态">
<dict-tag :options="hall_reserv_status" :value="viewForm.status" />
</el-form-item>
<!-- 当状态为审核中时显示可审核人员列表 -->
<el-form-item label="可审核人员" v-if="viewForm.status === '0' && auditorList.length > 0">
<div class="auditor-list">
<div v-for="auditor in auditorList" :key="auditor.userId" class="auditor-item">
<el-avatar :size="32" :src="auditor.avatar">{{ auditor.nickName?.substring(0, 1) }}</el-avatar>
<div class="auditor-info">
<div class="auditor-name">{{ auditor.nickName || auditor.userName }}</div>
<div class="auditor-dept">{{ auditor.dept?.deptName }}</div>
</div>
</div>
<div v-if="auditorList.length === 0" class="no-auditor">暂无可审核人员</div>
</div>
</el-form-item>
<el-form-item label="审核人" v-if="viewForm.auditName">
<span class="form-text">{{ viewForm.auditName }}</span>
</el-form-item>
@@ -325,7 +342,7 @@
<script setup name="HallReservation" lang="ts">
import { listHallReservation, getHallReservation, delHallReservation, addHallReservation, updateHallReservation } from '@/api/hq/hallReservation';
import { listHallInfo } from '@/api/hq/hallInfo';
import { getUserProfile } from '@/api/system/user';
import { getUserProfile, listUsersByPermission } from '@/api/system/user';
import { HallReservationVO, HallReservationQuery, HallReservationForm } from '@/api/hq/hallReservation/types';
import { HallInfoVO } from '@/api/hq/hallInfo/types';
import { useUserStore } from '@/store/modules/user';
@@ -375,6 +392,44 @@ const viewForm = ref<HallReservationForm>({
auditRemark: undefined
});
// 添加审核人员列表
const auditorList = ref<any[]>([]);
/** 获取具有审核权限的人员列表 */
const getAuditorList = async () => {
try {
const res = await listUsersByPermission('hq:hallAudit:list');
auditorList.value = res.data || [];
console.log('审核人员列表:', auditorList.value);
} catch (error) {
console.error('获取审核人员列表失败:', error);
auditorList.value = [];
}
};
/** 验证结束时间 */
const validateEndTime = (rule: any, value: any, callback: any) => {
if (value && form.value.startTime) {
const startTime = new Date(form.value.startTime).getTime();
const endTime = new Date(value).getTime();
if (endTime <= startTime) {
callback(new Error('结束时间必须晚于开始时间'));
} else {
callback();
}
} else {
callback();
}
};
/** 开始时间变化时触发结束时间验证 */
const handleStartTimeChange = () => {
// 如果结束时间已经填写,则触发验证
if (data.form.endTime) {
hallReservationFormRef.value?.validateField('endTime');
}
};
const initFormData: HallReservationForm = {
id: undefined,
hallId: undefined,
@@ -390,6 +445,7 @@ const initFormData: HallReservationForm = {
auditTime: undefined,
auditRemark: undefined
};
const data = reactive<PageData<HallReservationForm, HallReservationQuery>>({
form: { ...initFormData },
queryParams: {
@@ -409,7 +465,25 @@ const data = reactive<PageData<HallReservationForm, HallReservationQuery>>({
rules: {
hallName: [{ required: true, message: '报告厅名称不能为空', trigger: 'change' }],
startTime: [{ required: true, message: '预约开始时间不能为空', trigger: 'blur' }],
endTime: [{ required: true, message: '预约结束时间不能为空', trigger: 'blur' }],
endTime: [
{ required: true, message: '预约结束时间不能为空', trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (value && data.form.startTime) {
const startTime = new Date(data.form.startTime).getTime();
const endTime = new Date(value).getTime();
if (endTime <= startTime) {
callback(new Error('结束时间必须晚于开始时间'));
} else {
callback();
}
} else {
callback();
}
},
trigger: 'blur'
}
],
reservationPurpose: [{ required: true, message: '预约用途不能为空', trigger: 'blur' }]
}
});
@@ -635,6 +709,11 @@ const handleView = async (row: HallReservationVO) => {
const res = await getHallReservation(row.id);
Object.assign(viewForm.value, res.data);
// 如果状态是审核中,获取审核人员列表
if (viewForm.value.status === '0') {
await getAuditorList();
}
// 查找对应的报告厅并显示图片
if (viewForm.value.hallName) {
const selectedHall = hallList.value.find((hall) => hall.hallName === viewForm.value.hallName);
@@ -849,22 +928,28 @@ onMounted(() => {
/* 表格中预约用途文本样式 */
.purpose-text {
display: inline-block;
max-width: 100%;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
word-break: break-all;
word-wrap: break-word;
line-height: 1.4;
cursor: pointer;
max-height: 4.2em;
}
/* 表格中审核备注文本样式 */
.audit-remark-text {
display: inline-block;
max-width: 100%;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
word-break: break-all;
word-wrap: break-word;
line-height: 1.4;
cursor: pointer;
max-height: 4.2em;
}
/* 查看详情表单样式 */
@@ -923,6 +1008,7 @@ onMounted(() => {
display: flex;
flex-wrap: wrap;
gap: 12px;
max-width: 450px; /* 与预约用途保持一致 */
}
.image-item {
@@ -970,6 +1056,76 @@ onMounted(() => {
color: white;
font-size: 20px;
}
/* 暂无图片占位样式 */
.no-images-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 450px; /* 与预约用途保持一致 */
height: 120px;
background-color: #f5f7fa;
border: 2px dashed #dcdfe6;
border-radius: 8px;
color: #909399;
}
.no-images-placeholder .el-icon {
font-size: 32px;
margin-bottom: 8px;
}
.no-images-placeholder span {
font-size: 14px;
}
/* 审核人员列表样式 */
.auditor-list {
display: flex;
flex-wrap: wrap;
gap: 16px;
padding: 8px 0;
}
.auditor-item {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background-color: #f5f7fa;
border-radius: 8px;
transition: all 0.3s ease;
}
.auditor-item:hover {
background-color: #ecf5ff;
transform: translateY(-2px);
}
.auditor-info {
display: flex;
flex-direction: column;
}
.auditor-name {
font-size: 14px;
color: #303133;
font-weight: 500;
}
.auditor-dept {
font-size: 12px;
color: #909399;
}
.no-auditor {
color: #909399;
font-size: 14px;
font-style: italic;
}
/* 页面容器样式 */
</style>
<style>