234 lines
8.5 KiB
Vue
234 lines
8.5 KiB
Vue
<template>
|
|
<view class="page" :class="{ big: isH5 }">
|
|
<view class="panel">
|
|
<view class="filters">
|
|
<view class="chip" :class="{ active: query.sourceType === '' }" @click="setSource('')">全部</view>
|
|
<view class="chip" :class="{ active: query.sourceType === 'assessment' }" @click="setSource('assessment')">测评</view>
|
|
<view class="chip" :class="{ active: query.sourceType === 'questionnaire' }" @click="setSource('questionnaire')">问卷</view>
|
|
</view>
|
|
<view v-if="errorMsg" class="error">{{ errorMsg }}</view>
|
|
</view>
|
|
|
|
<view v-if="loading" class="state">
|
|
<uni-icons type="spinner-cycle" size="28" color="#94A3B8"></uni-icons>
|
|
<view class="state-text">加载中...</view>
|
|
</view>
|
|
<view v-else class="list">
|
|
<view v-if="rows.length === 0" class="state">
|
|
<uni-icons type="file-text" size="34" color="#CBD5E1"></uni-icons>
|
|
<view class="state-text">暂无数据</view>
|
|
</view>
|
|
<view v-else>
|
|
<view class="item" v-for="row in rows" :key="row.reportId" @click="openDetail(row)">
|
|
<view class="row">
|
|
<view class="badge" :class="row.sourceType === 'questionnaire' ? 'warn' : 'info'">
|
|
{{ row.sourceType === 'questionnaire' ? '问卷' : '测评' }}
|
|
</view>
|
|
<view class="item-title">{{ row.reportTitle || ('报告#' + row.reportId) }}</view>
|
|
</view>
|
|
<view class="item-desc">类型:{{ row.reportType || '-' }} · 信息编号:{{ row.infoNumber || '-' }}</view>
|
|
<view class="item-foot">生成:{{ formatTime(row.generateTime) }} · 创建:{{ formatTime(row.createTime) }}</view>
|
|
</view>
|
|
<view v-if="hasMore" class="load-more">上拉加载更多…</view>
|
|
<view v-else class="load-more">没有更多了</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { request } from '../../utils/request'
|
|
import { listReport } from '../../api/psychology/report'
|
|
import UniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'
|
|
|
|
export default {
|
|
components: {
|
|
UniIcons
|
|
},
|
|
data() {
|
|
return {
|
|
isH5: false,
|
|
loading: false,
|
|
errorMsg: '',
|
|
rows: [],
|
|
total: 0,
|
|
query: { pageNum: 1, pageSize: 10, sourceType: '' },
|
|
keyword: '',
|
|
userId: null
|
|
}
|
|
},
|
|
onLoad(options) {
|
|
try {
|
|
const info = uni.getSystemInfoSync()
|
|
const p = info ? (info.uniPlatform || info.platform) : ''
|
|
this.isH5 = p === 'web' || p === 'h5'
|
|
} catch (e) {
|
|
this.isH5 = false
|
|
}
|
|
this.keyword = (options && options.keyword) ? String(options.keyword) : ''
|
|
this.userId = null
|
|
this.refresh()
|
|
},
|
|
onPullDownRefresh() {
|
|
this.refresh().finally(() => uni.stopPullDownRefresh())
|
|
},
|
|
onReachBottom() {
|
|
if (this.loading || !this.hasMore) return
|
|
this.query.pageNum += 1
|
|
this.fetchList(true)
|
|
},
|
|
computed: {
|
|
hasMore() {
|
|
return this.rows.length < (this.total || 0)
|
|
}
|
|
},
|
|
methods: {
|
|
setSource(sourceType) {
|
|
if (this.loading) return
|
|
this.query.sourceType = sourceType
|
|
this.refresh()
|
|
},
|
|
refresh() {
|
|
this.query.pageNum = 1
|
|
this.rows = []
|
|
this.total = 0
|
|
return this.fetchList(false)
|
|
},
|
|
fetchList(append) {
|
|
this.errorMsg = ''
|
|
this.loading = true
|
|
const params = { pageNum: this.query.pageNum, pageSize: this.query.pageSize }
|
|
if (this.query.sourceType) params.sourceType = this.query.sourceType
|
|
|
|
const resolveUserId = () => {
|
|
if (this.userId) return Promise.resolve(this.userId)
|
|
const kw = (this.keyword || '').trim()
|
|
if (!kw) return Promise.resolve(null)
|
|
if (/^\d{1,18}$/.test(kw)) {
|
|
return request({
|
|
url: '/app/profile/options?keyword=' + encodeURIComponent(kw) + '&limit=1',
|
|
method: 'GET'
|
|
}).then((r) => {
|
|
const data = r && r.data ? r.data : null
|
|
if (!data || data.code !== 200) return null
|
|
const list = data.data || []
|
|
if (!list.length) return null
|
|
return list[0].userId || null
|
|
}).catch(() => null)
|
|
}
|
|
return request({
|
|
url: '/psychology/assessment/student/options?keyword=' + encodeURIComponent(kw) + '&limit=1',
|
|
method: 'GET'
|
|
}).then((r) => {
|
|
const data = r && r.data ? r.data : null
|
|
if (!data || data.code !== 200) return null
|
|
const list = data.data || []
|
|
if (!list.length) return null
|
|
return list[0].userId || null
|
|
}).catch(() => null)
|
|
}
|
|
|
|
return resolveUserId().then((uid) => {
|
|
if (uid) {
|
|
this.userId = uid
|
|
params.userId = uid
|
|
}
|
|
return listReport(params)
|
|
})
|
|
.then((res) => {
|
|
this.loading = false
|
|
const data = res && res.data ? res.data : null
|
|
if (!data || data.code !== 200) {
|
|
this.errorMsg = (data && data.msg) ? data.msg : '加载失败'
|
|
return
|
|
}
|
|
const list = data.rows || []
|
|
this.total = data.total || 0
|
|
this.rows = append ? this.rows.concat(list) : list
|
|
})
|
|
.catch((e) => {
|
|
this.loading = false
|
|
this.errorMsg = e && e.message ? e.message : '网络错误'
|
|
})
|
|
},
|
|
openDetail(row) {
|
|
if (!row || !row.reportId) return
|
|
const url = `/pages/report/detail?reportId=${encodeURIComponent(row.reportId)}&sourceType=${encodeURIComponent(row.sourceType || '')}`
|
|
uni.navigateTo({ url })
|
|
},
|
|
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 '—'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.page {
|
|
min-height: 100vh;
|
|
padding: 24rpx 24rpx 120rpx;
|
|
box-sizing: border-box;
|
|
background: #F4F6FB;
|
|
}
|
|
.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;
|
|
}
|
|
.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;
|
|
}
|
|
.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);
|
|
}
|
|
.filters { display: flex; flex-wrap: wrap; }
|
|
.chip { padding: 14rpx 22rpx; border-radius: 999rpx; font-size: 26rpx; color: #64748B; background: rgba(15, 23, 42, 0.04); margin-right: 16rpx; margin-bottom: 16rpx; min-height: 60rpx; display: flex; align-items: center; justify-content: center; }
|
|
.chip.active { color: #1677ff; background: rgba(22,119,255,0.12); }
|
|
.page.big .chip { color: rgba(201, 242, 255, 0.70); background: rgba(10, 18, 38, 0.65); border: 1px solid rgba(116, 216, 255, 0.20); }
|
|
.page.big .chip.active { color: #0b1226; background: linear-gradient(90deg, rgba(116, 216, 255, 0.95) 0%, rgba(43, 107, 255, 0.90) 100%); border-color: rgba(116, 216, 255, 0.5); }
|
|
.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; }
|
|
.row { display: flex; align-items: center; }
|
|
.badge { font-size: 22rpx; padding: 6rpx 14rpx; border-radius: 999rpx; margin-right: 14rpx; color: #fff; background: #8f959e; }
|
|
.badge.warn { background: #faad14; }
|
|
.badge.info { background: #1677ff; }
|
|
.item-title { font-size: 28rpx; font-weight: 700; color: #111827; flex: 1; }
|
|
.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; }
|
|
.load-more { text-align: center; color: #94A3B8; font-size: 22rpx; padding: 20rpx 0 6rpx; }
|
|
.error { margin-top: 14rpx; font-size: 24rpx; color: #ff4d4f; line-height: 36rpx; }
|
|
.page.big .item-title { color: rgba(235, 248, 255, 0.92); }
|
|
.page.big .item-desc,
|
|
.page.big .item-foot,
|
|
.page.big .state-text,
|
|
.page.big .load-more { color: rgba(201, 242, 255, 0.65); }
|
|
</style>
|