<template>
<view class="detail-container">
<!-- 顶部索引板块 -->
<view class="index-card">
<u-form :model="formData" ref="indexForm" class="mobile-form">
<!-- 问卷标题 -->
<u-form-item label="问卷标题:" prop="dcWjTitle" label-width="150rpx">
<u-input
v-model="formData.dcWjTitle"
placeholder="请输入问卷标题"
clearable
border="bottom"
prefixIcon="file-text"
/>
</u-form-item>
<!-- 被测评人 -->
<u-form-item label="被测评人:" prop="dcId" label-width="150rpx">
<u-select
v-model="formData.dcId"
:list="bdrOptions"
multiple
value-name="dcId"
label-name="dcName"
@confirm="handleBdrSelect"
placeholder="请选择被测评人"
></u-select>
</u-form-item>
<!-- 人员部门 -->
<u-form-item label="人员部门:" prop="dcDept" label-width="150rpx">
<u-input
v-model="formData.dcDept"
placeholder="请输入人员部门"
clearable
border="bottom"
prefixIcon="home"
/>
</u-form-item>
<!-- 人员状态 -->
<u-form-item label="人员状态:" prop="state" label-width="150rpx">
<u-select
v-model="formData.state"
:list="stateOptions"
value-name="value"
label-name="label"
placeholder="请选择提交状态"
></u-select>
</u-form-item>
<!-- 按钮区域 -->
<view class="button-group">
<u-button
type="primary"
@click="handleSearch"
class="action-button"
icon="search"
>
搜索
</u-button>
<u-button
@click="handleReset"
class="action-button"
icon="reload"
>
重置
</u-button>
</view>
</u-form>
</view>
<!-- 数据显示区域 -->
<view class="data-card">
<view class="card-header">
<u-button
type="primary"
size="small"
icon="reload"
@click="fetchData"
>
刷新数据
</u-button>
</view>
<view class="card-container">
<!-- 数据加载状态 -->
<u-loading-page :loading="loading" loadingText="加载中..." />
<!-- 数据卡片 -->
<view
v-for="(item, index) in tableData"
:key="item.dcWjId"
class="data-card-item"
>
<!-- 顶部:问卷标题 -->
<view class="card-header-section">
<view class="card-title">{{ item.dcWjTitle }}</view>
</view>
<!-- 中间:其他数据 -->
<view class="card-body-section">
<view class="card-row">
<text class="card-label">被测评人:</text>
<text class="card-value">{{ item.dcName }}</text>
</view>
<view class="card-row">
<text class="card-label">部门:</text>
<text class="card-value">{{ item.dcDept }}</text>
</view>
<view class="card-row">
<text class="card-label">创建时间:</text>
<text class="card-value">{{ item.createTime }}</text>
</view>
<view class="card-row">
<text class="card-label">提交时间:</text>
<text class="card-value">{{ item.updateTime || '-' }}</text>
</view>
</view>
<!-- 底部:状态和操作按钮 -->
<view class="card-footer-section">
<view class="status-container">
<u-tag :text="item.state === '1' ? '已提交' : '未提交'"
:type="item.state === '1' ? 'success' : 'info'" />
<view class="score">总分: {{ item.score || '0' }}</view>
</view>
<u-button
size="small"
type="primary"
@click="handleView(item)"
class="action-btn"
>
编辑/查看
</u-button>
</view>
</view>
<!-- 空数据提示 -->
<u-empty v-if="tableData.length === 0" mode="data" />
</view>
<!-- 分页控件 -->
<view class="pagination-container">
<u-pagination
v-model="pagination.current"
:itemsPerPage="pagination.size"
:total="pagination.total"
:showTotal="true"
@change="handlePageChange"
/>
</view>
</view>
</view>
</template>
<script>
import { ref, reactive, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
export default {
setup() {
// 环境变量管理API地址 - 使用uni-app兼容方式
const API_BASE = 'http://172.26.26.43/dev-api'; // 替换为实际API地址
const API_URL = `${API_BASE}/wjdc/wj/listTx`;
const BDR_API_URL = `${API_BASE}/wjdc/wj/getBdrList`;
// 状态选项
const stateOptions = ref([
{ label: '已提交', value: 1 },
{ label: '未提交', value: 0 }
]);
// 被测评人相关数据
const bdrOptions = ref([]); // 被测评人选项列表
const bdrLoading = ref(false); // 加载状态
const bdrCache = ref([]); // 缓存所有被测评人数据
// 表单数据
const formData = reactive({
dcWjTitle: '',
dcId: [],
dcDept: '',
state: null
});
// 表格数据
const tableData = ref([]);
const loading = ref(false);
// 分页配置
const pagination = reactive({
current: 1,
size: 10,
total: 0
});
// 表单引用
const indexForm = ref(null);
// 处理被测评人选择
const handleBdrSelect = (selected) => {
formData.dcId = selected.map(item => item.value);
};
// 获取被测评人列表
const fetchBdrList = async () => {
const token = getAuthToken();
if (!token) return;
bdrLoading.value = true;
try {
const [err, res] = await uni.request({
url: BDR_API_URL,
method: 'GET',
header: {
'Authorization': `Bearer ${token}`
}
});
if (err) {
throw new Error(err.errMsg || '请求失败');
}
const data = res.data;
if (data && data.code === 200) {
bdrCache.value = data.data || [];
bdrOptions.value = bdrCache.value.map(item => ({
value: item.dcId,
label: item.dcName
}));
} else {
const msg = data?.msg || '返回数据格式不正确';
uni.showToast({
title: '获取被测评人列表失败: ' + msg,
icon: 'none'
});
}
} catch (error) {
console.error('获取被测评人列表失败:', error);
uni.showToast({
title: '获取被测评人列表失败: ' + error.message,
icon: 'none'
});
} finally {
bdrLoading.value = false;
}
};
const token = getAuthToken();
if (!token) return;
bdrLoading.value = true;
try {
const response = await uni.request({
url: BDR_API_URL,
method: 'GET',
params: {
pageNum: pagination.current,
pageSize: pagination.size,
...formData,
dcId: formData.dcId.join(',')
},
header: {
'Authorization': `Bearer ${token}`
}
});
const data = response[1].data;
if (data && data.code === 200) {
bdrCache.value = data.data || [];
bdrOptions.value = bdrCache.value.map(item => ({
value: item.dcId,
label: item.dcName
}));
} else {
const msg = data?.msg || '返回数据格式不正确';
uni.showToast({
title: '获取被测评人列表失败: ' + msg,
icon: 'none'
});
}
} catch (error) {
console.error('获取被测评人列表失败:', error);
uni.showToast({
title: '获取被测评人列表失败',
icon: 'none'
});
} finally {
bdrLoading.value = false;
}
};
// 获取认证令牌
const getAuthToken = () => {
const token = uni.getStorageSync('token');
if (!token) {
uni.showToast({
title: '请先登录',
icon: 'none'
});
uni.navigateTo({
url: '/pages/login/login'
});
return null;
}
return token;
};
// 搜索按钮处理函数
const handleSearch = () => {
// 检查被测评人选择数量
if (formData.dcId.length > 1) {
uni.showToast({
title: '当前只能搜索一个被测人员',
icon: 'none',
duration: 3000
});
return;
}
pagination.current = 1;
fetchData();
};
// 重置按钮处理函数
const handleReset = () => {
formData.dcWjTitle = '';
formData.dcId = [];
formData.dcDept = '';
formData.state = null;
handleSearch();
};
// 编辑/查看
const handleView = (row) => {
uni.navigateTo({
url: `/pages/operation/operation?id=${row.dcWjId}`
});
};
// 页码改变
const handlePageChange = (page) => {
pagination.current = page;
fetchData();
};
// 获取数据
const fetchData = async () => {
const token = getAuthToken();
if (!token) return;
loading.value = true;
try {
const params = {
pageNum: pagination.current,
pageSize: pagination.size,
...formData,
dcId: formData.dcId.join(',')
};
const [err, res] = await uni.request({
url: API_URL,
method: 'GET',
data: params,
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
if (err) {
throw new Error(err.errMsg || '请求失败');
}
const data = res.data;
if (data && data.code === 200) {
tableData.value = data.rows || [];
pagination.total = data.total || 0;
if (tableData.value.length === 0) {
uni.showToast({
title: '没有找到匹配的数据',
icon: 'none'
});
}
} else {
const errorMsg = data?.msg || '未知错误';
console.error('API返回错误:', errorMsg);
uni.showToast({
title: `请求失败: ${errorMsg}`,
icon: 'none'
});
tableData.value = [];
pagination.total = 0;
}
} catch (error) {
// ... 错误处理 ...
} finally {
loading.value = false;
}
};
const token = getAuthToken();
if (!token) return;
loading.value = true;
try {
const params = {
pageNum: pagination.current,
pageSize: pagination.size,
...formData,
dcId: formData.dcId.join(',')
};
const response = await uni.request({
url: API_URL,
method: 'GET',
data: params,
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
const data = response[1].data;
if (data && data.code === 200) {
tableData.value = data.rows || [];
pagination.total = data.total || 0;
if (tableData.value.length === 0) {
uni.showToast({
title: '没有找到匹配的数据',
icon: 'none'
});
}
} else {
const errorMsg = data?.msg || '未知错误';
console.error('API返回错误:', errorMsg);
uni.showToast({
title: `请求失败: ${errorMsg}`,
icon: 'none'
});
tableData.value = [];
pagination.total = 0;
}
} catch (error) {
// 安全地访问错误属性
const statusCode = error.statusCode || error.errMsg?.match(/status code (\d+)/)?.[1];
if (statusCode === '401') {
uni.showToast({
title: '认证过期,请重新登录',
icon: 'none'
});
uni.removeStorageSync('token');
uni.navigateTo({
url: '/pages/login/login'
});
return;
}
console.error('获取数据失败:', error);
// 安全地获取错误信息
let errorMsg = '网络请求失败';
if (error.errMsg) {
errorMsg = error.errMsg;
} else if (error.message) {
errorMsg = error.message;
} else if (typeof error === 'string') {
errorMsg = error;
}
uni.showToast({
title: `请求失败: ${errorMsg}`,
icon: 'none'
});
tableData.value = [];
pagination.total = 0;
} finally {
loading.value = false;
}
};
onMounted(() => {
fetchBdrList();
fetchData();
});
return {
formData,
bdrOptions,
stateOptions,
tableData,
loading,
pagination,
indexForm,
handleBdrSelect,
handleSearch,
handleReset,
handleView,
handlePageChange,
fetchData
};
}
};
</script>
<style>
.detail-container {
padding: 20rpx;
background-color: #f8f8f8;
min-height: 100vh;
}
.index-card {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.05);
}
.mobile-form .u-form-item {
margin-bottom: 32rpx;
}
.mobile-form .u-input,
.mobile-form .u-select {
background: #f8f8f8;
border-radius: 12rpx;
padding: 20rpx;
margin-top: 12rpx;
}
.button-group {
display: flex;
justify-content: space-between;
margin-top: 24rpx;
}
.button-group .action-button {
flex: 1;
margin: 0 12rpx;
height: 80rpx;
border-radius: 12rpx;
font-size: 32rpx;
}
.data-card {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.05);
}
.data-card .card-header {
margin-bottom: 24rpx;
display: flex;
justify-content: flex-end;
}
.card-container .data-card-item {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
border: 1rpx solid #eee;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.card-container .card-header-section {
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f0f2f5;
margin-bottom: 20rpx;
}
.card-container .card-header-section .card-title {
font-size: 34rpx;
font-weight: bold;
color: #333;
}
.card-container .card-body-section {
margin-bottom: 20rpx;
}
.card-container .card-row {
display: flex;
margin-bottom: 16rpx;
font-size: 30rpx;
line-height: 1.6;
}
.card-container .card-label {
color: #666;
min-width: 150rpx;
}
.card-container .card-value {
color: #333;
flex: 1;
}
.card-container .card-footer-section {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 20rpx;
border-top: 1rpx solid #f0f2f5;
}
.card-container .status-container {
display: flex;
align-items: center;
}
.card-container .status-container .score {
margin-left: 24rpx;
font-size: 30rpx;
color: #e6a23c;
font-weight: 500;
}
.card-container .action-btn {
min-width: 180rpx;
}
.pagination-container {
margin-top: 40rpx;
display: flex;
justify-content: center;
}
/* 响应式调整 - 移动端 */
@media (max-width: 768px) {
.button-group {
flex-direction: column;
}
.button-group .action-button {
margin: 12rpx 0;
width: 100%;
}
.card-container .card-footer-section {
flex-direction: column;
align-items: flex-start;
}
.card-container .status-container {
margin-bottom: 20rpx;
}
.card-container .action-btn {
width: 100%;
}
}
</style>
报错:18:40:24.208 [plugin:vite:vue] [vue/compiler-sfc] Unexpected reserved word 'await'. (258:25)
18:40:24.208 D:/民意测评/vue3-uni-mycp/pages/detail/detail.vue
18:40:24.208 256|
18:40:24.208 257| try {
18:40:24.208 258| const response = await uni.request({
18:40:24.208 | ^
18:40:24.208 259| url: BDR_API_URL,
18:40:24.208 260| method: 'GET',
18:40:24.208 at pages/detail/detail.vue:258:25
最新发布