feat: 认证页面提价
@ -1,3 +1,4 @@
|
|||||||
MP_API_BASE_URL=http://192.168.60.2:8080
|
MP_API_BASE_URL=http://192.168.60.2:8080
|
||||||
MP_CACHE_PREFIX=development
|
MP_CACHE_PREFIX=development
|
||||||
MP_WX_APP_ID=wx93af55767423938e
|
MP_WX_APP_ID=wx93af55767423938e
|
||||||
|
MP_CORP_ID=wwe3fb2faa52cf9dfb
|
||||||
3
App.vue
@ -36,6 +36,9 @@ page {
|
|||||||
.relative {
|
.relative {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
.absolute{
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
.inline-block {
|
.inline-block {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view v-if="showCancel || showConfirm" class="relative px-15 py-12 bg-white text-center"
|
<view v-if="showCancel || showConfirm" class="relative flex px-15 py-12 bg-white text-center"
|
||||||
:class="hidedenShadow ? '' : 'shadow-up'">
|
:class="hidedenShadow ? '' : 'shadow-up'">
|
||||||
<view v-if="showCancel" class="flex-grow py-10 text-base border-primary rounded text-primary rounded"
|
<view v-if="showCancel" class="flex-grow py-10 text-base border-primary rounded text-primary rounded"
|
||||||
@click="cancel()">
|
@click="cancel()">
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<picker mode="selector" :range="displayRange" :disabled="disableChange" @change="change($event)">
|
<picker mode="selector" :range="displayRange" :disabled="disableChange" @change="change($event)">
|
||||||
<common-cell :name="name" :required="required">
|
<common-cell :name="name" :required="required">
|
||||||
<view class="form-content__wrapper">
|
<view class="form-content__wrapper">
|
||||||
<view class="flex-main-content truncate" :class="value ? '' : 'form__placeholder'">
|
<view class="flex-main-content truncate" :class="value ? '' : 'form__placeholder'">
|
||||||
@ -49,9 +49,9 @@ const displayRange = computed(() => {
|
|||||||
}
|
}
|
||||||
return props.range;
|
return props.range;
|
||||||
})
|
})
|
||||||
|
|
||||||
const value = computed(() => {
|
const value = computed(() => {
|
||||||
if (!props.form || !props.form[props.title]) return '';
|
if (!props.form || !props.form[props.title]) return '';
|
||||||
|
|
||||||
const currentValue = props.form[props.title];
|
const currentValue = props.form[props.title];
|
||||||
// 如果range是对象数组,找到对应的label显示
|
// 如果range是对象数组,找到对应的label显示
|
||||||
if (Array.isArray(props.range) && props.range.length > 0 && typeof props.range[0] === 'object') {
|
if (Array.isArray(props.range) && props.range.length > 0 && typeof props.range[0] === 'object') {
|
||||||
@ -65,7 +65,7 @@ function change(e) {
|
|||||||
const selectedValue = props.range[e.detail.value];
|
const selectedValue = props.range[e.detail.value];
|
||||||
emits('change', {
|
emits('change', {
|
||||||
title: props.title,
|
title: props.title,
|
||||||
value: selectedValue
|
value: typeof selectedValue === 'object' ? selectedValue.value : selectedValue
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -4,8 +4,9 @@
|
|||||||
{{ name }}<text v-if="required" class="form-cell--required"></text>
|
{{ name }}<text v-if="required" class="form-cell--required"></text>
|
||||||
</view>
|
</view>
|
||||||
<view class="mt-10">
|
<view class="mt-10">
|
||||||
<textarea :disabled="disableChange" :value="value" class="form-textarea" :placeholder="placeholder"
|
<textarea :disabled="disableChange" :value="value" class="form-textarea"
|
||||||
placeholder-class="form__placeholder" :maxlength="wordLimit" @input="change($event)" />
|
:class="border ? 'form-textarea--border' : ''" :placeholder="placeholder" placeholder-class="form__placeholder"
|
||||||
|
:maxlength="wordLimit" @input="change($event)" />
|
||||||
<view v-if="wordLimit > 0" class="form-textarea__count">
|
<view v-if="wordLimit > 0" class="form-textarea__count">
|
||||||
{{ value && value.length ? value.length : 0 }} / {{ wordLimit }}
|
{{ value && value.length ? value.length : 0 }} / {{ wordLimit }}
|
||||||
</view>
|
</view>
|
||||||
@ -17,6 +18,10 @@ import { computed } from 'vue';
|
|||||||
|
|
||||||
const emits = defineEmits(['change']);
|
const emits = defineEmits(['change']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
form: {
|
form: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
@ -45,7 +50,7 @@ const placeholder = computed(() => `请输入${props.name || ''}`)
|
|||||||
const value = computed(() => props.form && props.form && props.form[props.title] ? props.form[props.title] : '')
|
const value = computed(() => props.form && props.form && props.form[props.title] ? props.form[props.title] : '')
|
||||||
const wordLimit = computed(() => {
|
const wordLimit = computed(() => {
|
||||||
if (typeof props.wordLimit === 'string' && Number(props.wordLimit) > 0) {
|
if (typeof props.wordLimit === 'string' && Number(props.wordLimit) > 0) {
|
||||||
return Number.ceil(props.wordLimit)
|
return Math.ceil(props.wordLimit)
|
||||||
}
|
}
|
||||||
if (typeof props.wordLimit === 'number' && props.wordLimit > 0) {
|
if (typeof props.wordLimit === 'number' && props.wordLimit > 0) {
|
||||||
return props.wordLimit
|
return props.wordLimit
|
||||||
@ -72,12 +77,15 @@ function change(e) {
|
|||||||
.form-textarea {
|
.form-textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
border: 1px solid #eee;
|
|
||||||
padding: 20rpx;
|
padding: 20rpx;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-textarea--border {
|
||||||
|
border: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
.form-textarea__count {
|
.form-textarea__count {
|
||||||
padding-top: 20rpx;
|
padding-top: 20rpx;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="full-page" :style="pageStyle">
|
<view class="full-page" :class="pageClass" :style="pageStyle">
|
||||||
<view v-if="hasHeader" class="page-header">
|
<view v-if="hasHeader" class="page-header">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
</view>
|
</view>
|
||||||
<view class="page-main" :style="mainStyle">
|
<view class="page-main" :class="mainClass" :style="mainStyle">
|
||||||
<view v-if="customScroll" class="page-scroll">
|
<view v-if="customScroll" class="page-scroll">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</view>
|
</view>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<slot name="footer"></slot>
|
<slot name="footer"></slot>
|
||||||
</view>
|
</view>
|
||||||
<!-- #ifdef MP-->
|
<!-- #ifdef MP-->
|
||||||
<view class="safeareaBottom"></view>
|
<view v-if="showSafeArea" class="safeareaBottom"></view>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -27,8 +27,11 @@ import useDebounce from '@/utils/useDebounce';
|
|||||||
const emits = defineEmits(['reachBottom']);
|
const emits = defineEmits(['reachBottom']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
customScroll: { type: Boolean, default: false },
|
customScroll: { type: Boolean, default: false },
|
||||||
|
mainClass: { type: String, default: '' },
|
||||||
mainStyle: { default: '' },
|
mainStyle: { default: '' },
|
||||||
pageStyle: { default: '' }
|
pageClass: { type: String, default: '' },
|
||||||
|
pageStyle: { default: '' },
|
||||||
|
showSafeArea: { type: Boolean, default: true }
|
||||||
});
|
});
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
const hasHeader = computed(() => !!slots.header);
|
const hasHeader = computed(() => !!slots.header);
|
||||||
|
|||||||
@ -39,7 +39,9 @@ export default function useGuard() {
|
|||||||
|
|
||||||
async function triggleShowEvents() {
|
async function triggleShowEvents() {
|
||||||
await promise;
|
await promise;
|
||||||
onShowEvents.value.forEach(fn => fn(onShowOptions.value))
|
if (account.value && account.value.openid) {
|
||||||
|
onShowEvents.value.forEach(fn => fn(onShowOptions.value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function useShow(fn) {
|
function useShow(fn) {
|
||||||
@ -53,8 +55,10 @@ export default function useGuard() {
|
|||||||
const route = routes.find(i => page && i.path === page.route);
|
const route = routes.find(i => page && i.path === page.route);
|
||||||
const requireLogin = route && route.meta && route.meta.login;
|
const requireLogin = route && route.meta && route.meta.login;
|
||||||
if (requireLogin && !account.value) {
|
if (requireLogin && !account.value) {
|
||||||
const res = await login()
|
await login()
|
||||||
if (res) {
|
console.log('login success')
|
||||||
|
console.log(account.value)
|
||||||
|
if (account.value) {
|
||||||
resolve()
|
resolve()
|
||||||
} else {
|
} else {
|
||||||
return toLoginPage(opts, page.route);
|
return toLoginPage(opts, page.route);
|
||||||
|
|||||||
29
pages.json
@ -3,13 +3,8 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/message/message",
|
"path": "pages/message/message",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "消息"
|
"navigationBarTitleText": "消息",
|
||||||
}
|
"navigationStyle": "custom"
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "pages/case/case",
|
|
||||||
"style": {
|
|
||||||
"navigationBarTitleText": "病例"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -18,6 +13,12 @@
|
|||||||
"navigationBarTitleText": "工作台"
|
"navigationBarTitleText": "工作台"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/case/case",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "病例"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/work/profile",
|
"path": "pages/work/profile",
|
||||||
"style": {
|
"style": {
|
||||||
@ -30,10 +31,22 @@
|
|||||||
"navigationBarTitleText": "选择科室"
|
"navigationBarTitleText": "选择科室"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/work/verify/assistant",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "上传证照"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/work/verify/doctor",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "上传证照"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/login/login",
|
"path": "pages/login/login",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "登录"
|
"navigationBarTitleText": "授权登录"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view v-if="team" class="pt-lg px-15 flex flex-col items-center text-center">
|
<!-- <view v-if="team" class="pt-lg px-15 flex flex-col items-center text-center">
|
||||||
<group-avatar :avatarList="team.avatars" />
|
<group-avatar :avatarList="team.avatars" />
|
||||||
<view class="mt-15 text-base font-semibold text-dark">{{
|
<view class="mt-15 text-base font-semibold text-dark">{{
|
||||||
team.teamName
|
team.teamName
|
||||||
@ -8,20 +8,15 @@
|
|||||||
<view class="mt-15 text-lg text-dark font-semibold"
|
<view class="mt-15 text-lg text-dark font-semibold"
|
||||||
>为您提供团队个性化专属服务</view
|
>为您提供团队个性化专属服务</view
|
||||||
>
|
>
|
||||||
</view>
|
v-else
|
||||||
<view v-else class="pt-lg px-15 flex flex-col items-center text-center">
|
</view> -->
|
||||||
|
<view class="pt-lg px-15 flex flex-col items-center text-center">
|
||||||
<image src="/static/logo-plain.png" class="logo"></image>
|
<image src="/static/logo-plain.png" class="logo"></image>
|
||||||
<view class="mt-15 text-xl font-semibold text-dark">柚健康</view>
|
<view class="mt-15 text-xl font-semibold text-dark">柚健康</view>
|
||||||
<view class="mt-12 text-base text-dark">生命全周期健康管理伙伴</view>
|
<view class="mt-12 text-base text-dark">生命全周期健康管理伙伴</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="login-btn-wrap">
|
<view class="login-btn-wrap">
|
||||||
<button
|
<button v-if="checked" class="login-btn" type="primary" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
|
||||||
v-if="checked"
|
|
||||||
class="login-btn"
|
|
||||||
type="primary"
|
|
||||||
open-type="getPhoneNumber"
|
|
||||||
@getphonenumber="getPhoneNumber"
|
|
||||||
>
|
|
||||||
手机号快捷登录
|
手机号快捷登录
|
||||||
</button>
|
</button>
|
||||||
<!-- <button v-if="checked" class="login-btn" type="primary" @click="getPhoneNumber()">
|
<!-- <button v-if="checked" class="login-btn" type="primary" @click="getPhoneNumber()">
|
||||||
@ -31,10 +26,7 @@
|
|||||||
手机号快捷登录
|
手机号快捷登录
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view class="flex items-center justify-center mt-12 px-15" @click="checked = !checked">
|
||||||
class="flex items-center justify-center mt-12 px-15"
|
|
||||||
@click="checked = !checked"
|
|
||||||
>
|
|
||||||
<checkbox :checked="checked" style="transform: scale(0.7)" />
|
<checkbox :checked="checked" style="transform: scale(0.7)" />
|
||||||
<view class="text-sm text-gray">我已阅读并同意</view>
|
<view class="text-sm text-gray">我已阅读并同意</view>
|
||||||
<view class="text-sm text-primary">《用户协议》、</view>
|
<view class="text-sm text-primary">《用户协议》、</view>
|
||||||
@ -44,16 +36,16 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
import { onLoad } from "@dcloudio/uni-app";
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
import useAccountStore from "@/store/account";
|
import useAccountStore from "@/store/account";
|
||||||
import { get } from "@/utils/cache";
|
import { get } from "@/utils/cache";
|
||||||
import { toast } from "@/utils/widget";
|
import { toast } from "@/utils/widget";
|
||||||
|
|
||||||
import groupAvatar from "@/components/group-avatar.vue";
|
|
||||||
|
|
||||||
const team = ref(true);
|
const team = ref(true);
|
||||||
const checked = ref(false);
|
const checked = ref(false);
|
||||||
const redirectUrl = ref("");
|
const redirectUrl = ref("");
|
||||||
|
const { doctorInfo } = storeToRefs(useAccountStore());
|
||||||
const { login } = useAccountStore();
|
const { login } = useAccountStore();
|
||||||
|
|
||||||
function attempRedirect(url) {
|
function attempRedirect(url) {
|
||||||
@ -81,8 +73,8 @@ function remind() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toHome() {
|
function toHome() {
|
||||||
uni.navigateTo({
|
uni.switchTab({
|
||||||
url: "/pages/message/message",
|
url: "/pages/work/work",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +84,10 @@ async function getPhoneNumber(e) {
|
|||||||
const res = await login(phoneCode);
|
const res = await login(phoneCode);
|
||||||
if (res && redirectUrl.value) {
|
if (res && redirectUrl.value) {
|
||||||
await attempToPage(redirectUrl.value);
|
await attempToPage(redirectUrl.value);
|
||||||
|
} else if (res && !doctorInfo.value) {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages/work/profile'
|
||||||
|
})
|
||||||
} else if (res) {
|
} else if (res) {
|
||||||
toHome();
|
toHome();
|
||||||
}
|
}
|
||||||
@ -109,7 +105,6 @@ onLoad((opts) => {
|
|||||||
if (opts.source === "teamInvite") {
|
if (opts.source === "teamInvite") {
|
||||||
team.value = get("invite-team-info");
|
team.value = get("invite-team-info");
|
||||||
redirectUrl.value = `/pages/archive/edit-archive?teamId=${team.value.teamId}&corpId=${team.value.corpId}`;
|
redirectUrl.value = `/pages/archive/edit-archive?teamId=${team.value.teamId}&corpId=${team.value.corpId}`;
|
||||||
console.log("redirectUrl", redirectUrl.value);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (opts.redirect) {
|
if (opts.redirect) {
|
||||||
|
|||||||
64
pages/work/components/cert-popup.vue
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<uni-popup ref="popup" type="center" :mask-click="false">
|
||||||
|
<view class="bg-white rounded overflow-hidden" style="width: 690rpx;">
|
||||||
|
<view class="px-15 py-12 text-center text-lg font-semibold text-dark">
|
||||||
|
认证须知
|
||||||
|
</view>
|
||||||
|
<view class="text-base text-dark px-15 leading-normal font-semibold mt-10">
|
||||||
|
1、认证通过后,您个人账号病历档案管理数(含所有团队)上限由10个升级至100个;
|
||||||
|
</view>
|
||||||
|
<view class="px-15 leading-normal mt-10 ">
|
||||||
|
<text class="text-base text-dark">2、认证前请仔细核对个人信息,确保准确无误。认证后部分信息不支持修改,包括姓名、岗位等。如需修改以上信息,请联系客服人工处理</text>
|
||||||
|
</view>
|
||||||
|
<view class="mt-10 px-15 leading-normal font-semibold pb-50 text-lg text-primary" @click="toService()">点击添加客服
|
||||||
|
</view>
|
||||||
|
<view class="footer-buttons">
|
||||||
|
<button-footer hideden-shadow confirmText="去认证" @confirm="confirm()" @cancel="close()" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import ButtonFooter from '@/components/button-footer.vue';
|
||||||
|
|
||||||
|
const emits = defineEmits(['close', 'confirm'])
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const popup = ref()
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
emits('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirm() {
|
||||||
|
close()
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/work/profile?type=cert",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toService() {
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.visible, n => {
|
||||||
|
if (n) {
|
||||||
|
popup.value && popup.value.open()
|
||||||
|
} else {
|
||||||
|
popup.value && popup.value.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.pb-50 {
|
||||||
|
padding-bottom: 100rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
308
pages/work/profile copy.vue
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
<template>
|
||||||
|
<view class="profile-page">
|
||||||
|
<!-- 表单区域 -->
|
||||||
|
<view class="form-section bg-white">
|
||||||
|
<!-- 姓名 -->
|
||||||
|
<form-input
|
||||||
|
name="姓名"
|
||||||
|
:required="true"
|
||||||
|
:form="formData"
|
||||||
|
title="anotherName"
|
||||||
|
@change="handleFieldChange"
|
||||||
|
/>
|
||||||
|
<!-- 头像 -->
|
||||||
|
<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>
|
||||||
|
<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.mobile }}</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="科室">
|
||||||
|
<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 { chooseAndUploadImage } from "@/utils/file.js";
|
||||||
|
import useAccountStore from "@/store/account.js";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import CommonCell from "@/components/form-template/common-cell.vue";
|
||||||
|
import FormInput from "@/components/form-template/form-cell/form-input.vue";
|
||||||
|
import FormSelect from "@/components/form-template/form-cell/form-select.vue";
|
||||||
|
import FormTextarea from "@/components/form-template/form-cell/form-textarea.vue";
|
||||||
|
import api from "@/utils/api.js";
|
||||||
|
const { account, doctorInfo } = storeToRefs(useAccountStore());
|
||||||
|
const { useLoad } = useGuard();
|
||||||
|
const { getDoctorInfo } = useAccountStore();
|
||||||
|
// 表单数据
|
||||||
|
const formData = ref({
|
||||||
|
anotherName: "",
|
||||||
|
avatar: "",
|
||||||
|
gender: "",
|
||||||
|
mobile: "",
|
||||||
|
position: "",
|
||||||
|
title: "",
|
||||||
|
department: "",
|
||||||
|
departmentName: "",
|
||||||
|
departmentId: "",
|
||||||
|
intro: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 选项数据
|
||||||
|
const genderOptions = [
|
||||||
|
{ label: "男", value: "0" },
|
||||||
|
{ label: "女", value: "1" },
|
||||||
|
];
|
||||||
|
const positionOptions = ["医生", "护士", "药师", "技师", "其他"];
|
||||||
|
const titleOptions = ["主任医师", "副主任医师", "主治医师", "医师", "其他"];
|
||||||
|
// 字段变更处理
|
||||||
|
const handleFieldChange = (e) => {
|
||||||
|
if (e.title === "gender") {
|
||||||
|
formData.value[e.title] = e.value.value;
|
||||||
|
} else {
|
||||||
|
formData.value[e.title] = e.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择头像
|
||||||
|
const chooseAvatar = async () => {
|
||||||
|
const url = await chooseAndUploadImage();
|
||||||
|
if (url) {
|
||||||
|
formData.value.avatar = url;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
uni.navigateBack();
|
||||||
|
};
|
||||||
|
// 保存
|
||||||
|
const handleSave = async () => {
|
||||||
|
createDoctorInfo();
|
||||||
|
};
|
||||||
|
useLoad(() => {
|
||||||
|
if (doctorInfo.value) {
|
||||||
|
formData.value = { ...doctorInfo.value };
|
||||||
|
} else {
|
||||||
|
formData.value.mobile = account.value.mobile;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建医生信息
|
||||||
|
const createDoctorInfo = async () => {
|
||||||
|
if (!formData.value.anotherName) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请输入姓名",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let params = {
|
||||||
|
anotherName: formData.value.anotherName,
|
||||||
|
avatar: formData.value.avatar,
|
||||||
|
gender: formData.value.gender,
|
||||||
|
mobile: formData.value.mobile,
|
||||||
|
weChatOpenId: account.value.openid,
|
||||||
|
deptIds: [],
|
||||||
|
loginTypes: ["wxApp"],
|
||||||
|
corpId: account.value.corpId,
|
||||||
|
};
|
||||||
|
const res = await api("addCorpMember", {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
if (res.success && res.data) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "创建成功",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
await getDoctorInfo();
|
||||||
|
uni.navigateBack();
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: "创建失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
console.error("创建医生信息失败:", res);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateDoctorInfo = async () => {
|
||||||
|
let params = {
|
||||||
|
anotherName: formData.value.anotherName,
|
||||||
|
avatar: formData.value.avatar,
|
||||||
|
gender: formData.value.gender,
|
||||||
|
};
|
||||||
|
const res = await api("updateCorpMember", {
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
if (res.success && res.data) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "更新成功",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await getDoctorInfo();
|
||||||
|
uni.navigateBack();
|
||||||
|
};
|
||||||
|
// 打开科室选择
|
||||||
|
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>
|
||||||
|
|
||||||
@ -1,211 +1,83 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="profile-page">
|
<full-page>
|
||||||
<!-- 表单区域 -->
|
<view class="p-15">
|
||||||
<view class="form-section bg-white">
|
<view class="bg-white px-10 mb-10 rounded">
|
||||||
<!-- 姓名 -->
|
<form-input :form="formData" required wordLimit="10" title="anotherName" name="姓名" @change="onChange($event)" />
|
||||||
<form-input
|
<common-cell title="avatar" name="头像">
|
||||||
name="姓名"
|
<view class="flex-grow flex items-center justify-end" @click="chooseAvatar()">
|
||||||
:required="true"
|
<image v-if="formData.avatar" class="avatar mr-5 rounded-full" :src="formData.avatar" />
|
||||||
:form="formData"
|
<image v-else class="avatar mr-5 rounded-full" src="/static/default-avatar.png" />
|
||||||
title="anotherName"
|
<uni-icons color="#999" type="right" size="16" />
|
||||||
@change="handleFieldChange"
|
|
||||||
/>
|
|
||||||
<!-- 头像 -->
|
|
||||||
<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>
|
</view>
|
||||||
<uni-icons class="form-arrow" type="arrowright"></uni-icons>
|
</common-cell>
|
||||||
</view>
|
<form-select :form="formData" name="性别" title="gender" :range="genderOptions" @change="onChange($event)" />
|
||||||
</common-cell>
|
<form-input :form="formData" disableChange wordLimit="11" title="mobile" name="手机号 (不可修改)" />
|
||||||
<!-- 性别 -->
|
</view>
|
||||||
<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.mobile }}</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="科室">
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<!-- 个人介绍 -->
|
<view class="bg-white px-10 mb-10 rounded">
|
||||||
<form-textarea
|
<common-cell title="avatar" name="岗位">
|
||||||
name="个人介绍"
|
<view class="flex-grow flex items-center justify-end">
|
||||||
:form="formData"
|
<!-- <view class="mr-5 rounded-full" style="width: 64rpx;height: 64rpx;background: red;"></view> -->
|
||||||
title="intro"
|
<uni-icons color="#999" type="right" size="16" />
|
||||||
:word-limit="500"
|
</view>
|
||||||
@change="handleFieldChange"
|
</common-cell>
|
||||||
/>
|
<common-cell title="avatar" name="职称">
|
||||||
|
<view class="flex-grow flex items-center justify-end">
|
||||||
|
<!-- <view class="mr-5 rounded-full" style="width: 64rpx;height: 64rpx;background: red;"></view> -->
|
||||||
|
<uni-icons color="#999" type="right" size="16" />
|
||||||
|
</view>
|
||||||
|
</common-cell>
|
||||||
|
<common-cell title="avatar" name="科室">
|
||||||
|
<view class="flex-grow flex items-center justify-end">
|
||||||
|
<!-- <view class="mr-5 rounded-full" style="width: 64rpx;height: 64rpx;background: red;"></view> -->
|
||||||
|
<uni-icons color="#999" type="right" size="16" />
|
||||||
|
</view>
|
||||||
|
</common-cell>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="bg-white rounded">
|
||||||
|
<form-textarea :border="false" :form="formData" title="intro" name="个人介绍" :wordLimit="300"
|
||||||
|
@change="onChange($event)" />
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 底部按钮 -->
|
<template #footer>
|
||||||
<view class="button-footer">
|
<button-footer :cancelText="cancelText" :confirmText="confirmText" @confirm="save()" @cancel="back()" />
|
||||||
<view class="btn btn-cancel" @click="handleCancel">取消</view>
|
</template>
|
||||||
<view class="btn btn-save" @click="handleSave">保存</view>
|
</full-page>
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import useGuard from "@/hooks/useGuard.js";
|
|
||||||
import { chooseAndUploadImage } from "@/utils/file.js";
|
|
||||||
import useAccountStore from "@/store/account.js";
|
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import CommonCell from "@/components/form-template/common-cell.vue";
|
import useGuard from "@/hooks/useGuard.js";
|
||||||
|
import useAccountStore from "@/store/account.js";
|
||||||
|
import api from "@/utils/api.js";
|
||||||
|
import { upload } from "@/utils/http.js";
|
||||||
|
import { toast } from "@/utils/widget";
|
||||||
|
|
||||||
|
import buttonFooter from '@/components/button-footer.vue';
|
||||||
|
import commonCell from "@/components/form-template/common-cell.vue";
|
||||||
import FormInput from "@/components/form-template/form-cell/form-input.vue";
|
import FormInput from "@/components/form-template/form-cell/form-input.vue";
|
||||||
import FormSelect from "@/components/form-template/form-cell/form-select.vue";
|
import FormSelect from "@/components/form-template/form-cell/form-select.vue";
|
||||||
import FormTextarea from "@/components/form-template/form-cell/form-textarea.vue";
|
import FormTextarea from "@/components/form-template/form-cell/form-textarea.vue";
|
||||||
import api from "@/utils/api.js";
|
import fullPage from '@/components/full-page.vue';
|
||||||
|
|
||||||
const { account, doctorInfo } = storeToRefs(useAccountStore());
|
const { account, doctorInfo } = storeToRefs(useAccountStore());
|
||||||
const { useLoad } = useGuard();
|
const { useLoad, useShow } = useGuard();
|
||||||
const { getDoctorInfo } = useAccountStore();
|
const { getDoctorInfo } = useAccountStore();
|
||||||
// 表单数据
|
|
||||||
const formData = ref({
|
const form = ref({});
|
||||||
anotherName: "",
|
const type = ref('')
|
||||||
avatar: "",
|
const formData = computed(() => ({ ...(doctorInfo.value || {}), ...form.value, mobile: account.value?.mobile }));
|
||||||
gender: "",
|
const cancelText = computed(() => doctorInfo.value ? '取消' : '暂不填写');
|
||||||
mobile: "",
|
const confirmText = computed(() => type.value === 'cert' ? '下一步' : '保存');
|
||||||
position: "",
|
|
||||||
title: "",
|
|
||||||
department: "",
|
|
||||||
departmentName: "",
|
|
||||||
departmentId: "",
|
|
||||||
intro: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 选项数据
|
// 选项数据
|
||||||
const genderOptions = [
|
const genderOptions = [
|
||||||
{ label: "男", value: "0" },
|
{ label: "男", value: "0" },
|
||||||
{ label: "女", value: "1" },
|
{ label: "女", value: "1" },
|
||||||
];
|
];
|
||||||
const positionOptions = ["医生", "护士", "药师", "技师", "其他"];
|
|
||||||
const titleOptions = ["主任医师", "副主任医师", "主治医师", "医师", "其他"];
|
|
||||||
// 字段变更处理
|
|
||||||
const handleFieldChange = (e) => {
|
|
||||||
if (e.title === "gender") {
|
|
||||||
formData.value[e.title] = e.value.value;
|
|
||||||
} else {
|
|
||||||
formData.value[e.title] = e.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 选择头像
|
|
||||||
const chooseAvatar = async () => {
|
|
||||||
const url = await chooseAndUploadImage();
|
|
||||||
if (url) {
|
|
||||||
formData.value.avatar = url;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
|
||||||
uni.navigateBack();
|
|
||||||
};
|
|
||||||
// 保存
|
|
||||||
const handleSave = async () => {
|
|
||||||
createDoctorInfo();
|
|
||||||
};
|
|
||||||
useLoad(() => {
|
|
||||||
if (doctorInfo.value) {
|
|
||||||
formData.value = { ...doctorInfo.value };
|
|
||||||
} else {
|
|
||||||
formData.value.mobile = account.value.mobile;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 创建医生信息
|
|
||||||
const createDoctorInfo = async () => {
|
|
||||||
if (!formData.value.anotherName) {
|
|
||||||
uni.showToast({
|
|
||||||
title: "请输入姓名",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let params = {
|
|
||||||
anotherName: formData.value.anotherName,
|
|
||||||
avatar: formData.value.avatar,
|
|
||||||
gender: formData.value.gender,
|
|
||||||
mobile: formData.value.mobile,
|
|
||||||
weChatOpenId: account.value.openid,
|
|
||||||
deptIds: [],
|
|
||||||
loginTypes: ["wxApp"],
|
|
||||||
corpId: account.value.corpId,
|
|
||||||
};
|
|
||||||
const res = await api("addCorpMember", {
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
if (res.success && res.data) {
|
|
||||||
uni.showToast({
|
|
||||||
title: "创建成功",
|
|
||||||
icon: "success",
|
|
||||||
});
|
|
||||||
await getDoctorInfo();
|
|
||||||
uni.navigateBack();
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: "创建失败",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
console.error("创建医生信息失败:", res);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateDoctorInfo = async () => {
|
|
||||||
let params = {
|
|
||||||
anotherName: formData.value.anotherName,
|
|
||||||
avatar: formData.value.avatar,
|
|
||||||
gender: formData.value.gender,
|
|
||||||
};
|
|
||||||
const res = await api("updateCorpMember", {
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
if (res.success && res.data) {
|
|
||||||
uni.showToast({
|
|
||||||
title: "更新成功",
|
|
||||||
icon: "success",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await getDoctorInfo();
|
|
||||||
uni.navigateBack();
|
|
||||||
};
|
|
||||||
// 打开科室选择
|
// 打开科室选择
|
||||||
const openDepartmentSelect = () => {
|
const openDepartmentSelect = () => {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
@ -219,89 +91,74 @@ const openDepartmentSelect = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function back() {
|
||||||
|
const pages = getCurrentPages();
|
||||||
|
if (pages.length > 1) {
|
||||||
|
uni.navigateBack();
|
||||||
|
} else {
|
||||||
|
uni.switchTab({
|
||||||
|
url: "/pages/work/work",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function chooseAvatar() {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
success: async (res) => {
|
||||||
|
const [path] = res.tempFilePaths;
|
||||||
|
const url = await upload(path);
|
||||||
|
if (url) {
|
||||||
|
form.value.avatar = url;
|
||||||
|
} else {
|
||||||
|
toast('上传失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange({ title, value }) {
|
||||||
|
form.value[title] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
async function save() {
|
||||||
|
if (typeof formData.value.anotherName !== 'string' || !formData.value.anotherName.trim()) {
|
||||||
|
return toast('请输入姓名')
|
||||||
|
}
|
||||||
|
if (type.value === 'cert' && !formData.value.departmentId) {
|
||||||
|
return toast('请输入岗位信息')
|
||||||
|
}
|
||||||
|
const apiName = doctorInfo.value ? 'updateCorpMemberFromWxapp' : 'addCorpMemberFromWxapp';
|
||||||
|
const data = {
|
||||||
|
...form.value,
|
||||||
|
weChatOpenId: account.value.openid,
|
||||||
|
mobile: account.value.mobile,
|
||||||
|
corpId: account.value.corpId,
|
||||||
|
}
|
||||||
|
const res = await api(apiName, data);
|
||||||
|
if (res && res.success) {
|
||||||
|
await toast('保存成功');
|
||||||
|
await getDoctorInfo()
|
||||||
|
back()
|
||||||
|
} else {
|
||||||
|
await toast(res?.message || '保存失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useLoad(opts => {
|
||||||
|
type.value = opts?.type;
|
||||||
|
})
|
||||||
|
|
||||||
|
useShow(() => {
|
||||||
|
getDoctorInfo()
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.profile-page {
|
.avatar {
|
||||||
min-height: 100vh;
|
width: 64rpx;
|
||||||
background: #f5f5f5;
|
height: 64rpx;
|
||||||
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>
|
</style>
|
||||||
|
|
||||||
|
|||||||
164
pages/work/verify/assistant.vue
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
<template>
|
||||||
|
<full-page pageClass="bg-white">
|
||||||
|
<view class="p-15">
|
||||||
|
<view class="mt-15 title-bar relative font-semibold">
|
||||||
|
<text class="mr-5 text-dark text-base">请上传</text>
|
||||||
|
<text class="text-primary text-base">身份证正反面</text>
|
||||||
|
</view>
|
||||||
|
<view class="mt-12 flex items-center justify-between">
|
||||||
|
<view class="album border rounded overflow-hidden" @click="uploadIdCard('idCardFront')">
|
||||||
|
<image v-if="form.idCardFront" class="w-full h-full" :src="form.idCardFront" />
|
||||||
|
<view v-else class="relative w-full h-full ">
|
||||||
|
<image class="absolute w-full h-full" src="/static/work/fIDCard.png" />
|
||||||
|
<view class="absolute w-full h-full flex flex-col items-center justify-center">
|
||||||
|
<image class="carmra-icon" src="/static/work/camera.png" />
|
||||||
|
<view class="text-lg font-semibold color-428">上传人像面</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="album border rounded overflow-hidden" @click="uploadIdCard('idCardBack')">
|
||||||
|
<image v-if="form.idCardBack" class="w-full h-full" :src="form.idCardBack" />
|
||||||
|
<view v-else class="relative w-full h-full ">
|
||||||
|
<image class="absolute w-full h-full" src="/static/work/aIDCard.png" />
|
||||||
|
<view class="absolute w-full h-full flex flex-col items-center justify-center">
|
||||||
|
<image class="carmra-icon" src="/static/work/camera.png" />
|
||||||
|
<view class="text-lg font-semibold color-428">上传国徽面</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="exam px-15 rounded-sm leading-normal text-dark text-base">
|
||||||
|
身份证示例
|
||||||
|
</view>
|
||||||
|
<view class="mt-12 flex items-center justify-between">
|
||||||
|
<image class="album" src="/static/work/cardFront.png" />
|
||||||
|
<image class="album" src="/static/work/cardBack.png" />
|
||||||
|
</view>
|
||||||
|
<view class="mt-12 text-dark font-semibold text-base">拍摄须知</view>
|
||||||
|
<view class="mt-10 flex items-center justify-between">
|
||||||
|
<view class="flex flex-col items-center justify-center">
|
||||||
|
<image class="mb-5 exam-icon" src="/static/work/fIDCard.png" />
|
||||||
|
<image class="mb-5 status-icon" src="/static/work/hook.png" />
|
||||||
|
<view class="text-base text-dark">标准</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center justify-center">
|
||||||
|
<image class="mb-5 exam-icon" src="/static/work/lackCard.png" />
|
||||||
|
<image class="mb-5 status-icon" src="/static/work/error.png" />
|
||||||
|
<view class="text-base text-dark">缺边</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center justify-center">
|
||||||
|
<image class="mb-5 exam-icon" src="/static/work/vagueCard.png" />
|
||||||
|
<image class="mb-5 status-icon" src="/static/work/error.png" />
|
||||||
|
<view class="text-base text-dark">模糊</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center justify-center">
|
||||||
|
<image class="mb-5 exam-icon" src="/static/work/flashCard.png" />
|
||||||
|
<image class="mb-5 status-icon" src="/static/work/error.png" />
|
||||||
|
<view class="text-base text-dark">闪光</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<template #footer>
|
||||||
|
<button-footer cancelText="上一步" confirmText="提交审核" @confirm="save()" @cancel="back()" />
|
||||||
|
</template>
|
||||||
|
</full-page>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import useGuard from "@/hooks/useGuard.js";
|
||||||
|
import useAccountStore from "@/store/account.js";
|
||||||
|
import { upload } from "@/utils/http.js";
|
||||||
|
import { hideLoading, loading as showLoading, toast } from "@/utils/widget";
|
||||||
|
|
||||||
|
import buttonFooter from '@/components/button-footer.vue';
|
||||||
|
import fullPage from '@/components/full-page.vue';
|
||||||
|
|
||||||
|
useGuard();
|
||||||
|
|
||||||
|
const { account, doctorInfo } = storeToRefs(useAccountStore());
|
||||||
|
const form = ref({})
|
||||||
|
const formData = computed(() => ({ ...(doctorInfo.value || {}), ...form.value }))
|
||||||
|
|
||||||
|
function back() {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadIdCard(type) {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
success: async (res) => {
|
||||||
|
const [path] = res.tempFilePaths;
|
||||||
|
showLoading('正在上传')
|
||||||
|
const url = await upload(path);
|
||||||
|
hideLoading()
|
||||||
|
if (url) {
|
||||||
|
form.value[type] = url;
|
||||||
|
} else {
|
||||||
|
toast('上传失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function save() {
|
||||||
|
if (typeof formData.value.idCardFront !== 'string' || formData.value.idCardFront.trim() === '') {
|
||||||
|
return toast('请上传人像面')
|
||||||
|
}
|
||||||
|
if (typeof formData.value.idCardBack !== 'string' || formData.value.idCardBack.trim() === '') {
|
||||||
|
return toast('请上传国徽面')
|
||||||
|
}
|
||||||
|
console.log('form.value: ', formData.value)
|
||||||
|
|
||||||
|
// uni.showToast({ title: '提交成功', icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.title-bar {
|
||||||
|
padding-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
height: 80%;
|
||||||
|
width: 8rpx;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
border-radius: 4rpx;
|
||||||
|
background: #0074ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album {
|
||||||
|
width: 330rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carmra-icon {
|
||||||
|
width: 96rpx;
|
||||||
|
height: 96rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-428 {
|
||||||
|
color: #428bf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exam {
|
||||||
|
margin-top: 80rpx;
|
||||||
|
background: #dde6f6;
|
||||||
|
padding: 8rpx 30rpx;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exam-icon {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 104rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-icon {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
126
pages/work/verify/doctor.vue
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<full-page pageClass="bg-white">
|
||||||
|
<view class="p-15">
|
||||||
|
<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="w-0 flex-grow truncate text-base mr-10" :class="formData.hospitalName ? 'text-dark' : 'text-gray'">
|
||||||
|
{{ formData.hospitalName || '请填写执业医院' }}
|
||||||
|
</view>
|
||||||
|
<uni-icons class="flex-shrink-0" color="#666" type="right" size="16" />
|
||||||
|
</view>
|
||||||
|
<view class="mt-15 title-bar relative font-semibold">
|
||||||
|
<text class="mr-5 text-dark text-base">请上传</text>
|
||||||
|
<text class="text-primary text-base">医师执业资格证</text>
|
||||||
|
</view>
|
||||||
|
<view class="mt-12 flex items-center justify-between">
|
||||||
|
<view class="album border rounded overflow-hidden" @click="uploadLicense('medicalLicenseFront')">
|
||||||
|
<image v-if="formData.medicalLicenseFront" class="w-full h-full" :src="formData.medicalLicenseFront" />
|
||||||
|
<view v-else class="w-full h-full flex flex-col items-center justify-center">
|
||||||
|
<uni-icons color="#666" type="camera" size="36" />
|
||||||
|
<view class="text-dark text-base">上传第一页</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="album border rounded overflow-hidden" @click="uploadLicense('medicalLicenseBack')">
|
||||||
|
<image v-if="formData.medicalLicenseBack" class="w-full h-full" :src="formData.medicalLicenseBack" />
|
||||||
|
<view v-else class="w-full h-full flex flex-col items-center justify-center">
|
||||||
|
<uni-icons color="#666" type="camera" size="36" />
|
||||||
|
<view class="text-dark text-base">上传第二页</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="exam px-15 rounded-sm leading-normal text-dark text-base">
|
||||||
|
证书示例
|
||||||
|
</view>
|
||||||
|
<view class="mt-10 text-sm text-dark leading-normal">1、确保姓名、照片、编号、执业范围、签发机关等清晰可见</view>
|
||||||
|
<view class="mt-10 text-sm text-dark leading-normal">2、需上传证书第一、第二页,图片仅供参考,以实际证书为准</view>
|
||||||
|
<view class="mt-12 flex items-center justify-between">
|
||||||
|
<image class="album" src="/static/work/licenseFront.png" />
|
||||||
|
<image class="album" src="/static/work/licenseBack.png" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<template #footer>
|
||||||
|
<button-footer cancelText="上一步" confirmText="提交审核" @confirm="save()" @cancel="back()" />
|
||||||
|
</template>
|
||||||
|
</full-page>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import useGuard from "@/hooks/useGuard.js";
|
||||||
|
import useAccountStore from "@/store/account.js";
|
||||||
|
import { upload } from "@/utils/http.js";
|
||||||
|
import { hideLoading, loading as showLoading, toast } from "@/utils/widget";
|
||||||
|
|
||||||
|
import buttonFooter from '@/components/button-footer.vue';
|
||||||
|
import fullPage from '@/components/full-page.vue';
|
||||||
|
|
||||||
|
useGuard();
|
||||||
|
const { account, doctorInfo } = storeToRefs(useAccountStore());
|
||||||
|
const form = ref({});
|
||||||
|
const formData = computed(() => ({ ...(doctorInfo.value || {}), ...form.value }))
|
||||||
|
|
||||||
|
function back() {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadLicense(type) {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
success: async (res) => {
|
||||||
|
const [path] = res.tempFilePaths;
|
||||||
|
showLoading('正在上传')
|
||||||
|
const url = await upload(path);
|
||||||
|
hideLoading()
|
||||||
|
if (url) {
|
||||||
|
form.value[type] = url;
|
||||||
|
} else {
|
||||||
|
toast('上传失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function save() {
|
||||||
|
if (typeof formData.value.hospitalName !== 'string' || formData.value.hospitalName.trim() === '') {
|
||||||
|
return toast('请填写执业医院')
|
||||||
|
}
|
||||||
|
if (typeof formData.value.medicalLicenseFront !== 'string' || formData.value.medicalLicenseFront.trim() === '') {
|
||||||
|
return toast('请上传医师执业资格证第一页')
|
||||||
|
}
|
||||||
|
if (typeof formData.value.medicalLicenseBack !== 'string' || formData.value.medicalLicenseBack.trim() === '') {
|
||||||
|
return toast('请上传医师执业资格证第二页')
|
||||||
|
}
|
||||||
|
console.log('form.value: ', formData.value)
|
||||||
|
|
||||||
|
// uni.showToast({ title: '提交成功', icon: 'none' })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.title-bar {
|
||||||
|
padding-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-bar::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
height: 80%;
|
||||||
|
width: 8rpx;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
border-radius: 4rpx;
|
||||||
|
background: #0074ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album {
|
||||||
|
width: 330rpx;
|
||||||
|
height: 240rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exam {
|
||||||
|
margin-top: 80rpx;
|
||||||
|
background: #dde6f6;
|
||||||
|
padding: 8rpx 30rpx;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,80 +1,93 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="work-page">
|
<full-page :showSafeArea="false" :customScroll="true">
|
||||||
<!-- 顶部用户信息区域 -->
|
<template #header>
|
||||||
<view class="user-header bg-white px-15 py-15">
|
<view class="user-header bg-white px-15 py-15">
|
||||||
<view class="flex items-center justify-between">
|
<view class="flex items-center justify-between" @click="editProfile()">
|
||||||
<!-- 左侧:用户头像和信息 -->
|
<view class="flex items-center flex-grow">
|
||||||
<view class="flex items-center flex-grow">
|
<view class="relative user-avatar mr-10">
|
||||||
<view class="user-avatar mr-10">
|
<image v-if="doctorInfo && doctorInfo.avatar" class="avatar-img rounded-full overflow-hidden"
|
||||||
<image
|
:src="doctorInfo.avatar" mode="aspectFill" />
|
||||||
class="avatar-img"
|
<image v-else class="avatar-img rounded-full overflow-hidden" src="/static/default-avatar.png"
|
||||||
src="/static/default-avatar.png"
|
mode="aspectFill" />
|
||||||
mode="aspectFill"
|
<view v-if="doctorInfo" class="edit-sub flex items-center justify-center rounded-full bg-primary">
|
||||||
/>
|
<image class="edit-icon" src="/static/work/pen.svg" mode="aspectFill" />
|
||||||
</view>
|
|
||||||
<view class="flex-col">
|
|
||||||
<text class="user-name text-black text-lg font-semibold"
|
|
||||||
>请完善信息</text
|
|
||||||
>
|
|
||||||
<view class="flex items-center mt-5">
|
|
||||||
<view
|
|
||||||
class="status-tag tag-orange mr-10"
|
|
||||||
@click="handleCompleteInfo"
|
|
||||||
>
|
|
||||||
<text class="tag-text text-white">信息待完善</text>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="status-tag tag-gray" @click="handleVerify">
|
</view>
|
||||||
<text class="tag-text text-dark">未认证</text>
|
<view class="flex-col">
|
||||||
|
<text v-if="doctorInfo && doctorInfo.anotherName" class="user-name text-dark text-lg font-semibold">
|
||||||
|
{{ doctorInfo.anotherName }}
|
||||||
|
</text>
|
||||||
|
<text v-else class="user-name text-black text-lg font-semibold">请完善信息</text>
|
||||||
|
<view class="flex items-center mt-5">
|
||||||
|
<view v-if="!doctorInfo || !doctorInfo.anotherName" class="status-tag tag-orange mr-10">
|
||||||
|
<text class="tag-text text-white">信息待完善</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="certStatus" class="px-10 py-3 text-sm rounded-full" :class="certStatus.classnames"
|
||||||
|
@click.stop="toCert()">
|
||||||
|
{{ certStatus.text }}
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 右侧:操作按钮 -->
|
<!-- 右侧:操作按钮 -->
|
||||||
<view class="flex items-center">
|
<view class="flex items-center">
|
||||||
<view
|
<view class="action-btn flex-col items-center mr-10" @click="handleInvitePatient">
|
||||||
class="action-btn flex-col items-center mr-15"
|
<image class="mb-5 qrcode-icon" src="/static/work/qrcode.svg" />
|
||||||
@click="handleInvitePatient"
|
<text class="action-text text-dark text-sm">邀请</text>
|
||||||
>
|
</view>
|
||||||
<view class="qrcode-icon">
|
<view class="action-btn flex-col items-center" @click="handleMore">
|
||||||
<text class="qrcode-text">▦</text>
|
<image class="mb-5 qrcode-icon" src="/static/work/more.svg" />
|
||||||
|
<text class="action-text text-dark text-sm">更多</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="action-text text-black text-sm mt-5">邀请患者</text>
|
|
||||||
</view>
|
|
||||||
<view class="more-btn" @click="handleMore">
|
|
||||||
<text class="more-icon">⋯</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
<view class="mt-15 px-15 py-12 text-dark text-lg font-semibold bg-white border-b">
|
||||||
|
待办列表11
|
||||||
<!-- 待办列表区域 -->
|
|
||||||
<view class="todo-section px-15 mt-15">
|
|
||||||
<view class="section-title mb-15">
|
|
||||||
<text class="text-black text-lg font-semibold">待办列表11</text>
|
|
||||||
</view>
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- 空状态 -->
|
<scroll-view v-if="list.length" scroll-y="true" class="h-full bg-white">
|
||||||
<view class="empty-state">
|
<view class="p-15">
|
||||||
<empty-data text="暂无记录" />
|
<view v-for="i in 10" class="p-15 bg-primary mb-10"></view>
|
||||||
</view>
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view v-else class="flex flex-col items-center justify-center h-full bg-white">
|
||||||
|
<empty-data text="暂无记录" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
<template #footer>
|
||||||
|
<view class="border-b"></view>
|
||||||
|
</template>
|
||||||
|
</full-page>
|
||||||
|
<cert-popup :visible="visible" @close="visible = false" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
import useGuard from "@/hooks/useGuard.js";
|
import useGuard from "@/hooks/useGuard.js";
|
||||||
|
import useAccountStore from "@/store/account.js";
|
||||||
|
|
||||||
|
import certPopup from "./components/cert-popup.vue";
|
||||||
import EmptyData from "@/components/empty-data.vue";
|
import EmptyData from "@/components/empty-data.vue";
|
||||||
|
import fullPage from '@/components/full-page.vue';
|
||||||
|
|
||||||
const { useLoad } = useGuard();
|
const certConfig = {
|
||||||
|
verified: { text: '已认证', classnames: 'bg-success text-white' },
|
||||||
// 完善信息
|
verifing: { text: '认证中', classnames: 'bg-orange text-white' },
|
||||||
const handleCompleteInfo = () => {
|
unverified: { text: '未认证', classnames: 'bg-gray text-dark' },
|
||||||
uni.navigateTo({
|
|
||||||
url: "/pages/work/profile",
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { useLoad, useShow } = useGuard();
|
||||||
|
const { getDoctorInfo } = useAccountStore();
|
||||||
|
const { doctorInfo } = storeToRefs(useAccountStore());
|
||||||
|
const list = ref([1]);
|
||||||
|
const visible = ref(false);
|
||||||
|
|
||||||
|
const certStatus = computed(() => doctorInfo.value?.verifyStatus ? certConfig[doctorInfo.value.verifyStatus] : certConfig.unverified)
|
||||||
|
|
||||||
// 认证
|
// 认证
|
||||||
const handleVerify = () => {
|
const handleVerify = () => {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@ -101,15 +114,39 @@ const handleMore = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function editProfile() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/work/profile",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toCert() {
|
||||||
|
// if (doctorInfo.value.verifyStatus === 'unverified') {
|
||||||
|
visible.value = true
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
useLoad(() => {
|
useLoad(() => {
|
||||||
console.log("工作台页面加载");
|
console.log("工作台页面加载");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useShow(() => {
|
||||||
|
getDoctorInfo()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.work-page {
|
.edit-sub {
|
||||||
min-height: 100vh;
|
width: 36rpx;
|
||||||
background: #f5f5f5;
|
height: 36rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-icon {
|
||||||
|
width: 24rpx;
|
||||||
|
height: 24rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-header {
|
.user-header {
|
||||||
@ -119,9 +156,6 @@ useLoad(() => {
|
|||||||
.user-avatar {
|
.user-avatar {
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
border-radius: 50%;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #e5e5e5;
|
|
||||||
|
|
||||||
.avatar-img {
|
.avatar-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -133,6 +167,11 @@ useLoad(() => {
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.py-3 {
|
||||||
|
padding-top: 6rpx;
|
||||||
|
padding-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.status-tag {
|
.status-tag {
|
||||||
padding: 6rpx 16rpx;
|
padding: 6rpx 16rpx;
|
||||||
border-radius: 20rpx;
|
border-radius: 20rpx;
|
||||||
@ -162,17 +201,8 @@ useLoad(() => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
.qrcode-icon {
|
.qrcode-icon {
|
||||||
width: 48rpx;
|
width: 40rpx;
|
||||||
height: 48rpx;
|
height: 40rpx;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.qrcode-text {
|
|
||||||
font-size: 40rpx;
|
|
||||||
color: #333;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-text {
|
.action-text {
|
||||||
@ -209,5 +239,4 @@ useLoad(() => {
|
|||||||
// align-items: center;
|
// align-items: center;
|
||||||
// justify-content: center;
|
// justify-content: center;
|
||||||
// width: 100%;
|
// width: 100%;
|
||||||
// }
|
// }</style>
|
||||||
</style>
|
|
||||||
@ -1,20 +1,36 @@
|
|||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
path: 'pages/message/message',
|
path: 'pages/message/message',
|
||||||
meta: { title: '首页', login: false },
|
meta: { title: '消息' },
|
||||||
style: { navigationStyle: 'custom' }
|
style: { navigationStyle: 'custom' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'pages/work/work',
|
path: 'pages/work/work',
|
||||||
meta: { title: '工作台', login: false }
|
meta: { title: '工作台' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'pages/case/case',
|
||||||
|
meta: { title: '病例' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'pages/work/profile',
|
path: 'pages/work/profile',
|
||||||
meta: { title: '完善个人信息', login: false }
|
meta: { title: '完善个人信息' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'pages/work/department-select',
|
path: 'pages/work/department-select',
|
||||||
meta: { title: '选择科室', login: false }
|
meta: { title: '选择科室' }
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
path: 'pages/work/verify/assistant',
|
||||||
|
meta: { title: '上传证照', login: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'pages/work/verify/doctor',
|
||||||
|
meta: { title: '上传证照', login: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'pages/login/login',
|
||||||
|
meta: { title: '授权登录' }
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
BIN
static/work/aIDCard.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
static/work/camera.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
static/work/cardBack.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
static/work/cardFront.png
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
static/work/error.png
Normal file
|
After Width: | Height: | Size: 960 B |
BIN
static/work/fIDCard.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
static/work/flashCard.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
static/work/hook.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
static/work/lackCard.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
static/work/licenseBack.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
static/work/licenseFront.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
1
static/work/more.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1769069890058" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14332" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M378.112 481.536H159.488c-51.2 0-92.928-41.728-92.928-92.928V169.984c0-51.2 41.728-92.928 92.928-92.928h218.624c51.2 0 92.928 41.728 92.928 92.928v218.624c0 51.2-41.728 92.928-92.928 92.928zM159.488 138.752c-17.408 0-31.488 14.08-31.488 31.488v218.624c0 17.408 14.08 31.488 31.488 31.488h218.624c17.408 0 31.488-14.08 31.488-31.488V169.984c0-17.408-14.08-31.488-31.488-31.488H159.488zM378.112 949.504H159.488c-51.2 0-92.928-41.728-92.928-92.928v-218.624c0-51.2 41.728-92.928 92.928-92.928h218.624c51.2 0 92.928 41.728 92.928 92.928v218.624c0 51.456-41.728 92.928-92.928 92.928zM159.488 606.72c-17.408 0-31.488 14.08-31.488 31.488v218.624c0 17.408 14.08 31.488 31.488 31.488h218.624c17.408 0 31.488-14.08 31.488-31.488v-218.624c0-17.408-14.08-31.488-31.488-31.488H159.488zM680.448 480l-143.616-144.128c-33.536-33.792-33.536-88.576 0.256-122.112l144.128-143.616c33.792-33.536 88.576-33.536 122.112 0.256l143.616 144.128c33.536 33.792 33.536 88.576-0.256 122.112l-144.128 143.616c-33.792 33.536-88.32 33.536-122.112-0.256zM762.88 110.848c-11.264-11.52-29.952-11.52-41.216 0l-144.128 143.616c-11.52 11.264-11.52 29.952 0 41.216l143.616 144.128c11.264 11.52 29.952 11.52 41.216 0l144.128-143.616c11.52-11.264 11.52-29.952 0-41.216L762.88 110.848zM840.96 949.504l-218.624-0.512c-51.2 0-92.672-41.728-92.672-92.928l0.512-218.624c0-51.2 41.728-92.672 92.928-92.672l218.624 0.512c51.2 0 92.672 41.728 92.672 92.928l-0.512 218.624c0 51.2-41.728 92.928-92.928 92.672z m-217.856-343.04c-17.408 0-31.488 14.08-31.488 31.232l-0.512 218.624c0 17.408 14.08 31.488 31.232 31.488l218.624 0.512c17.408 0 31.488-14.08 31.488-31.232l0.512-218.624c0-17.408-14.08-31.488-31.232-31.488l-218.624-0.512z" fill="#2c2c2c" p-id="14333"></path></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
1
static/work/pen.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1769067872142" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10445" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M581.50172 186.48l256.04 256.04-555.98 555.98-228.28 25.2C22.72172 1027.08-3.09828 1001.24 0.30172 970.68l25.4-228.44 555.8-555.76z m414.4-38.12l-120.22-120.22c-37.5-37.5-98.32-37.5-135.82 0l-113.1 113.1 256.04 256.04 113.1-113.1c37.5-37.52 37.5-98.32 0-135.82z" fill="#ffffff" p-id="10446"></path></svg>
|
||||||
|
After Width: | Height: | Size: 638 B |
1
static/work/qrcode.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1769069475491" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11505" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M85.312 85.312V384H384V85.312H85.312zM0 0h469.248v469.248H0V0z m170.624 170.624h128v128h-128v-128zM0 554.624h469.248v469.248H0V554.624z m85.312 85.312v298.624H384V639.936H85.312z m85.312 85.312h128v128h-128v-128zM554.624 0h469.248v469.248H554.624V0z m85.312 85.312V384h298.624V85.312H639.936z m383.936 682.56H1024v85.376h-298.752V639.936H639.936V1023.872H554.624V554.624h255.936v213.248h128V554.624h85.312v213.248z m-298.624-597.248h128v128h-128v-128z m298.624 853.248h-85.312v-85.312h85.312v85.312z m-213.312 0h-85.312v-85.312h85.312v85.312z" fill="#262626" p-id="11506"></path></svg>
|
||||||
|
After Width: | Height: | Size: 919 B |
BIN
static/work/vagueCard.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
@ -8,15 +8,27 @@ const env = __VITE_ENV__;
|
|||||||
|
|
||||||
export default defineStore("accountStore", () => {
|
export default defineStore("accountStore", () => {
|
||||||
const appid = env.MP_WX_APP_ID;
|
const appid = env.MP_WX_APP_ID;
|
||||||
|
const corpId = env.MP_CORP_ID;
|
||||||
const account = ref(null);
|
const account = ref(null);
|
||||||
const loading = ref(false)
|
const loading = ref(false);
|
||||||
|
const loginPromise = ref(null);
|
||||||
// IM 相关
|
// IM 相关
|
||||||
const openid = ref("");
|
const openid = ref("");
|
||||||
// 医生信息
|
// 医生信息
|
||||||
const doctorInfo = ref(null);
|
const doctorInfo = ref(null);
|
||||||
async function login(phoneCode = '') {
|
|
||||||
if (loading.value) return;
|
function getLoginPromise(phoneCode = '') {
|
||||||
loading.value = true;
|
if (loginPromise.value) return loginPromise.value;
|
||||||
|
loginPromise.value = loginByCode(phoneCode);
|
||||||
|
return loginPromise.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login(phoneCode) {
|
||||||
|
await getLoginPromise(phoneCode);
|
||||||
|
loginPromise.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loginByCode(phoneCode = '') {
|
||||||
try {
|
try {
|
||||||
const { code } = await uni.login({
|
const { code } = await uni.login({
|
||||||
appid,
|
appid,
|
||||||
@ -27,8 +39,8 @@ export default defineStore("accountStore", () => {
|
|||||||
const res = await api('wxAppLogin', {
|
const res = await api('wxAppLogin', {
|
||||||
phoneCode,
|
phoneCode,
|
||||||
code,
|
code,
|
||||||
|
corpId,
|
||||||
});
|
});
|
||||||
loading.value = false;
|
|
||||||
if (res.success && res.data) {
|
if (res.success && res.data) {
|
||||||
if (!res.data.mobile) {
|
if (!res.data.mobile) {
|
||||||
const target = '/pages/login/login';
|
const target = '/pages/login/login';
|
||||||
@ -42,11 +54,13 @@ export default defineStore("accountStore", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
toast('登录失败,请重新登录');
|
toast('登录失败,请重新登录');
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast('登录失败,请重新登录');
|
toast('登录失败,请重新登录');
|
||||||
}
|
}
|
||||||
loading.value = false
|
return Promise.reject()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDoctorInfo() {
|
async function getDoctorInfo() {
|
||||||
try {
|
try {
|
||||||
const res = await api('getCorpMemberData', {
|
const res = await api('getCorpMemberData', {
|
||||||
|
|||||||
@ -11,7 +11,9 @@ const urlsConfig = {
|
|||||||
getHospitalList: 'getRealHospital',
|
getHospitalList: 'getRealHospital',
|
||||||
addCorpMember: 'addCorpMember',
|
addCorpMember: 'addCorpMember',
|
||||||
getCorpMemberData: 'getCorpMemberData',
|
getCorpMemberData: 'getCorpMemberData',
|
||||||
updateCorpMember: 'updateCorpMember'
|
updateCorpMember: 'updateCorpMember',
|
||||||
|
addCorpMemberFromWxapp: "addCorpMemberFromWxapp",
|
||||||
|
updateCorpMemberFromWxapp: "updateCorpMemberFromWxapp"
|
||||||
},
|
},
|
||||||
|
|
||||||
knowledgeBase: {
|
knowledgeBase: {
|
||||||
|
|||||||
173
utils/http.js
@ -21,21 +21,21 @@ let retryQueue = [];
|
|||||||
* @param {String} token - 新的 token
|
* @param {String} token - 新的 token
|
||||||
*/
|
*/
|
||||||
function processQueue(token) {
|
function processQueue(token) {
|
||||||
retryQueue.forEach(({ resolve, reject, config }) => {
|
retryQueue.forEach(({ resolve, reject, config }) => {
|
||||||
if (token) {
|
if (token) {
|
||||||
// 更新 token 并重试请求
|
// 更新 token 并重试请求
|
||||||
if (!config.header) config.header = {};
|
if (!config.header) config.header = {};
|
||||||
config.header.Authorization = `Bearer ${token}`;
|
config.header.Authorization = `Bearer ${token}`;
|
||||||
uni.request({
|
uni.request({
|
||||||
...config,
|
...config,
|
||||||
success: (res) => resolve(res),
|
success: (res) => resolve(res),
|
||||||
fail: (err) => reject(err),
|
fail: (err) => reject(err),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
reject(new Error("Token 刷新失败"));
|
reject(new Error("Token 刷新失败"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
retryQueue = [];
|
retryQueue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,114 +43,114 @@ function processQueue(token) {
|
|||||||
* @returns {Promise<String|null>}
|
* @returns {Promise<String|null>}
|
||||||
*/
|
*/
|
||||||
async function refreshAccessToken() {
|
async function refreshAccessToken() {
|
||||||
const refreshToken = uni.getStorageSync("refreshToken");
|
const refreshToken = uni.getStorageSync("refreshToken");
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRefreshing) {
|
if (isRefreshing) {
|
||||||
// 等待刷新完成
|
// 等待刷新完成
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
return uni.getStorageSync("accessToken");
|
return uni.getStorageSync("accessToken");
|
||||||
}
|
}
|
||||||
|
|
||||||
isRefreshing = true;
|
isRefreshing = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await uni.request({
|
const res = await uni.request({
|
||||||
url: `${baseUrl}/auth/refresh`,
|
url: `${baseUrl}/auth/refresh`,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
header: {
|
header: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
refreshToken,
|
refreshToken,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res && res.data && res.data.success && res.data.data) {
|
if (res && res.data && res.data.success && res.data.data) {
|
||||||
const newToken = res.data.data.accessToken;
|
const newToken = res.data.data.accessToken;
|
||||||
uni.setStorageSync("accessToken", newToken);
|
uni.setStorageSync("accessToken", newToken);
|
||||||
processQueue(newToken);
|
processQueue(newToken);
|
||||||
return newToken;
|
return newToken;
|
||||||
} else {
|
} else {
|
||||||
// 刷新失败,清空队列
|
// 刷新失败,清空队列
|
||||||
processQueue(null);
|
processQueue(null);
|
||||||
// 清除登录状态
|
// 清除登录状态
|
||||||
uni.removeStorageSync("accessToken");
|
uni.removeStorageSync("accessToken");
|
||||||
uni.removeStorageSync("refreshToken");
|
uni.removeStorageSync("refreshToken");
|
||||||
uni.removeStorageSync("jwtUserInfo");
|
uni.removeStorageSync("jwtUserInfo");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Token 刷新异常:", error);
|
console.error("Token 刷新异常:", error);
|
||||||
processQueue(null);
|
processQueue(null);
|
||||||
uni.removeStorageSync("accessToken");
|
uni.removeStorageSync("accessToken");
|
||||||
uni.removeStorageSync("refreshToken");
|
uni.removeStorageSync("refreshToken");
|
||||||
uni.removeStorageSync("jwtUserInfo");
|
uni.removeStorageSync("jwtUserInfo");
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
isRefreshing = false;
|
isRefreshing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = async (options = {}, showLoading = true) => {
|
const request = async (options = {}, showLoading = true) => {
|
||||||
// 合并用户传入的配置和默认配置
|
// 合并用户传入的配置和默认配置
|
||||||
if (!options.data) options.data = {};
|
if (!options.data) options.data = {};
|
||||||
if(!options.data.corpId) {
|
if (!options.data.corpId) {
|
||||||
options.data.corpId = env.MP_CORP_ID;
|
options.data.corpId = env.MP_CORP_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
...options,
|
...options,
|
||||||
url: baseUrl + options.url,
|
url: baseUrl + options.url,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加 token 到请求头
|
// 添加 token 到请求头
|
||||||
// const accessToken = uni.getStorageSync("accessToken");
|
// const accessToken = uni.getStorageSync("accessToken");
|
||||||
// if (accessToken) {
|
// if (accessToken) {
|
||||||
// if (!config.header) config.header = {};
|
// if (!config.header) config.header = {};
|
||||||
// config.header.Authorization = `Bearer ${accessToken}`;
|
// config.header.Authorization = `Bearer ${accessToken}`;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const key = `${JSON.stringify(config)}_${Date.now()}`;
|
const key = `${JSON.stringify(config)}_${Date.now()}`;
|
||||||
if (showLoading) {
|
if (showLoading) {
|
||||||
recordTask(key)
|
recordTask(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 发起请求
|
// 发起请求
|
||||||
const res = await uni.request(config);
|
const res = await uni.request(config);
|
||||||
if (showLoading) {
|
if (showLoading) {
|
||||||
removeTask(key)
|
removeTask(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果返回 401,尝试刷新 token
|
// 如果返回 401,尝试刷新 token
|
||||||
// if (res.statusCode === 401) {
|
// if (res.statusCode === 401) {
|
||||||
// if (showLoading) {
|
// if (showLoading) {
|
||||||
// removeTask(key)
|
// removeTask(key)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // 尝试刷新 token
|
// // 尝试刷新 token
|
||||||
// const newToken = await refreshAccessToken();
|
// const newToken = await refreshAccessToken();
|
||||||
|
|
||||||
// if (newToken) {
|
// if (newToken) {
|
||||||
// // 刷新成功,重试原请求
|
// // 刷新成功,重试原请求
|
||||||
// if (!config.header) config.header = {};
|
// if (!config.header) config.header = {};
|
||||||
// config.header.Authorization = `Bearer ${newToken}`;
|
// config.header.Authorization = `Bearer ${newToken}`;
|
||||||
|
|
||||||
// if (showLoading) {
|
// if (showLoading) {
|
||||||
// recordTask(key)
|
// recordTask(key)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// const retryRes = await uni.request(config);
|
// const retryRes = await uni.request(config);
|
||||||
|
|
||||||
// if (showLoading) {
|
// if (showLoading) {
|
||||||
// removeTask(key)
|
// removeTask(key)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// const success = retryRes && retryRes.data && retryRes.data.success === true;
|
// const success = retryRes && retryRes.data && retryRes.data.success === true;
|
||||||
// if (success) {
|
// if (success) {
|
||||||
// return retryRes.data;
|
// return retryRes.data;
|
||||||
@ -166,7 +166,7 @@ const request = async (options = {}, showLoading = true) => {
|
|||||||
// };
|
// };
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const success = res && res.data && res.data.success === true;
|
const success = res && res.data && res.data.success === true;
|
||||||
if (success) {
|
if (success) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -206,5 +206,28 @@ export default request;
|
|||||||
export const uploadUrl = `${baseUrl}/upload`;
|
export const uploadUrl = `${baseUrl}/upload`;
|
||||||
|
|
||||||
export function getFullPath(path) {
|
export function getFullPath(path) {
|
||||||
return `${baseUrl}${path}`;
|
return `${baseUrl}/${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function upload(path) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
uni.uploadFile({
|
||||||
|
url: uploadUrl, // 替换为你的上传接口地址
|
||||||
|
filePath: path,
|
||||||
|
name: 'file',
|
||||||
|
fileType: 'image',
|
||||||
|
success: (res) => {
|
||||||
|
try {
|
||||||
|
const url = JSON.parse(res.data).filePath;
|
||||||
|
resolve(url ? getFullPath(url) : '')
|
||||||
|
} catch (e) {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: res => {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// 引入腾讯IM SDK
|
// 引入腾讯IM SDK
|
||||||
import TIM from 'tim-wx-sdk'
|
import TIM from 'tim-wx-sdk'
|
||||||
import TIMUploadPlugin from 'tim-upload-plugin'
|
import TIMUploadPlugin from 'tim-upload-plugin'
|
||||||
import { getUserSig, sendSystemMessage, getChatRecordsByGroupId } from '../api/corp/im.js'
|
// import { getUserSig, sendSystemMessage, getChatRecordsByGroupId } from '../api/corp/im.js'
|
||||||
|
|
||||||
const env = __VITE_ENV__;
|
const env = __VITE_ENV__;
|
||||||
|
|
||||||
|
|||||||