843f28df by lttnew

个人会员中心+注册+bug

1 parent 8b3e35cc
......@@ -1714,6 +1714,14 @@ export function unbindUser() {
})
}
// 电子会员证下载
export function downStuCertSingle(pId) {
return request({
url: `/person/info/downStuCertSingle/${pId}`,
method: 'post'
})
}
/**
* 订单列表
* @param params
......@@ -2028,3 +2036,45 @@ export function memBerAuditList(params) {
params: params
})
}
/**
* 结算审核列表
* @param params
* @returns {*}
*/
export function settlementList(params) {
return request({
url: '/exam/paymentSubmit/list',
method: 'get',
params: params
})
}
/**
* 结算审核(通过/拒绝)
* @param data { ids, type, reason }
* @returns {*}
*/
export function settlementAudit(data) {
return request({
url: `/exam/paymentSubmit/audit/${data.ids}`,
method: 'post',
params: {
type: data.type,
reason: data.reason
}
})
}
/**
* 结算详情列表(根据结算单ID获取关联的缴费单)
* @param params { payIds, pageNum, pageSize }
* @returns {*}
*/
export function settlementDetailList(params) {
return request({
url: '/exam/payment/list',
method: 'get',
params: params
})
}
......
......@@ -120,7 +120,8 @@ function requestPaymentCredential(encodedData) {
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: encodedData
data: encodedData,
timeout: 60000 // 60秒超时,与业务请求保持一致
})
}
......
......@@ -60,10 +60,13 @@ function handleTokenExpire() {
// 显示错误提示
function showError(msg) {
console.log('showError called:', msg)
// 先隐藏可能存在的 loading,确保 Toast 能显示
uni.hideLoading()
uni.showToast({
title: msg || '请求失败',
icon: 'none',
duration: 2000
duration: 3000
})
}
......@@ -119,9 +122,16 @@ const request = function (req) {
return
}
// 其他业务错误
showError(data.msg || '请求失败')
reject(new Error(data.msg || '请求失败'))
// 业务错误(code != 200 且非 Token 过期)- 统一显示错误提示
const errorMsg = data.msg || '操作失败'
showError(errorMsg)
// code == 500 时仅显示提示,不抛出异常,避免页面 catch 覆盖错误信息
if (data.code == 500) {
return
}
reject(new Error(errorMsg))
}).catch(error => {
console.error('请求失败:', error)
......@@ -139,9 +149,12 @@ const request = function (req) {
reject(error)
}).finally(() => {
// 延迟隐藏 loading,确保错误提示能显示
setTimeout(() => {
if (req.showLoading != false) {
hideLoading()
}
}, 100)
})
})
}
......
......@@ -13,15 +13,15 @@
<view class="vipData mt30" style="flex-wrap: wrap;padding: 20rpx;">
<view class="w50">
年限合计:
<text>{{ form?.renewYear }}</text>
<text>{{ form?.renewYear }}</text>
</view>
<view class="w50">
费用合计:
<text>{{ form?.allPrice }}</text>
<text>{{ form?.allPrice }}</text>
</view>
<view class="w50">
政策优惠:
<text>{{ form?.discount }}</text>
<text>{{ form?.discount }}</text>
</view>
<view class="w50">
付款费用:
......
......@@ -117,7 +117,7 @@
</view>
<view class="level-item">
<text class="level-label">考试级别</text>
<view class="select-wrapper" @click="changeLevelfather(n)">
<view class="select-wrapper exam-level-select" @click="changeLevelfather(n)">
<uni-data-select v-model="n.levelNew" :clear="false" :localdata="levelArr" @change="changeLevel"/>
</view>
</view>
......@@ -427,7 +427,10 @@ function getChosedStudentList() {
d.levelRecommend = '9'
}
if (!d.levelNew) {
// 原级别是一级时,levelNew 默认为空,不使用推荐值
if (d.levelOld === '1') {
d.levelNew = ''
} else if (!d.levelNew) {
d.levelNew = d.levelRecommend
}
......@@ -475,10 +478,21 @@ function szToHz(num) {
let nowRow
function changeLevelfather(row) {
nowRow = row
api.jiDropDownBox({
perId: row.perId
function changeLevelfather(row, flag = 0) {
const data = _.map(infoList.value, (d) => {
return {
id: d.id,
levelNew: d.levelNew,
// score: d.score,
isPass: d.isPass
}
})
api.editLevel({
examId: form.value.examId,
personInfo: JSON.stringify(data),
transcript: form.value.transcript,
// perId: row.perId,
status: flag
}).then(res => {
levelArr.value = res.data
for (let l of levelArr.value) {
......@@ -489,36 +503,43 @@ function changeLevelfather(row) {
}
function changeLevel(e) {
if (e == nowRow.levelOld) {
uni.showToast({title: '考试级别重复,请重新选择!', icon: 'none'})
nowRow.levelNew = nowRow.levelRecommend
return
}
if (e !== nowRow.levelRecommend) {
// 切换考试级别时弹出确认框
uni.showModal({
title: '提示',
content: `建议考试级别为 "${szToHz(nowRow.levelRecommend)}级" ,确定要修改为${szToHz(e)}级吗?`,
content: '请仔细核实本次等级申报是否正确!',
success: function (res) {
if (res.confirm) {
// 保存当前行数据
const data = _.map(infoList.value, (d) => {
return {
id: d.id,
levelNew: d.levelNew,
isPass: d.isPass
}
})
api.editLevel({
examId: form.value.examId,
personInfo: JSON.stringify(data),
transcript: form.value.transcript,
status: 0
}).then(() => {
// 保存成功后更新统计
getTablePersonInfo()
})
} else {
nowRow.levelNew = nowRow.levelRecommend
// 取消时恢复为推荐级别
nowRow.levelNew = nowRow.levelRecommend != 0 ? nowRow.levelRecommend : ''
}
},
fail: function (res) {
nowRow.levelNew = nowRow.levelRecommend
nowRow.levelNew = nowRow.levelRecommend != 0 ? nowRow.levelRecommend : ''
}
})
}
}
function submitForm2(flag) {
// 循环校验考试级别
// 循环校验考试级别是否选择(考试级别重复可以提交)
for (let item of infoList.value) {
if (item.levelNew == item.levelOld) {
uni.showToast({title: `${item.realName}考试级别重复,请重新选择!`, icon: 'none'})
return
}
if (!item.levelNew) {
uni.showToast({title: `${item.realName}请选择考试级别!`, icon: 'none'})
return
......@@ -536,16 +557,11 @@ function submitForm2(flag) {
content: `请确认人员照片是否已更新?`,
success: function (res) {
if (res.confirm) {
// saveStep2(flag).then(() => {
// uni.showToast({title: '提交成功', icon: 'none'})
// uni.navigateTo({
// url: `/level/paymentDetail?examId=${form.value.examId}`
// })
// })
saveStep2(flag).then(() => {
uni.navigateTo({
url: `/level/paymentDetail?examId=${form.value.examId}`
})
})
}
}
})
......@@ -866,7 +882,15 @@ function handleDelete(row) {
}
.select-wrapper {
width: 120rpx;
width: 160rpx;
position: relative;
z-index: 99;
}
.exam-level-select {
position: relative;
z-index: 999;
margin-bottom: 300rpx;
}
}
}
......
......@@ -23,9 +23,10 @@
<view class="date">注册地:{{n.memName||'-'}}</view>
</view>
<view class="status">
<text v-if="isChosen(n)" class="text-gray">已选</text>
<text v-if="isChosen(n)" class="text-chosen">已选</text>
<!-- <text v-else-if="n.canChoose != 1" class="text-gray">不可选</text> -->
<text v-if="n.canChoose == 1" class="text-primary" @click="handleChoose(n)">选择</text>
<text v-else-if="n.canChoose == 1" class="text-primary" @click="handleChoose(n)">选择</text>
<text v-else class="text-gray">不可选</text>
</view>
</view>
</view>
......@@ -146,6 +147,15 @@
}
function handleChoose(row) {
// 校验是否已被其他位置选中
if (isChosen(row)) {
uni.showToast({
title: '该考官已被选中,不能重复选择',
icon: 'none'
})
return
}
if (row.canChoose != 1) {
uni.showToast({
title: '该考官资质已过期!',
......@@ -215,7 +225,7 @@
success: (res) => {
if (res.confirm) {
uni.showLoading({ title: '添加中' })
api.selfAdd(app.globalData.memberInfo.memId, row.perId).then(() => {
api.selfAdd(row.perId).then(() => {
uni.hideLoading()
uni.showToast({ title: '添加成功', icon: 'success' })
addPopup.value.close()
......@@ -317,6 +327,11 @@
color: #999;
}
.text-chosen {
color: #AD181F;
font-weight: bold;
}
.text-danger {
color: #dd524d;
}
......
......@@ -63,7 +63,7 @@
<button class="btn-red" @click="login">登录</button>
</view>
<view class="center-item">
<text class="text-red" @click="goRegister">没有账号,去注册</text>
<button class="btn-red btn-register" @click="goRegister">没有账号,去注册</button>
</view>
</view>
<view class="wNumber">
......@@ -84,6 +84,25 @@
<image v-else src="@/static/login/xz2@2x.png"></image>
<view>登录即代表您同意<text>《用户协议》</text><text>《隐私策略》</text></view> -->
</view>
<!-- 注册提示弹框 -->
<uni-popup ref="registerPopup" type="center" :mask-click="false">
<view class="register-popup">
<view class="popup-title">注册提示</view>
<view class="popup-content">
<view class="popup-text">请准备以下材料,以便顺利完成注册</view>
<view class="popup-list">
<text>1. 单位营业执照(清晰照片)</text>
<text>2. 法人身份证正反面照片(清晰照片)</text>
<text>3. 单位营业执照(清晰照片)</text>
</view>
</view>
<view class="popup-btns">
<view class="popup-btn cancel" @click="closeRegisterPopup">取消</view>
<view class="popup-btn confirm" @click="confirmRegister">确定</view>
</view>
</view>
</uni-popup>
</view>
</template>
......@@ -107,6 +126,7 @@ const agree = ref(false)
const isRember = ref(true)
const loading = ref(false)
const codeUrl = ref(null)
const registerPopup = ref(null)
const inputstyle = ref({
borderColor: 'transparent',
fontSize: '30rpx'
......@@ -226,9 +246,17 @@ function login() {
}
function goRegister() {
const path = '/login/register'
registerPopup.value.open()
}
function closeRegisterPopup() {
registerPopup.value.close()
}
function confirmRegister() {
registerPopup.value.close()
uni.navigateTo({
url: path
url: '/login/register'
})
}
......@@ -517,4 +545,78 @@ function call(num) {
margin-right: 20rpx;
}
}
/* 注册按钮 */
.btn-register {
border-radius: 40rpx;
width: 600rpx;
line-height: 80rpx;
font-size: 36rpx;
background: #fff;
color: #AD181F;
border: 1rpx solid #AD181F;
margin: 0;
}
/* 注册提示弹框 */
.register-popup {
width: 600rpx;
background: #ffffff;
border-radius: 24rpx;
overflow: hidden;
}
.popup-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
text-align: center;
padding: 40rpx 30rpx 20rpx;
}
.popup-content {
padding: 20rpx 30rpx 40rpx;
}
.popup-text {
font-size: 28rpx;
color: #333;
margin-bottom: 20rpx;
}
.popup-list {
display: flex;
flex-direction: column;
gap: 16rpx;
padding-left: 10rpx;
}
.popup-list text {
font-size: 26rpx;
color: #666;
line-height: 1.5;
}
.popup-btns {
display: flex;
border-top: 1rpx solid #eee;
}
.popup-btn {
flex: 1;
height: 100rpx;
line-height: 100rpx;
text-align: center;
font-size: 30rpx;
}
.popup-btn.cancel {
color: #666;
border-right: 1rpx solid #eee;
}
.popup-btn.confirm {
color: #AD181F;
font-weight: 500;
}
</style>
......
......@@ -12,19 +12,19 @@
<form>
<view class="round-input-item">
<image class="icon" :src="config.baseUrl_api+'/fs/static/login/tag01@2x.png'"></image>
<uni-easyinput :styles="inputstyle" v-model="registerForm.telNo" placeholder="请输入手机号" />
<uni-easyinput :styles="inputstyle" v-model="registerForm.telNo" placeholder="请输入手机号" @blur="validateTelNo" />
</view>
<view class="round-input-item">
<image class="icon" :src="config.baseUrl_api+'/fs/static/login/tag02@2x.png'"></image>
<uni-easyinput :styles="inputstyle" v-model="registerForm.password" placeholder="密码" type="password"/>
<uni-easyinput :styles="inputstyle" v-model="registerForm.password" placeholder="密码" type="password" @blur="validatePassword" />
</view>
<view class="round-input-item">
<image class="icon" :src="config.baseUrl_api+'/fs/static/login/tag03@2x.png'"></image>
<uni-easyinput :styles="inputstyle" v-model="registerForm.password2" placeholder="确认密码" type="password"/>
<uni-easyinput :styles="inputstyle" v-model="registerForm.password2" placeholder="确认密码" type="password" @blur="validatePassword2" />
</view>
<view class="round-input-item">
<image class="icon" :src="config.baseUrl_api+'/fs/static/login/tag03@2x.png'"></image>
<uni-easyinput :styles="inputstyle" placeholder="图形验证码" v-model="registerForm.captcha" />
<uni-easyinput :styles="inputstyle" placeholder="图形验证码" v-model="registerForm.captcha" @blur="validateCaptcha" />
<image :src="codeUrl" @click="getCode" />
</view>
<view class="round-input-item">
......@@ -138,12 +138,20 @@ function register() {
groupMemberRegister(registerForm.value)
.then((res) => {
uni.showToast({
title: `恭喜你,您的账号 ${registerForm.value.telNo} 注册成功!`,
icon: 'none'
})
uni.showModal({
title: '提示',
content: `恭喜你,您的账号 ${registerForm.value.telNo} 注册成功!`,
confirmText: '去登录',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
registerForm.value = {}
setTimeout(goLogin, 2000)
goLogin()
} else {
// 取消,保持当前页面
}
}
})
})
}
......@@ -160,6 +168,58 @@ function validPassword(pwd) {
return (lowerRegex.test(pwd) && upperRegex.test(pwd) && digitRegex.test(pwd) && symbolRegex.test(pwd) && specific.test(pwd))
}
// 手机号校验
function validateTelNo() {
const telNo = registerForm.value.telNo
if (!telNo) {
uni.showToast({ title: '手机号不能为空', icon: 'none' })
return false
}
if (!/^1[3-9]\d{9}$/.test(telNo)) {
uni.showToast({ title: '手机号格式不正确', icon: 'none' })
return false
}
return true
}
// 密码校验
function validatePassword() {
const password = registerForm.value.password
if (!password) {
uni.showToast({ title: '密码不能为空', icon: 'none' })
return false
}
if (!validPassword(password)) {
uni.showToast({ title: '密码必须为8~18位大小写字母、数字和特殊符号组合', icon: 'none', duration: 3000 })
return false
}
return true
}
// 确认密码校验
function validatePassword2() {
const password2 = registerForm.value.password2
if (!password2) {
uni.showToast({ title: '确认密码不能为空', icon: 'none' })
return false
}
if (registerForm.value.password && password2 !== registerForm.value.password) {
uni.showToast({ title: '两次密码不一致', icon: 'none' })
return false
}
return true
}
// 图形验证码校验
function validateCaptcha() {
const captcha = registerForm.value.captcha
if (!captcha) {
uni.showToast({ title: '图形验证码不能为空', icon: 'none' })
return false
}
return true
}
function goLogin() {
let path = '/login/loginC';
uni.navigateTo({
......
......@@ -51,7 +51,7 @@
</uni-list-item>
<uni-list-item v-if="form.menCode" :rightText="form.menCode" title="会员编号"/>
<uni-list-item :rightText="form.name" title="机构名称"/>
<uni-list-item title="所属省份">
<!-- <uni-list-item title="所属省份">
<template v-slot:footer>
<view class="frrr">
<uni-data-picker v-model="form.belongProvinceId" :clear-icon="false" :localdata="options"
......@@ -59,7 +59,7 @@
</uni-data-picker>
</view>
</template>
</uni-list-item>
</uni-list-item> -->
<uni-list-item
v-if="authenticationStatusa != 1&&authenticationStatusa != 0&&authenticationStatusa != 3&&newResult||form.associateId&&form.associateId>0||activeStatus==1"
:rightText="form.creditCode"
......@@ -96,7 +96,8 @@
</view>
</template>
</uni-list-item>
<uni-list-item :rightText="form.companyName||'--'" title="营业执照名称"/>
<uni-list-item :rightText="form.creditCode||'--'" title="社会信用代码"/>
<uni-list-item clickable title="营业执照">
<template v-slot:footer>
<view v-if="form.businessLicenseArr&&form.businessLicenseArr?.length>0" class="frrr"
......
......@@ -96,13 +96,21 @@ async function getList() {
return uni.showToast({title: '请输入考官编号', icon: 'none'})
loading.value = true
try {
const res = await api.getCoachList(queryParams.value)
infoList.value = res.rows
total.value = res.total
infoList.value = res.rows || []
total.value = res.total || 0
} catch (err) {
console.error('获取考官列表失败:', err)
infoList.value = []
total.value = 0
} finally {
loading.value = false
}
// 空数组提示
if (infoList.value.length === 0) {
uni.showToast({title: '请核实考官编号、有效期及归属地!', icon: 'none'})
uni.showToast({title: '请核实考官编号、有效期及归属地', icon: 'none', duration: 2000})
}
}
......@@ -163,7 +171,8 @@ async function confirmAddExpireExaminer() {
uni.navigateBack({delta: 1})
} catch (err) {
console.log(err)
uni.showToast({title: '添加失败', icon: 'none'})
const errMsg = err?.data?.msg || err?.msg || '添加失败'
uni.showToast({title: errMsg, icon: 'none', duration: 3000})
} finally {
expirePopup.value.close()
currentExpireItem.value = null
......
......@@ -18,10 +18,10 @@
<uni-forms-item label="机构名称" required>
<uni-easyinput v-model="form.name" :disabled="type" placeholder="机构名称" /></uni-forms-item>
<uni-forms-item label="所属省份" required>
<!-- <uni-forms-item label="所属省份" required>
<uni-data-select :clear="false" :disabled="type&&(belongProvinceId||belongProvinceId==0)"
v-model="form.belongProvinceId" :localdata="regionsList"></uni-data-select>
</uni-forms-item>
</uni-forms-item> -->
<uni-forms-item label="社会信用代码" required>
<uni-easyinput v-model="form.creditCode" :disabled="type&&!!creditCode&&newResult" />
</uni-forms-item>
......@@ -43,13 +43,11 @@
<uni-forms-item label="法人证件号" required>
<uni-easyinput v-model="form.legalIdcCode" />
</uni-forms-item>
<uni-forms-item label="营业执照名称" required>
<uni-easyinput v-model="form.companyName" />
</uni-forms-item>
<uni-forms-item v-if="form.deptType==6&&activeStatus!= 0" label="是否申请考点" required>
<!-- <uni-forms-item v-if="form.deptType==6&&activeStatus!= 0" label="是否申请考点" required>
<uni-data-checkbox v-model="form.applyPoints" :localdata="yesno" />
</uni-forms-item>
</uni-forms-item> -->
<uni-forms-item label="法人身份证" required>
<view class="imgArea">
......@@ -63,11 +61,17 @@
</uni-file-picker>
</view>
</uni-forms-item>
<uni-forms-item label="营业执照名称" required>
<uni-easyinput v-model="form.companyName" />
</uni-forms-item>
<uni-forms-item label="营业执照" required>
<uni-file-picker limit="1" v-model="businessLicenseArr" file-extname="png,jpg,jpeg,pdf"
file-mediatype="all" @select="selectFile" @delete="delSupplementFile"></uni-file-picker>
</uni-forms-item>
<!-- <uni-forms-item label="社会信用代码" required>
<uni-file-picker limit="1" v-model="businessLicenseArr" file-extname="png,jpg,jpeg,pdf"
file-mediatype="all" @select="selectFile" @delete="delSupplementFile"></uni-file-picker>
</uni-forms-item> -->
<uni-forms-item label="机构照片" required>
<uni-file-picker v-model="picArrR" limit="3" mode="grid" file-mediatype="image"
@select="upPicArr" @delete="delpicArr">
......
......@@ -240,6 +240,13 @@
"navigationBarTitleText": "我的订单",
"enablePullDownRefresh": false
}
},
{
"path": "certPreview",
"style": {
"navigationBarTitleText": "电子会员证",
"enablePullDownRefresh": false
}
}
]
},
......@@ -876,6 +883,20 @@
"navigationBarTitleText": "考生信息",
"enablePullDownRefresh": false
}
},
{
"path": "settlementAudit",
"style": {
"navigationBarTitleText": "结算审核",
"enablePullDownRefresh": false
}
},
{
"path": "settlementView",
"style": {
"navigationBarTitleText": "结算详情",
"enablePullDownRefresh": false
}
}
]
}, {
......
......@@ -239,18 +239,23 @@
<image :src="config.baseUrl_api+'/fs/static/icon/2.png'"/>
考试审核
</view>
<view @click="goPath('/level/ztx/cert?type=1')">
<image :src="config.baseUrl_api+'/fs/static/icon/18.png'"/>
证书发布
</view>
<view @click="goPath('/level/ztx/mail')">
<image :src="config.baseUrl_api+'/fs/static/icon/3.png'"/>
证书邮寄
</view>
<view @click="goPath('/level/ztx/cert?type=1')">
<image :src="config.baseUrl_api+'/fs/static/icon/18.png'"/>
证书发布
</view>
<view @click="goPath('/personalVip/changeLevelAudit')">
<image :src="config.baseUrl_api+'/fs/static/icon/26.png'"/>
变更审核
</view>
<view @click="goPath('/level/settlementAudit')">
<image :src="config.baseUrl_api+'/fs/static/icon/10.png'"/>
结算审核
</view>
<view @click="goPath('/personalVip/order?type=2')">
<image :src="config.baseUrl_api+'/fs/static/icon/6.png'"/>
订单列表
......
......@@ -284,7 +284,7 @@
getDetail()
getRegionsList()
getMyMemberCertUnitFeeApi()
// getMyMemberCertUnitFeeApi()
canUseDiscountApi()
getZtxDiscountPolicyApi()
getMyStatusAPI()
......
......@@ -176,7 +176,7 @@
// 审核
function goApproval(item) {
uni.navigateTo({
url: `/pages/rank/scoreAudit?ids=${item.examId}&pageType=2`
url: `/pages/rank/scoreAudit?ids=${item.examId}&pageType=1`
})
}
</script>
......
......@@ -87,12 +87,16 @@
delete params.reason
}
try {
// 根据 pageType 自动切换接口
// 根据 pageType 1 审核考试 2 审核成绩 3 结算审核
if (pageType.value == '1') {
await api.auditDuanExam(params);
} else if (pageType.value == '2') {
await api.auditDuanScore(params);
} else if (pageType.value == '3') {
params.type = '1' // 结算审核固定 type = 1
await api.settlementAudit(params);
} else {
uni.showToast({ title: '页面类型错误', icon: 'none' });
submitting.value = false;
......
......@@ -51,6 +51,14 @@
<uni-easyinput :styles="inputstyle" :placeholderStyle="placeholderStyle"
v-model="baseFormData.phone" placeholder="请输入联系方式" />
</uni-forms-item>
<uni-forms-item label="会员编号" name="perCode" v-if="baseFormData.perCode">
<uni-easyinput :styles="inputstyle" :placeholderStyle="placeholderStyle"
v-model="baseFormData.perCode" placeholder="请输入会员编号" />
</uni-forms-item>
<uni-forms-item label="会员有效期" name="validityDate" v-if="baseFormData.validityDate">
<uni-easyinput :styles="inputstyle" :placeholderStyle="placeholderStyle"
v-model="baseFormData.validityDate" placeholder="请输入会员有效期" />
</uni-forms-item>
<!-- <uni-forms-item label="所在地区">
......@@ -148,6 +156,8 @@
sex: '',
idcType: '0',
perType: '1', // (1:个人会员;2:教练;3:考官;4:裁判;5:临时会员;)
perCode:'',
validityDate:''
})
const items = ref(['身份证添加', '证件照录入'])
const idcTypeList = ref([{
......@@ -199,7 +209,7 @@
height: '316rpx'
});
onLoad((option) => {
onLoad(async (option) => {
if (option.tab == '1') {
current.value = 1
baseFormData.value.sourceFlag = 1
......@@ -210,8 +220,11 @@
disabledName.value = true
}
}
// console.log(current.value,option.tab)
// getRegionsList()
// 如果传入了 perId,预填会员信息
if (option.perId) {
perId.value = option.perId
await fetchMemberInfo(option.perId)
}
})
onMounted(() => {
......@@ -227,6 +240,40 @@
})
}
// 根据 perId 获取会员信息预填表单
async function fetchMemberInfo(id) {
if (!id) return
uni.showLoading({ title: '加载中...' })
try {
const res = await api.getInfo(id)
const data = res.data || {}
baseFormData.value.name = data.name || ''
baseFormData.value.idcCode = data.idcCode || ''
baseFormData.value.idcType = data.idcType || '0'
baseFormData.value.sex = data.sex || ''
baseFormData.value.birth = data.birth || ''
baseFormData.value.phone = data.phone || ''
baseFormData.value.perCode = data.perCode || ''
baseFormData.value.validityDate = data.validityDate ? data.validityDate.slice(0, 10) : ''
// 照片处理
if (data.photo2) {
const photoUrl = data.photo2.indexOf('http') === -1 ? config.baseUrl_api + data.photo2 : data.photo2
photoArr.value = {
url: photoUrl,
name: '头像',
extname: 'jpg'
}
baseFormData.value.photo = data.photo
baseFormData.value.photo2 = data.photo2
}
disabledName.value = true
} catch (e) {
console.error('获取会员信息失败', e)
} finally {
uni.hideLoading()
}
}
function onClickItem(e) {
if (current.value != e.currentIndex) {
current.value = e.currentIndex
......@@ -277,6 +324,8 @@
baseFormData.value.idcCode = res.data.code
baseFormData.value.name = res.data.name
baseFormData.value.uuid = res.data.uuid
baseFormData.value.perCode = res.data.perCode ||''
baseFormData.value.validityDate = res.data.validityDate?.slice(0,10) //去掉时分秒
// baseFormData.value.cityId = res.data.cityId
// baseFormData.value.address = res.data.address
} else {
......@@ -363,6 +412,8 @@
baseFormData.value.birth = res.data.birth
baseFormData.value.name = res.data.name
baseFormData.value.phone = res.data.phone
baseFormData.value.perCode = res.data.perCode ||''
baseFormData.value.validityDate = res.data.validityDate?.slice(0,10) //去掉时分秒
// baseFormData.value.cityId = res.data.cityId
// baseFormData.value.address = res.data.address
if (res.data.photo) {
......
<template>
<view class="preview-container">
<view class="loading-tip" v-if="loading">加载中...</view>
<view class="error-tip" v-else-if="showError">{{ errorMsg }}</view>
<view class="download-btn" @click="openDocument">
<text>查看会员证</text>
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import config from "@/config.js";
const pdfUrl = ref("");
const loading = ref(true);
const showError = ref(false);
const errorMsg = ref("");
const tempFilePath = ref("");
onLoad(async (option) => {
if (option.url) {
pdfUrl.value = config.baseUrl_api + decodeURIComponent(option.url);
await downloadPdf();
}
});
const downloadPdf = () => {
return new Promise((resolve) => {
uni.showLoading({ title: "加载中..." });
uni.downloadFile({
url: pdfUrl.value,
success: (res) => {
uni.hideLoading();
if (res.statusCode === 200) {
tempFilePath.value = res.tempFilePath;
loading.value = false;
// 自动打开文档
openDocument();
} else {
showError.value = true;
errorMsg.value = "下载失败";
}
resolve();
},
fail: () => {
uni.hideLoading();
showError.value = true;
errorMsg.value = "下载失败";
resolve();
}
});
});
};
const openDocument = () => {
if (!tempFilePath.value) {
uni.showToast({ title: "文件未准备好", icon: "none" });
return;
}
uni.openDocument({
filePath: tempFilePath.value,
fileType: "pdf",
showMenu: true,
success: () => {
console.log("打开文档成功");
},
fail: () => {
uni.showToast({ title: "打开失败,请在右上角菜单中下载", icon: "none" });
}
});
};
</script>
<style lang="scss" scoped>
.preview-container {
min-height: 100vh;
background: #f5f5f5;
position: relative;
}
.loading-tip {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 28rpx;
color: #666;
}
.error-tip {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 28rpx;
color: #C40F18;
}
.download-btn {
position: fixed;
bottom: 50rpx;
left: 50%;
transform: translateX(-50%);
background: #C40F18;
color: #fff;
padding: 24rpx 60rpx;
border-radius: 40rpx;
font-size: 28rpx;
z-index: 100;
}
</style>
......@@ -76,6 +76,8 @@
<script setup>
import { ref, onMounted } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { useUserStore } from '../store/modules/user';
import { getAssoPers } from '@/common/api.js';
import { getPersonTecDetails } from '@/common/api.js';
......@@ -90,12 +92,22 @@
// 变更记录相关
const changeRecordPopup = ref(null);
const currentChangeRecord = ref(null);
const pageType = ref('');
// 返回上一页
const goBack = () => {
uni.navigateBack();
};
onLoad((option) => {
if (option.type) {
pageType.value = option.type;
if (pageType.value == '0') {
uni.setNavigationBarTitle({ title: '级位记录' })
} else if (pageType.value == '1') {
uni.setNavigationBarTitle({ title: '段位记录' })
}
}
});
// 显示变更记录
const showChangeRecord = (item) => {
// remark已经在getLevelRecords中解析过了,直接使用
......@@ -116,7 +128,7 @@
const getLevelRecords = async () => {
loading.value = true;
try {
const res = await getPersonTecDetails(0, perId.value); // 0表示级位
const res = await getPersonTecDetails(pageType.value, perId.value); // 0表示级位
levelRecords.value = res.data || [];
// 处理数据
levelRecords.value.forEach(item => {
......
......@@ -51,6 +51,14 @@
<uni-easyinput :styles="inputstyle" :placeholderStyle="placeholderStyle"
v-model="baseFormData.phone" placeholder="请输入联系方式" />
</uni-forms-item>
<uni-forms-item label="会员编号" name="perCode" v-if="baseFormData.perCode">
<uni-easyinput :styles="inputstyle" :placeholderStyle="placeholderStyle"
v-model="baseFormData.perCode" placeholder="请输入会员编号" />
</uni-forms-item>
<uni-forms-item label="会员有效期" name="validityDate" v-if="baseFormData.validityDate">
<uni-easyinput :styles="inputstyle" :placeholderStyle="placeholderStyle"
v-model="baseFormData.validityDate" placeholder="请输入会员有效期" />
</uni-forms-item>
<uni-forms-item label="所在地区">
......@@ -142,6 +150,8 @@
sex: '',
idcType: '0',
perType: '1', // (1:个人会员;2:教练;3:考官;4:裁判;5:临时会员;)
perCode:'',
validityDate:''
})
const items = ref(['身份证添加', '证件照录入'])
const idcTypeList = ref([{
......@@ -356,6 +366,8 @@
baseFormData.value.phone = res.data.phone
baseFormData.value.cityId = res.data.cityId
baseFormData.value.address = res.data.address
baseFormData.value.perCode = res.data.perCode ||''
baseFormData.value.validityDate = res.data.validityDate?.slice(0,10) //去掉时分秒
if (res.data.photo) {
console.log(res.data.photo)
if (res.data.photo.indexOf('http') == -1) {
......
......@@ -51,15 +51,15 @@
<view class="stats-row">
<view class="stat-item">
<text class="stat-label">人数合计</text>
<text class="stat-value">{{ item.allCount || 0 }}</text>
<text class="stat-value">{{ item.allCount || '/' }}</text>
</view>
<view class="stat-item">
<text class="stat-label">新会员合计</text>
<text class="stat-value">{{ item.newCount || 0 }}</text>
<text class="stat-value">{{ item.newCount || '/' }}</text>
</view>
<view class="stat-item">
<text class="stat-label">年限合计</text>
<text class="stat-value">{{ item.yearCount || 0 }}</text>
<text class="stat-value">{{ item.yearCount || '/' }}</text>
</view>
</view>
......@@ -493,7 +493,7 @@ onUnmounted(() => {
}
.stat-value {
font-size:32rpx;
font-weight:700;
// font-weight:700;
color:#333;
}
}
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!