297 lines
9.8 KiB
Vue
297 lines
9.8 KiB
Vue
<template>
|
||
<view class="page" :class="{ big: isH5 }">
|
||
<view class="panel">
|
||
<view class="section-title">查询</view>
|
||
<input class="input" v-model="keyword" placeholder="请输入姓名/编号" />
|
||
<button class="btn" type="primary" :disabled="loading" @click="onSearch">查询</button>
|
||
<button class="btn" :disabled="loading" @click="goHistory">查看历史综合报告</button>
|
||
<view v-if="errorMsg" class="error">{{ errorMsg }}</view>
|
||
</view>
|
||
|
||
<view v-if="loading" class="state">
|
||
<uni-icons type="spinner-cycle" size="28" color="#94AB38"></uni-icons>
|
||
<view class="state-text">加载中...</view>
|
||
</view>
|
||
<view v-else>
|
||
<view v-if="hasData" class="panel">
|
||
<view class="kv">
|
||
<view class="kv-item"><text class="k">用户ID</text><text class="v">{{ selectedUserId || '—' }}</text></view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="assessments.length" class="panel">
|
||
<view class="section-title">量表(测评)</view>
|
||
<view class="list">
|
||
<view class="item" v-for="row in assessments" :key="row.assessmentId" @click="openAssessmentDetail(row)">
|
||
<view class="item-title">{{ row.scaleName || ('量表#' + row.scaleId) }}</view>
|
||
<view class="item-desc">测评ID:{{ row.assessmentId }} · 状态:{{ statusText(row.status) }}</view>
|
||
<view class="item-foot">开始:{{ formatTime(row.startTime) }} · 提交:{{ formatTime(row.submitTime) }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="reports.length" class="panel">
|
||
<view class="section-title">报告</view>
|
||
<view class="list">
|
||
<view class="item" v-for="row in reports" :key="row.reportId" @click="openReportDetail(row)">
|
||
<view class="item-title">{{ row.reportTitle || ('报告#' + row.reportId) }}</view>
|
||
<view class="item-desc">类型:{{ row.reportType || '-' }} · 来源:{{ row.sourceType === 'questionnaire' ? '问卷' : '测评' }}</view>
|
||
<view class="item-foot">生成:{{ formatTime(row.generateTime) }} · 创建:{{ formatTime(row.createTime) }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="comprehensiveReports.length" class="panel">
|
||
<view class="section-title">综合报告</view>
|
||
<view class="list">
|
||
<view class="item" v-for="row in comprehensiveReports" :key="row.reportId" @click="openComprehensiveDetail(row)">
|
||
<view class="item-title">{{ row.reportTitle || ('综合报告#' + row.reportId) }}</view>
|
||
<view class="item-desc">创建:{{ formatTime(row.createTime) }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="!hasData" class="state">
|
||
<uni-icons type="paperplane" size="34" color="#CBD5E1"></uni-icons>
|
||
<view class="state-text">暂无报告</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { request } from '../../utils/request'
|
||
import { listAssessment } from '../../api/psychology/assessment'
|
||
import { listReport } from '../../api/psychology/report'
|
||
import { listComprehensiveReportsByUserId } from '../../api/psychology/comprehensiveReport'
|
||
import UniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'
|
||
|
||
export default {
|
||
components: {
|
||
UniIcons
|
||
},
|
||
data() {
|
||
return {
|
||
isH5: false,
|
||
keyword: '',
|
||
loading: false,
|
||
errorMsg: '',
|
||
selectedUserId: null,
|
||
assessments: [],
|
||
reports: [],
|
||
comprehensiveReports: []
|
||
}
|
||
},
|
||
onLoad() {
|
||
try {
|
||
const info = uni.getSystemInfoSync()
|
||
this.isH5 = info && info.uniPlatform === 'web'
|
||
} catch (e) {
|
||
this.isH5 = false
|
||
}
|
||
},
|
||
computed: {
|
||
hasData() {
|
||
return !!(this.selectedUserId && (this.assessments.length || this.reports.length || this.comprehensiveReports.length))
|
||
}
|
||
},
|
||
methods: {
|
||
goHistory() {
|
||
uni.navigateTo({ url: '/pages/comprehensive/history' })
|
||
},
|
||
formatTime(val) {
|
||
if (!val) return '—'
|
||
try {
|
||
const d = new Date(val)
|
||
if (isNaN(d.getTime())) return '—'
|
||
const y = d.getFullYear()
|
||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||
const day = String(d.getDate()).padStart(2, '0')
|
||
const hh = String(d.getHours()).padStart(2, '0')
|
||
const mm = String(d.getMinutes()).padStart(2, '0')
|
||
return `${y}-${m}-${day} ${hh}:${mm}`
|
||
} catch (e) {
|
||
return '—'
|
||
}
|
||
},
|
||
statusText(status) {
|
||
const map = { '0': '进行中', '1': '已完成', '2': '已作废', '3': '已暂停' }
|
||
return map[String(status)] || '未知'
|
||
},
|
||
openAssessmentDetail(row) {
|
||
if (!row || !row.assessmentId) return
|
||
uni.navigateTo({ url: `/pages/assessment/detail?assessmentId=${encodeURIComponent(row.assessmentId)}` })
|
||
},
|
||
openReportDetail(row) {
|
||
if (!row || !row.reportId) return
|
||
const url = `/pages/report/detail?reportId=${encodeURIComponent(row.reportId)}&sourceType=${encodeURIComponent(row.sourceType || '')}`
|
||
uni.navigateTo({ url })
|
||
},
|
||
openComprehensiveDetail(row) {
|
||
if (!row || !row.reportId) return
|
||
uni.navigateTo({ url: `/pages/comprehensive/detail?reportId=${encodeURIComponent(row.reportId)}` })
|
||
},
|
||
async onSearch() {
|
||
this.errorMsg = ''
|
||
this.loading = true
|
||
this.selectedUserId = null
|
||
this.assessments = []
|
||
this.reports = []
|
||
this.comprehensiveReports = []
|
||
try {
|
||
// 先通过学员选项接口把关键词解析成 userId
|
||
const userRes = await request({
|
||
url: `/psychology/assessment/student/options?keyword=${encodeURIComponent(this.keyword || '')}&limit=1`,
|
||
method: 'GET'
|
||
})
|
||
const userData = userRes && userRes.data ? userRes.data : null
|
||
if (!userData || userData.code !== 200) {
|
||
this.errorMsg = (userData && userData.msg) ? userData.msg : '查询失败'
|
||
this.loading = false
|
||
return
|
||
}
|
||
const list = userData.data || []
|
||
if (!list.length) {
|
||
this.errorMsg = '未找到匹配人员'
|
||
this.loading = false
|
||
return
|
||
}
|
||
this.selectedUserId = list[0].userId
|
||
|
||
const uid = this.selectedUserId
|
||
const [assRes, repRes, compRes] = await Promise.all([
|
||
listAssessment({ pageNum: 1, pageSize: 1000, userId: uid }),
|
||
listReport({ pageNum: 1, pageSize: 1000, userId: uid }),
|
||
listComprehensiveReportsByUserId(uid)
|
||
])
|
||
|
||
const assData = assRes && assRes.data ? assRes.data : null
|
||
if (assData && assData.code === 200) {
|
||
this.assessments = assData.rows || []
|
||
}
|
||
|
||
const repData = repRes && repRes.data ? repRes.data : null
|
||
if (repData && repData.code === 200) {
|
||
this.reports = repData.rows || []
|
||
}
|
||
|
||
const compData = compRes && compRes.data ? compRes.data : null
|
||
if (compData && compData.code === 200) {
|
||
this.comprehensiveReports = compData.data || []
|
||
}
|
||
this.loading = false
|
||
} catch (e) {
|
||
this.loading = false
|
||
this.errorMsg = e && e.message ? e.message : '网络错误'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.page {
|
||
min-height: 100vh;
|
||
padding: 24rpx 24rpx 120rpx;
|
||
box-sizing: border-box;
|
||
background: #F4F6FB;
|
||
}
|
||
.panel {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
border-radius: 18rpx;
|
||
padding: 24rpx;
|
||
border: 1px solid rgba(15, 23, 42, 0.06);
|
||
box-shadow: 0 10rpx 22rpx rgba(15, 23, 42, 0.05);
|
||
margin-bottom: 18rpx;
|
||
}
|
||
.section-title {
|
||
margin-top: 8rpx;
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: #111827;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
.input {
|
||
width: 100%;
|
||
background: rgba(15, 23, 42, 0.04);
|
||
border-radius: 16rpx;
|
||
padding: 26rpx 22rpx;
|
||
font-size: 32rpx;
|
||
line-height: 44rpx;
|
||
min-height: 92rpx;
|
||
box-sizing: border-box;
|
||
margin-bottom: 16rpx;
|
||
border: 1px solid rgba(15, 23, 42, 0.06);
|
||
}
|
||
.btn {
|
||
width: 100%;
|
||
margin-top: 12rpx;
|
||
border-radius: 16rpx;
|
||
}
|
||
.kv-item { display: flex; justify-content: space-between; padding: 12rpx 0; border-bottom: 1px solid rgba(15, 23, 42, 0.06); }
|
||
.kv-item:last-child { border-bottom: 0; }
|
||
.k { color: #94A3B8; font-size: 24rpx; }
|
||
.v { color: #111827; font-size: 24rpx; font-weight: 700; }
|
||
.list { margin-top: 8rpx; }
|
||
.item { background: rgba(255, 255, 255, 0.95); border-radius: 18rpx; padding: 18rpx; border: 1px solid rgba(15, 23, 42, 0.06); margin-bottom: 14rpx; }
|
||
.item-title { font-size: 28rpx; font-weight: 700; color: #111827; }
|
||
.item-desc { margin-top: 10rpx; font-size: 24rpx; color: #64748B; }
|
||
.item-foot { margin-top: 10rpx; font-size: 22rpx; color: #94A3B8; }
|
||
.state {
|
||
height: 360rpx;
|
||
border-radius: 20rpx;
|
||
background: rgba(255, 255, 255, 0.85);
|
||
border: 1px solid rgba(15, 23, 42, 0.06);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 12rpx;
|
||
}
|
||
.state-text {
|
||
font-size: 24rpx;
|
||
color: #94A3B8;
|
||
font-weight: 700;
|
||
}
|
||
.error { margin-top: 14rpx; font-size: 24rpx; color: #ff4d4f; line-height: 36rpx; }
|
||
.hint { margin-top: 10rpx; font-size: 22rpx; color: #8f959e; }
|
||
|
||
.page.big {
|
||
padding: 14rpx 14rpx 120rpx;
|
||
background-image:
|
||
radial-gradient(1100rpx 520rpx at 50% 14%, rgba(43, 107, 255, 0.30) 0%, rgba(6, 16, 40, 0.0) 65%),
|
||
linear-gradient(180deg, rgba(5, 11, 24, 0.90) 0%, rgba(8, 20, 45, 0.85) 42%, rgba(6, 16, 40, 0.92) 100%),
|
||
url('/static/bg.png');
|
||
background-size: auto, auto, cover;
|
||
background-position: center, center, center;
|
||
background-repeat: no-repeat, no-repeat, no-repeat;
|
||
}
|
||
.page.big .panel,
|
||
.page.big .item,
|
||
.page.big .state {
|
||
border: 1px solid rgba(116, 216, 255, 0.22);
|
||
background: linear-gradient(180deg, rgba(10, 18, 38, 0.75) 0%, rgba(5, 10, 22, 0.55) 100%);
|
||
box-shadow: 0 12rpx 24rpx rgba(0, 0, 0, 0.35);
|
||
}
|
||
.page.big .section-title,
|
||
.page.big .item-title,
|
||
.page.big .v {
|
||
color: rgba(235, 248, 255, 0.92);
|
||
}
|
||
.page.big .k,
|
||
.page.big .item-desc,
|
||
.page.big .item-foot,
|
||
.page.big .state-text {
|
||
color: rgba(201, 242, 255, 0.65);
|
||
}
|
||
.page.big .input {
|
||
background: rgba(7, 13, 28, 0.35);
|
||
border-color: rgba(116, 216, 255, 0.18);
|
||
color: rgba(235, 248, 255, 0.92);
|
||
}
|
||
.page.big .btn[type="primary"] {
|
||
background: linear-gradient(90deg, rgba(116, 216, 255, 0.95) 0%, rgba(43, 107, 255, 0.92) 100%);
|
||
color: #0b1226;
|
||
}
|
||
</style>
|