feat: 认证页面开发

This commit is contained in:
huxuejian 2026-01-23 18:08:14 +08:00
parent 397098a7ca
commit 44e5185746
6 changed files with 102 additions and 22 deletions

View File

@ -15,8 +15,10 @@
</view> </view>
<view class="bg-white px-10 mb-10 rounded"> <view class="bg-white px-10 mb-10 rounded">
<common-cell title="avatar" name="岗位"> <!-- 填写认证资料的时候岗位必填 -->
<view class="flex-grow flex items-center justify-end"> <common-cell :required="type === 'cert'" title="avatar" name="岗位">
<view class="flex-grow flex items-center justify-end" @click="selectJob()">
<view v-if="jobStr" class="text-base text-base">{{ jobStr }}</view>
<!-- <view class="mr-5 rounded-full" style="width: 64rpx;height: 64rpx;background: red;"></view> --> <!-- <view class="mr-5 rounded-full" style="width: 64rpx;height: 64rpx;background: red;"></view> -->
<uni-icons color="#999" type="right" size="16" /> <uni-icons color="#999" type="right" size="16" />
</view> </view>
@ -66,11 +68,17 @@ const { account, doctorInfo } = storeToRefs(useAccountStore());
const { useLoad, useShow } = useGuard(); const { useLoad, useShow } = useGuard();
const { getDoctorInfo } = useAccountStore(); const { getDoctorInfo } = useAccountStore();
const job = { assistant: '医生助理', doctor: '医生' };
const form = ref({}); const form = ref({});
const type = ref('') const type = ref('');
const formData = computed(() => ({ ...(doctorInfo.value || {}), ...form.value, mobile: account.value?.mobile })); const formData = computed(() => ({ ...(doctorInfo.value || {}), ...form.value, mobile: account.value?.mobile }));
const cancelText = computed(() => doctorInfo.value ? '取消' : '暂不填写'); const cancelText = computed(() => doctorInfo.value ? '取消' : '暂不填写');
const confirmText = computed(() => type.value === 'cert' ? '下一步' : '保存'); const confirmText = computed(() => type.value === 'cert' ? '下一步' : '保存');
const jobStr = computed(() => {
const jobs = formData.value && Array.isArray(formData.value.job) ? formData.value.job.filter(i => i === 'assistant' || i === 'doctor') : [];
return jobs[0] && job[jobs[0]] ? job[jobs[0]] : '';
})
// //
const genderOptions = [ const genderOptions = [
@ -122,12 +130,36 @@ function onChange({ title, value }) {
form.value[title] = value form.value[title] = value
} }
function selectJob() {
uni.showActionSheet({
itemList: ['医生', '医生助理', '无'],
success: ({ tapIndex }) => {
const job = ['doctor', 'assistant',][tapIndex];
form.value.job = job ? [job] : [];
}
})
}
function toCert() {
if (jobStr.value === '医生') {
uni.navigateTo({
url: '/pages/work/verify/doctor'
})
} else if (jobStr.value === '医生助理') {
uni.navigateTo({
url: '/pages/work/verify/assistant'
})
} else {
toast('请选择岗位信息')
}
}
async function save() { async function save() {
if (typeof formData.value.anotherName !== 'string' || !formData.value.anotherName.trim()) { if (typeof formData.value.anotherName !== 'string' || !formData.value.anotherName.trim()) {
return toast('请输入姓名') return toast('请输入姓名')
} }
if (type.value === 'cert' && !formData.value.departmentId) { if (type.value === 'cert' && !jobStr.value) {
return toast('请输入岗位信息') return toast('请选择岗位信息')
} }
const apiName = doctorInfo.value ? 'updateCorpMemberFromWxapp' : 'addCorpMemberFromWxapp'; const apiName = doctorInfo.value ? 'updateCorpMemberFromWxapp' : 'addCorpMemberFromWxapp';
const data = { const data = {
@ -136,11 +168,19 @@ async function save() {
mobile: account.value.mobile, mobile: account.value.mobile,
corpId: account.value.corpId, corpId: account.value.corpId,
} }
if (doctorInfo.value) {
data.id = doctorInfo.value._id;
}
const res = await api(apiName, data); const res = await api(apiName, data);
if (res && res.success) { if (res && res.success) {
await toast('保存成功');
await getDoctorInfo() await getDoctorInfo()
form.value = {};
if (type.value === 'cert') {
toCert()
} else {
await toast('保存成功');
back() back()
}
} else { } else {
await toast(res?.message || '保存失败'); await toast(res?.message || '保存失败');
} }

View File

@ -69,6 +69,7 @@ import { computed, ref } from "vue";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import useGuard from "@/hooks/useGuard.js"; import useGuard from "@/hooks/useGuard.js";
import useAccountStore from "@/store/account.js"; import useAccountStore from "@/store/account.js";
import api from "@/utils/api.js";
import { upload } from "@/utils/http.js"; import { upload } from "@/utils/http.js";
import { hideLoading, loading as showLoading, toast } from "@/utils/widget"; import { hideLoading, loading as showLoading, toast } from "@/utils/widget";
@ -108,6 +109,20 @@ async function save() {
} }
if (typeof formData.value.idCardBack !== 'string' || formData.value.idCardBack.trim() === '') { if (typeof formData.value.idCardBack !== 'string' || formData.value.idCardBack.trim() === '') {
return toast('请上传国徽面') return toast('请上传国徽面')
}
const data = {
idCardFront: formData.value.idCardFront,
idCardBack: formData.value.idCardBack,
corpId: account.value.corpId,
weChatOpenId: account.value.openid,
id: doctorInfo.value._id,
}
const res = await api('submitCertProfile', data);
if (res && res.success) {
await toast('提交成功');
uni.navigateBack({ delta: 2 })
} else {
toast(res.message || '提交失败')
} }
console.log('form.value: ', formData.value) console.log('form.value: ', formData.value)

View File

@ -2,11 +2,15 @@
<full-page pageClass="bg-white"> <full-page pageClass="bg-white">
<view class="p-15"> <view class="p-15">
<view class="title-bar relative text-dark text-base font-semibold">请填写执业医院</view> <view class="title-bar relative text-dark text-base font-semibold">请填写执业医院</view>
<view class="mt-12 p-10 flex items-center justify-between border rounded"> <!-- <view class="mt-12 p-10 flex items-center justify-between border rounded">
<view class="w-0 flex-grow truncate text-base mr-10" :class="formData.hospitalName ? 'text-dark' : 'text-gray'"> <view class="w-0 flex-grow truncate text-base mr-10" :class="formData.hospitalName ? 'text-dark' : 'text-gray'">
{{ formData.hospitalName || '请填写执业医院' }} {{ formData.hospitalName || '请填写执业医院' }}
</view> </view>
<uni-icons class="flex-shrink-0" color="#666" type="right" size="16" /> <uni-icons class="flex-shrink-0" color="#666" type="right" size="16" />
</view> -->
<view class="mt-12 p-10 flex items-center justify-between border rounded">
<input class="w-0 flex-grow text-base mr-10" :value="formData.hospitalName" @change="inputHospitalName($event)"
placeholder="请填写执业医院" />
</view> </view>
<view class="mt-15 title-bar relative font-semibold"> <view class="mt-15 title-bar relative font-semibold">
<text class="mr-5 text-dark text-base">请上传</text> <text class="mr-5 text-dark text-base">请上传</text>
@ -48,6 +52,7 @@ import { computed, ref } from "vue";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import useGuard from "@/hooks/useGuard.js"; import useGuard from "@/hooks/useGuard.js";
import useAccountStore from "@/store/account.js"; import useAccountStore from "@/store/account.js";
import api from "@/utils/api.js";
import { upload } from "@/utils/http.js"; import { upload } from "@/utils/http.js";
import { hideLoading, loading as showLoading, toast } from "@/utils/widget"; import { hideLoading, loading as showLoading, toast } from "@/utils/widget";
@ -63,6 +68,10 @@ function back() {
uni.navigateBack() uni.navigateBack()
} }
function inputHospitalName(e) {
form.value.hospitalName = e.detail.value
}
function uploadLicense(type) { function uploadLicense(type) {
uni.chooseImage({ uni.chooseImage({
count: 1, count: 1,
@ -90,7 +99,21 @@ async function save() {
if (typeof formData.value.medicalLicenseBack !== 'string' || formData.value.medicalLicenseBack.trim() === '') { if (typeof formData.value.medicalLicenseBack !== 'string' || formData.value.medicalLicenseBack.trim() === '') {
return toast('请上传医师执业资格证第二页') return toast('请上传医师执业资格证第二页')
} }
console.log('form.value: ', formData.value) const data = {
hospitalName: formData.value.hospitalName,
medicalLicenseFront: formData.value.medicalLicenseFront,
medicalLicenseBack: formData.value.medicalLicenseBack,
corpId: account.value.corpId,
weChatOpenId: account.value.openid,
id: doctorInfo.value._id,
}
const res = await api('submitCertProfile', data);
if (res && res.success) {
await toast('提交成功');
uni.navigateBack({ delta: 2 })
} else {
toast(res.message || '提交失败')
}
// uni.showToast({ title: '', icon: 'none' }) // uni.showToast({ title: '', icon: 'none' })
} }

View File

@ -76,7 +76,7 @@ import fullPage from '@/components/full-page.vue';
const certConfig = { const certConfig = {
verified: { text: '已认证', classnames: 'bg-success text-white' }, verified: { text: '已认证', classnames: 'bg-success text-white' },
verifing: { text: '认证中', classnames: 'bg-orange text-white' }, verifying: { text: '认证中', classnames: 'bg-warning text-white' },
unverified: { text: '未认证', classnames: 'bg-gray text-dark' }, unverified: { text: '未认证', classnames: 'bg-gray text-dark' },
}; };
@ -86,7 +86,7 @@ const { doctorInfo } = storeToRefs(useAccountStore());
const list = ref([1]); const list = ref([1]);
const visible = ref(false); const visible = ref(false);
const certStatus = computed(() => doctorInfo.value?.verifyStatus ? certConfig[doctorInfo.value.verifyStatus] : certConfig.unverified) const certStatus = computed(() => doctorInfo.value?.verifyStatus ? certConfig[doctorInfo.value.verifyStatus] : null)
// //
const handleVerify = () => { const handleVerify = () => {

View File

@ -25,8 +25,9 @@ export default defineStore("accountStore", () => {
} }
async function login(phoneCode) { async function login(phoneCode) {
await getLoginPromise(phoneCode); const res = await getLoginPromise(phoneCode);
loginPromise.value = null; loginPromise.value = null;
return res
} }
async function loginByCode(phoneCode = '') { async function loginByCode(phoneCode = '') {
@ -51,15 +52,15 @@ export default defineStore("accountStore", () => {
account.value = res.data; account.value = res.data;
openid.value = res.data.openid; openid.value = res.data.openid;
// 登录成功后初始化腾讯IM // 登录成功后初始化腾讯IM
try { // try {
console.log('开始初始化腾讯IMuserID:', res.data.openid); // console.log('开始初始化腾讯IMuserID:', res.data.openid);
await initGlobalTIM(res.data.openid); // await initGlobalTIM(res.data.openid);
isIMInitialized.value = true; // isIMInitialized.value = true;
console.log('腾讯IM初始化成功'); // console.log('腾讯IM初始化成功');
} catch (imError) { // } catch (imError) {
console.error('腾讯IM初始化失败:', imError); // console.error('腾讯IM初始化失败:', imError);
// IM初始化失败不影响登录流程 // // IM初始化失败不影响登录流程
} // }
await getDoctorInfo(openid.value); await getDoctorInfo(openid.value);
return res.data return res.data
} }

View File

@ -13,7 +13,8 @@ const urlsConfig = {
getCorpMemberData: 'getCorpMemberData', getCorpMemberData: 'getCorpMemberData',
updateCorpMember: 'updateCorpMember', updateCorpMember: 'updateCorpMember',
addCorpMemberFromWxapp: "addCorpMemberFromWxapp", addCorpMemberFromWxapp: "addCorpMemberFromWxapp",
updateCorpMemberFromWxapp: "updateCorpMemberFromWxapp" updateCorpMemberFromWxapp: "updateCorpMemberFromWxapp",
submitCertProfile: 'submitCertProfile'
}, },
knowledgeBase: { knowledgeBase: {