219 lines
5.7 KiB
Vue
219 lines
5.7 KiB
Vue
<template>
|
||
<s-layout title="上传健康证" class="health-cert-page">
|
||
<view class="page-body">
|
||
<view class="form-row">
|
||
<text class="label">编号:</text>
|
||
<up-input v-model="healthNumber" placeholder="请输入健康证编号" clearable />
|
||
</view>
|
||
|
||
<view class="form-row">
|
||
<text class="label">类别:</text>
|
||
<up-input v-model="healthCategory" placeholder="请输入健康证类别" clearable />
|
||
</view>
|
||
|
||
<view class="form-row date-row">
|
||
<text class="label">有效日期:</text>
|
||
<up-datetime-picker hasInput v-model="healthValidStart" mode="date" placeholder="年/月/日" class="date-input" />
|
||
<text class="dash"> — </text>
|
||
<up-datetime-picker hasInput v-model="healthValidEnd" mode="date" placeholder="年/月/日" class="date-input" />
|
||
</view>
|
||
|
||
<view class="upload-section">
|
||
<text class="upload-title">上传健康证:</text>
|
||
<view class="upload-row">
|
||
<view v-for="(img, idx) in healthImages" :key="idx" class="upload-item">
|
||
<up-image :src="img" class="upload-thumb" mode="aspectFill" @click="previewImage(idx)" />
|
||
<view class="remove-btn" @click.stop="removeHealthImage(idx)">×</view>
|
||
</view>
|
||
|
||
<up-upload :max-count="1" :show-file-list="false" @change="onUploadHealth">
|
||
<view class="upload-add" v-if="healthImages.length < 4">
|
||
<up-icon name="plus" size="36" color="#999999" />
|
||
</view>
|
||
</up-upload>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="save-row">
|
||
<up-button type="primary" block @click="onSave">保存</up-button>
|
||
</view>
|
||
</view>
|
||
</s-layout>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onBeforeMount } from 'vue';
|
||
import FileApi from '@/sheep/api/infra/file';
|
||
import UserApi from '@/sheep/api/member/user';
|
||
import sheep from '@/sheep';
|
||
|
||
const healthNumber = ref('');
|
||
const healthCategory = ref('');
|
||
const healthValidStart = ref('');
|
||
const healthValidEnd = ref('');
|
||
const healthImages = ref([]); // 存放图片 url
|
||
|
||
// 页面初始化,从用户信息恢复(若已有则填充)
|
||
async function init() {
|
||
const user = await sheep.$store('user').getInfo();
|
||
if (user) {
|
||
healthNumber.value = user.healthCertNumber || user.healthCertNo || '';
|
||
healthCategory.value = user.healthCertCategory || '';
|
||
healthValidStart.value = user.healthCertValidStart || '';
|
||
healthValidEnd.value = user.healthCertValidEnd || '';
|
||
// 健康证可能只保留首张图片字符串,为兼容性处理成数组
|
||
const img = user.healthCert || user.healthCertImage || user.healthCertUrl || '';
|
||
if (img) {
|
||
healthImages.value = Array.isArray(img) ? img.slice() : [img];
|
||
}
|
||
}
|
||
}
|
||
|
||
onBeforeMount(() => {
|
||
init();
|
||
});
|
||
|
||
function previewImage(index) {
|
||
const urls = healthImages.value.slice();
|
||
uni.previewImage({
|
||
current: index,
|
||
urls,
|
||
});
|
||
}
|
||
|
||
function removeHealthImage(index) {
|
||
if (index >= 0 && index < healthImages.value.length) {
|
||
healthImages.value.splice(index, 1);
|
||
}
|
||
}
|
||
|
||
function onUploadHealth(event) {
|
||
const file = Array.isArray(event) ? event[0] : (event.detail || event);
|
||
const url = file?.url || file?.path || file?.thumb || '';
|
||
if (url) {
|
||
// 限制最多 4 张
|
||
if (healthImages.value.length < 4) {
|
||
healthImages.value.push(url);
|
||
}
|
||
// 兼容:在表单保存时取首张
|
||
}
|
||
}
|
||
|
||
// 如果用户通过本地选择图片(没有使用 up-upload 的自动上传),也支持手动选择并上传
|
||
async function chooseAndUpload() {
|
||
const res = await uni.chooseImage({ count: 1 });
|
||
if (!res || !res.tempFilePaths || !res.tempFilePaths.length) return;
|
||
const tempPath = res.tempFilePaths[0];
|
||
const { data } = await FileApi.uploadFile(tempPath);
|
||
if (data) {
|
||
if (healthImages.value.length < 4) {
|
||
healthImages.value.push(data);
|
||
}
|
||
}
|
||
}
|
||
|
||
async function onSave() {
|
||
// 简单校验:至少填写编号或上传图片
|
||
if (!healthNumber.value && !healthImages.value.length) {
|
||
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('请填写编号或上传健康证图片');
|
||
return;
|
||
}
|
||
|
||
const payload = {
|
||
healthCertNumber: healthNumber.value || undefined,
|
||
healthCertCategory: healthCategory.value || undefined,
|
||
healthCertValidStart: healthValidStart.value || undefined,
|
||
healthCertValidEnd: healthValidEnd.value || undefined,
|
||
// 为兼容后端,保留首张图片字段 healthCert(若后端支持数组可改为数组)
|
||
healthCert: healthImages.value.length ? healthImages.value[0] : undefined,
|
||
};
|
||
|
||
try {
|
||
const res = await UserApi.updateUser(payload);
|
||
if (res && res.code === 0) {
|
||
// 更新本地用户缓存
|
||
await sheep.$store('user').updateUserData();
|
||
uni.navigateBack();
|
||
}
|
||
} catch (err) {
|
||
console.warn('保存健康证失败', err);
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.health-cert-page .page-body {
|
||
padding: 20rpx 30rpx;
|
||
background: transparent;
|
||
}
|
||
.form-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 35rpx;
|
||
}
|
||
.label {
|
||
width: 140rpx;
|
||
color: #333333;
|
||
font-size: 28rpx;
|
||
}
|
||
.date-row .date-input {
|
||
width: 260rpx;
|
||
}
|
||
.dash {
|
||
margin: 0 10rpx;
|
||
color: #999999;
|
||
}
|
||
.upload-section {
|
||
margin-top: 28rpx;
|
||
}
|
||
.upload-title {
|
||
display: block;
|
||
margin-bottom: 12rpx;
|
||
color: #333;
|
||
font-size: 28rpx;
|
||
}
|
||
.upload-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
flex-wrap: wrap;
|
||
}
|
||
.upload-item {
|
||
position: relative;
|
||
width: 140rpx;
|
||
height: 140rpx;
|
||
border-radius: 8rpx;
|
||
overflow: hidden;
|
||
}
|
||
.upload-thumb {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.remove-btn {
|
||
position: absolute;
|
||
right: 6rpx;
|
||
top: 6rpx;
|
||
width: 30rpx;
|
||
height: 30rpx;
|
||
line-height: 30rpx;
|
||
text-align: center;
|
||
background: rgba(0,0,0,0.6);
|
||
color: #fff;
|
||
border-radius: 50%;
|
||
font-size: 24rpx;
|
||
z-index: 5;
|
||
}
|
||
.upload-add {
|
||
width: 140rpx;
|
||
height: 140rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border: 1px dashed #e6e6e6;
|
||
border-radius: 8rpx;
|
||
background: #fafafa;
|
||
}
|
||
.save-row {
|
||
margin-top: 80rpx;
|
||
}
|
||
</style> |