ykt-wxapp/pages/work/profile.vue
2026-01-20 16:30:03 +08:00

380 lines
8.8 KiB
Vue

<template>
<view class="profile-page">
<!-- 表单区域 -->
<view class="form-section bg-white">
<!-- 姓名 -->
<common-cell name="姓名" :required="true">
<view class="form-content__wrapper">
<input
class="flex-main-content text-right"
v-model="formData.name"
placeholder="请输入"
placeholder-style="color: #999"
/>
<uni-icons class="form-arrow" type="arrowright"></uni-icons>
</view>
</common-cell>
<!-- 头像 -->
<common-cell name="头像">
<view class="form-content__wrapper" @click="chooseAvatar">
<view class="flex-main-content flex items-center">
<image
v-if="formData.avatar"
class="avatar-preview"
:src="formData.avatar"
mode="aspectFill"
/>
<view v-else class="avatar-placeholder">
<text class="avatar-icon">👤</text>
</view>
</view>
<uni-icons class="form-arrow" type="arrowright"></uni-icons>
</view>
</common-cell>
<!-- 性别 -->
<form-select
name="性别"
:form="formData"
title="gender"
:range="genderOptions"
@change="handleFieldChange"
/>
<!-- 手机号(不可修改) -->
<common-cell name="手机号 (不可修改)">
<view class="form-content__wrapper">
<view class="flex-main-content text-dark">{{ formData.phone }}</view>
</view>
</common-cell>
<!-- 岗位 -->
<form-select
name="岗位"
:form="formData"
title="position"
:range="positionOptions"
@change="handleFieldChange"
/>
<!-- 职称 -->
<form-select
name="职称"
:form="formData"
title="title"
:range="titleOptions"
@change="handleFieldChange"
/>
<!-- 科室 -->
<common-cell name="科室" :required="true">
<view class="form-content__wrapper" @click="openDepartmentSelect">
<view
class="flex-main-content text-right"
:class="{ 'text-placeholder': !formData.departmentName }"
>
{{ formData.departmentName || "请选择" }}
</view>
<uni-icons class="form-arrow" type="arrowright"></uni-icons>
</view>
</common-cell>
<!-- 个人介绍 -->
<form-textarea
name="个人介绍"
:form="formData"
title="intro"
:word-limit="500"
@change="handleFieldChange"
/>
</view>
<!-- 底部按钮 -->
<view class="button-footer">
<view class="btn btn-cancel" @click="handleCancel">取消</view>
<view class="btn btn-save" @click="handleSave">保存</view>
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import useGuard from "@/hooks/useGuard.js";
import {
getDoctorInfoByAccountId,
updateDoctorInfo,
} from "@/api/doctor/doctor.js";
import { uploadFile } from "@/api/file.js";
import useAccountStore from "@/store/account.js";
import { storeToRefs } from "pinia";
import CommonCell from "@/components/form-template/common-cell.vue";
import FormSelect from "@/components/form-template/form-cell/form-select.vue";
import FormTextarea from "@/components/form-template/form-cell/form-textarea.vue";
const { account, mobile } = storeToRefs(useAccountStore());
const { useLoad } = useGuard();
// 表单数据
const formData = ref({
name: "",
avatar: "",
gender: "",
phone: "",
position: "",
title: "",
department: "",
departmentName: "",
departmentId: "",
intro: "",
});
// 选项数据
const genderOptions = ["男", "女"];
const positionOptions = ["医生", "护士", "药师", "技师", "其他"];
const titleOptions = ["主任医师", "副主任医师", "主治医师", "住院医师", "其他"];
// 字段变更处理
const handleFieldChange = (e) => {
formData.value[e.title] = e.value;
};
// 选择头像
const chooseAvatar = () => {
uni.chooseImage({
count: 1,
sizeType: ["compressed"],
sourceType: ["album", "camera"],
success: async (res) => {
const tempFilePath = res.tempFilePaths[0];
uni.showLoading({
title: "上传中...",
});
try {
const uploadRes = await uploadFile(tempFilePath, "other", "public");
if (uploadRes && uploadRes.previewUrl) {
formData.value.avatar = uploadRes.previewUrl;
uni.hideLoading();
uni.showToast({
title: "上传成功",
icon: "success",
});
} else {
throw new Error("上传失败");
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: "上传失败",
icon: "none",
});
}
},
});
};
// 取消
const handleCancel = () => {
uni.navigateBack();
};
// 保存
const handleSave = async () => {
// 验证必填字段
if (!formData.value.name) {
uni.showToast({
title: "请输入姓名",
icon: "none",
});
return;
}
uni.showLoading({
title: "保存中...",
});
try {
// 调用更新接口
const result = await updateDoctorInfo({
name: formData.value.name,
avatar: formData.value.avatar,
gender: formData.value.gender,
position: formData.value.position,
title: formData.value.title,
departmentId: formData.value.departmentId,
department: formData.value.departmentName || formData.value.department,
intro: formData.value.intro,
});
uni.hideLoading();
if (result && result.success) {
uni.showToast({
title: "保存成功",
icon: "success",
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
} else {
uni.showToast({
title: result?.message || "保存失败",
icon: "none",
});
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: "保存失败",
icon: "none",
});
console.error("保存失败:", error);
}
};
// 加载医生信息
const loadDoctorInfo = async () => {
if (!account.value?.id) {
return;
}
try {
uni.showLoading({
title: "加载中...",
});
const result = await getDoctorInfoByAccountId(account.value.id);
uni.hideLoading();
if (result && result.success && result.data) {
const doctorInfo = result.data;
formData.value = {
name: doctorInfo.name || "",
avatar: doctorInfo.avatar || "",
gender: doctorInfo.gender || "",
phone: doctorInfo.phone || mobile.value || "",
position: doctorInfo.position || "",
title: doctorInfo.title || "",
department: doctorInfo.department || "",
departmentName: doctorInfo.department || "",
departmentId: doctorInfo.departmentId || "",
intro: doctorInfo.intro || "",
};
} else {
// 如果没有医生信息,设置手机号为授权登录的手机号
if (mobile.value) {
formData.value.phone = mobile.value;
}
}
} catch (error) {
uni.hideLoading();
console.error("加载医生信息失败:", error);
}
};
useLoad(() => {
// 初始化时设置手机号为授权登录的手机号
if (mobile.value && !formData.value.phone) {
formData.value.phone = mobile.value;
}
loadDoctorInfo();
});
// 打开科室选择
const openDepartmentSelect = () => {
uni.navigateTo({
url: "/pages/work/department-select",
events: {
deptSelected: ({ name, deptId }) => {
formData.value.department = name || "";
formData.value.departmentName = name || "";
formData.value.departmentId = deptId || "";
},
},
});
};
</script>
<style lang="scss" scoped>
.profile-page {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 120rpx;
}
.form-section {
margin-top: 20rpx;
}
.form-content__wrapper {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
text-align: right;
font-size: 28rpx;
input {
text-align: right;
}
}
.text-placeholder {
color: #999;
}
.avatar-preview {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: #e5e5e5;
}
.avatar-placeholder {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: #e5e5e5;
display: flex;
align-items: center;
justify-content: center;
.avatar-icon {
font-size: 48rpx;
color: #999;
}
}
.button-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
padding: 20rpx 30rpx;
background: #fff;
border-top: 1px solid #eee;
gap: 20rpx;
z-index: 100;
.btn {
flex: 1;
height: 88rpx;
line-height: 88rpx;
text-align: center;
border-radius: 8rpx;
font-size: 32rpx;
}
.btn-cancel {
background: #fff;
border: 1px solid #007aff;
color: #007aff;
}
.btn-save {
background: #007aff;
color: #fff;
}
}
</style>