feat:移动端整改 增加会员查询页面

This commit is contained in:
2026-11-05 20:58:18 +08:00
parent e744b7c271
commit f83513d8f1
2 changed files with 196 additions and 1 deletions
@@ -121,11 +121,12 @@ public class MemberMobileController {
@ViReturn
@RequiresRoles(value = {"H04", "A06"}, logical = Logical.OR)
public Object viewInfo(String id) {
// 用户表仅存储出生日期,按当前日期计算周岁,空出生日期返回空年龄。
Sql sql = Sqls.create("""
SELECT
u.username,
u.sex,
u.age,
TIMESTAMPDIFF(YEAR, NULLIF(u.birthday, ''), CURDATE()) AS age,
u.nation,
u.education,
u.political,
@@ -0,0 +1,194 @@
<!--#
layout("/mobile/platform.html"){
#-->
<style>
.member-query-header {
position: sticky;
top: 0;
z-index: 10;
background-color: #fff;
}
.member-query-list {
padding: 10px 0 20px;
}
.member-query-count {
padding: 0 16px 10px;
color: #969799;
font-size: 13px;
}
.member-query-detail {
height: 85%;
padding-bottom: env(safe-area-inset-bottom);
box-sizing: border-box;
}
.member-query-detail .van-cell__value,
.member-query-list .van-cell__value {
overflow-wrap: anywhere;
white-space: pre-wrap;
}
.member-query-loading {
padding: 40px 0;
text-align: center;
}
</style>
<div id="app" v-cloak>
<div class="member-query-header">
<van-nav-bar title="会员查询" left-arrow placeholder fixed
@click-left="location.replace('/mobile/index')"></van-nav-bar>
<form action="/mobile/member/query" @submit.prevent="doSearch">
<van-search v-model="keyword" placeholder="请输入姓名或工号" label="会员" show-action
@search="doSearch" @clear="doSearch">
<template #action>
<van-button type="primary" size="small" native-type="button" @click="doSearch">搜索</van-button>
</template>
</van-search>
</form>
</div>
<div class="member-query-list">
<div v-if="tableData.length" class="member-query-count">共 {{pageForm.totalCount}} 位会员</div>
<van-list v-model="loading" :finished="finished" :error.sync="loadError"
error-text="加载失败,点击重试" :finished-text="tableData.length ? '没有更多了' : ''"
:immediate-check="false" @load="onLoad">
<div v-for="o in tableData" :key="o.id" class="list-card">
<van-cell-group inset>
<van-cell :border="false" title="姓  名">{{o.username || '—'}}</van-cell>
<van-cell :border="false" title="工  号">{{o.loginname || '—'}}</van-cell>
<van-cell :border="false" title="所在工会">{{o.unionname || '—'}}</van-cell>
<van-cell :border="false" title="所在单位">{{o.unitname || '—'}}</van-cell>
<van-cell :border="false" title="人员类型">{{o.personType || '—'}}</van-cell>
</van-cell-group>
<van-cell title="查看会员详情" is-link clickable @click="openView(o)"></van-cell>
</div>
</van-list>
<van-empty v-if="!loading && !loadError && finished && tableData.length === 0"
image="/none.svg" description="暂无符合条件的会员"></van-empty>
</div>
<van-popup v-model="showDetail" position="bottom" round class="member-query-detail">
<van-nav-bar title="会员详情" left-arrow @click-left="showDetail = false"></van-nav-bar>
<div v-if="detailLoading" class="member-query-loading">
<van-loading size="24px" vertical>加载中...</van-loading>
</div>
<van-empty v-else-if="detailError" description="详情加载失败">
<van-button type="primary" size="small" @click="openView(selectedMember)">重试</van-button>
</van-empty>
<van-cell-group v-else-if="memberInfo">
<van-cell title="姓名" :value="memberInfo.username || '—'"></van-cell>
<van-cell title="性别" :value="memberInfo.sex || '—'"></van-cell>
<van-cell title="年龄" :value="memberInfo.age == null ? '—' : memberInfo.age"></van-cell>
<van-cell title="民族" :value="memberInfo.nation || '—'"></van-cell>
<van-cell title="学历" :value="memberInfo.education || '—'"></van-cell>
<van-cell title="政治面貌" :value="memberInfo.political || '—'"></van-cell>
<van-cell title="职称" :value="memberInfo.jobTitle || '—'"></van-cell>
<van-cell title="职务" :value="memberInfo.position || '—'"></van-cell>
<van-cell title="所在单位" :value="memberInfo.unitname || '—'"></van-cell>
<van-cell title="个人简历" :value="memberInfo.vita || '—'"></van-cell>
</van-cell-group>
<van-empty v-else description="暂无会员详情"></van-empty>
</van-popup>
</div>
<script>
// 复用移动端会员接口,在查询页内查看详情,保持与查询入口一致的角色权限。
const vue = new Vue({
el: '#app',
mixins: [mobileMixins],
data() {
return {
keyword: '',
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: ''
},
loadError: false,
requestId: 0,
pending: false,
showDetail: false,
detailLoading: false,
detailError: false,
detailRequestId: 0,
selectedMember: null,
memberInfo: null
}
},
methods: {
doSearch() {
// 新搜索使上一轮分页请求失效,避免较慢的旧响应混入新结果。
this.requestId++
this.pending = false
this.pageForm.pageNumber = 1
this.pageForm.totalCount = 0
this.pageForm.searchKeyword = this.keyword.trim()
this.tableData = []
this.finished = false
this.loadError = false
this.onLoad()
},
async onLoad() {
if (this.pending || this.finished) return
const requestId = this.requestId
this.pending = true
this.loading = true
this.loadError = false
try {
const res = await $.post('/mobile/member/getMemberData', Object.assign({}, this.pageForm))
if (requestId !== this.requestId) return
if (res.code !== 0 || !res.data || !Array.isArray(res.data.list)) {
throw new Error('会员查询失败')
}
this.tableData = this.tableData.concat(res.data.list)
this.pageForm.totalCount = res.data.totalCount
this.finished = res.data.list.length === 0 || this.tableData.length >= res.data.totalCount
if (!this.finished) this.pageForm.pageNumber++
} catch (e) {
if (requestId === this.requestId) this.loadError = true
} finally {
if (requestId === this.requestId) {
this.pending = false
this.loading = false
}
}
},
async openView(member) {
if (!member || !member.id) {
this.$toast.fail('缺少会员信息')
return
}
const requestId = ++this.detailRequestId
this.selectedMember = member
this.memberInfo = null
this.showDetail = true
this.detailLoading = true
this.detailError = false
try {
const res = await $.get('/mobile/member/viewInfo', {id: member.id})
if (requestId !== this.detailRequestId) return
if (res.code !== 0) throw new Error('会员详情加载失败')
this.memberInfo = res.data
} catch (e) {
if (requestId === this.detailRequestId) this.detailError = true
} finally {
if (requestId === this.detailRequestId) this.detailLoading = false
}
}
},
created() {
this.doSearch()
}
})
</script>
<!--#
}
#-->