提交
This commit is contained in:
parent
a8fe202cf0
commit
c9df1e6341
@ -1,3 +1,4 @@
|
|||||||
MP_API_BASE_URL=http://localhost:8080
|
MP_API_BASE_URL=http://localhost:8080
|
||||||
MP_CACHE_PREFIX=development
|
MP_CACHE_PREFIX=development
|
||||||
MP_WX_APP_ID=wx93af55767423938e
|
MP_WX_APP_ID=wx93af55767423938e
|
||||||
|
MP_CORP_ID=wwe3fb2faa52cf9dfb
|
||||||
|
|||||||
13
api/corp/dept.js
Normal file
13
api/corp/dept.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import api from "../../utils/http.js";
|
||||||
|
|
||||||
|
const BASE_PATH = "/corp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取科室列表(按 corpId)
|
||||||
|
* @param {Object} params
|
||||||
|
* @param {string} params.corpId
|
||||||
|
*/
|
||||||
|
export function getDeptList(params = {}) {
|
||||||
|
return api.post(`${BASE_PATH}`, { type: "getDeptList", ...params });
|
||||||
|
}
|
||||||
|
|
||||||
18
pages.json
18
pages.json
@ -17,6 +17,24 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "工作台"
|
"navigationBarTitleText": "工作台"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/work/profile",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "完善个人信息"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/work/department-select",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "选择科室"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/login/login",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "登录"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
|
|||||||
@ -82,7 +82,7 @@ function remind() {
|
|||||||
|
|
||||||
function toHome() {
|
function toHome() {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: "/pages/home/home",
|
url: "/pages/message/message",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,12 @@ onLoad((opts) => {
|
|||||||
console.log("redirectUrl", redirectUrl.value);
|
console.log("redirectUrl", redirectUrl.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
redirectUrl.value = opts.redirectUrl || "";
|
// 支持 redirect 参数(来自 useGuard)或 redirectUrl 参数
|
||||||
|
if (opts.redirect) {
|
||||||
|
redirectUrl.value = decodeURIComponent(opts.redirect);
|
||||||
|
} else {
|
||||||
|
redirectUrl.value = opts.redirectUrl || "";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
340
pages/work/department-select.vue
Normal file
340
pages/work/department-select.vue
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
<template>
|
||||||
|
<view class="dept-page">
|
||||||
|
<view class="dept-container bg-white">
|
||||||
|
<scroll-view class="sidebar" scroll-y>
|
||||||
|
<view
|
||||||
|
v-for="item in level1List"
|
||||||
|
:key="item._id"
|
||||||
|
:class="[
|
||||||
|
'sidebar-item',
|
||||||
|
item._id === selectedParentId ? 'active' : '',
|
||||||
|
]"
|
||||||
|
@click="selectParent(item)"
|
||||||
|
>
|
||||||
|
<text class="sidebar-text">{{ item.hlwDeptName }}</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<scroll-view class="content" scroll-y>
|
||||||
|
<view v-if="contentList.length" class="content-list">
|
||||||
|
<view
|
||||||
|
v-for="child in contentList"
|
||||||
|
:key="child._id"
|
||||||
|
:class="['dept-item', isSelected(child) ? 'selected' : '']"
|
||||||
|
>
|
||||||
|
<view class="dept-name-row" @click="selectDept(child)">
|
||||||
|
<view class="dept-name">{{ child.deptName }}</view>
|
||||||
|
<text v-if="isSelected(child)" class="check-tag">已选</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="child.children && child.children.length"
|
||||||
|
class="dept-sub-list"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
v-for="sub in child.children"
|
||||||
|
:key="sub._id"
|
||||||
|
:class="['dept-sub-item', isSelected(sub) ? 'selected' : '']"
|
||||||
|
@click.stop="selectDept(sub)"
|
||||||
|
>
|
||||||
|
<text class="dept-sub-text">{{ sub.deptName }}</text>
|
||||||
|
<text v-if="isSelected(sub)" class="check-dot" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-else class="empty-wrapper">
|
||||||
|
<empty-data text="暂无科室" />
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<view class="footer-tip">
|
||||||
|
如没有符合的内容,请联系客服
|
||||||
|
<text class="link" @click="contactService">点击添加客服</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
|
import useGuard from "@/hooks/useGuard.js";
|
||||||
|
import EmptyData from "@/components/empty-data.vue";
|
||||||
|
import api from "@/utils/api";
|
||||||
|
import { toast } from "@/utils/widget";
|
||||||
|
|
||||||
|
const { useLoad } = useGuard();
|
||||||
|
|
||||||
|
const deptList = ref([]);
|
||||||
|
const selectedParentId = ref("");
|
||||||
|
const selectedDeptId = ref("");
|
||||||
|
|
||||||
|
const sorter = (a, b) => {
|
||||||
|
const sortA = typeof a.sort === "number" ? a.sort : 0;
|
||||||
|
const sortB = typeof b.sort === "number" ? b.sort : 0;
|
||||||
|
if (sortA !== sortB) return sortA - sortB;
|
||||||
|
const timeA = a.createTime || 0;
|
||||||
|
const timeB = b.createTime || 0;
|
||||||
|
return timeA - timeB;
|
||||||
|
};
|
||||||
|
|
||||||
|
const level1List = computed(() =>
|
||||||
|
deptList.value.filter((i) => i.level === 1).sort(sorter)
|
||||||
|
);
|
||||||
|
|
||||||
|
const contentList = computed(() => {
|
||||||
|
const children = deptList.value
|
||||||
|
.filter(
|
||||||
|
(i) =>
|
||||||
|
i.level === 2 && i.parentId && i.parentId === selectedParentId.value
|
||||||
|
)
|
||||||
|
.sort(sorter);
|
||||||
|
if (children.length === 0) {
|
||||||
|
// 如果没有二级科室,允许一级科室直接选择
|
||||||
|
const currentParent = deptList.value.find(
|
||||||
|
(i) => i._id === selectedParentId.value
|
||||||
|
);
|
||||||
|
return currentParent ? [{ ...currentParent, children: [] }] : [];
|
||||||
|
}
|
||||||
|
const level3List = deptList.value.filter((i) => i.level === 3);
|
||||||
|
return children.map((item) => ({
|
||||||
|
...item,
|
||||||
|
children: level3List.filter((c) => c.parentId === item._id).sort(sorter),
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
function isSelected(item) {
|
||||||
|
const targetId = selectedDeptId.value;
|
||||||
|
return !!targetId && (item.deptId === targetId || item._id === targetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchDeptList() {
|
||||||
|
uni.showLoading({ title: "加载中..." });
|
||||||
|
try {
|
||||||
|
const res = await api("getDeptList");
|
||||||
|
if (res && res.success && Array.isArray(res.data.list)) {
|
||||||
|
deptList.value = res.data.list;
|
||||||
|
hydrateSelectedParent();
|
||||||
|
} else {
|
||||||
|
toast(res?.message || "获取科室失败");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取科室失败", error);
|
||||||
|
toast("获取科室失败");
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hydrateSelectedParent() {
|
||||||
|
// 优先根据已选科室找到对应父级
|
||||||
|
if (selectedDeptId.value) {
|
||||||
|
const match =
|
||||||
|
deptList.value.find(
|
||||||
|
(i) =>
|
||||||
|
i._id === selectedDeptId.value || i.deptId === selectedDeptId.value
|
||||||
|
) || null;
|
||||||
|
if (match?.parentId) {
|
||||||
|
selectedParentId.value = match.parentId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再次兜底使用入参的 parentId
|
||||||
|
if (selectedParentId.value) return;
|
||||||
|
|
||||||
|
// 最后兜底选第一个一级科室
|
||||||
|
const first = level1List.value[0];
|
||||||
|
if (first) {
|
||||||
|
selectedParentId.value = first._id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectParent(item) {
|
||||||
|
selectedParentId.value = item._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitSelection(item) {
|
||||||
|
const eventChannel =
|
||||||
|
typeof getOpenerEventChannel === "function"
|
||||||
|
? getOpenerEventChannel()
|
||||||
|
: null;
|
||||||
|
eventChannel?.emit("deptSelected", {
|
||||||
|
id: item._id,
|
||||||
|
deptId: item.deptId || item._id,
|
||||||
|
name: item.deptName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectDept(item) {
|
||||||
|
selectedDeptId.value = item.deptId || item._id;
|
||||||
|
emitSelection(item);
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
function contactService() {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请联系客服添加科室",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
useLoad(() => {
|
||||||
|
fetchDeptList();
|
||||||
|
});
|
||||||
|
|
||||||
|
onLoad((opts) => {
|
||||||
|
// 支持从外部传入默认选中的一级科室
|
||||||
|
if (opts.parentId) {
|
||||||
|
selectedParentId.value = opts.parentId;
|
||||||
|
}
|
||||||
|
const passedDeptId = opts.deptId || opts.departmentId || opts.id;
|
||||||
|
if (passedDeptId) {
|
||||||
|
selectedDeptId.value = passedDeptId;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.dept-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dept-container {
|
||||||
|
display: flex;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
background: linear-gradient(180deg, #fdfdfd 0%, #f6f8fb 100%);
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
|
||||||
|
height: 88vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 210rpx;
|
||||||
|
background: #f8f9fb;
|
||||||
|
border-right: 1px solid #eef0f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item {
|
||||||
|
padding: 30rpx 18rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 1px solid #eef0f5;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #fff;
|
||||||
|
color: #2a6ff2;
|
||||||
|
font-weight: 600;
|
||||||
|
box-shadow: inset 4rpx 0 0 #2a6ff2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-text {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
background: #fff;
|
||||||
|
border-top-right-radius: 12rpx;
|
||||||
|
border-bottom-right-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list {
|
||||||
|
padding: 12rpx 20rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dept-item {
|
||||||
|
padding: 26rpx 22rpx 14rpx;
|
||||||
|
border-bottom: 1px solid #f2f4f7;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
margin-bottom: 14rpx;
|
||||||
|
background: #fff;
|
||||||
|
transition: box-shadow 0.2s ease, transform 0.15s ease;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
box-shadow: 0 8rpx 24rpx rgba(42, 111, 242, 0.08);
|
||||||
|
border: 1px solid #e1e9ff;
|
||||||
|
transform: translateY(-2rpx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dept-name-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dept-name {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dept-sub-list {
|
||||||
|
margin-top: 12rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dept-sub-item {
|
||||||
|
padding: 12rpx 16rpx;
|
||||||
|
background: #f6f8fb;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #3a3a3a;
|
||||||
|
border: 1px solid #e5e9f2;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border-color: #2a6ff2;
|
||||||
|
background: #eaf1ff;
|
||||||
|
color: #1f5ed6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dept-sub-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-tag {
|
||||||
|
padding: 6rpx 14rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #2a6ff2;
|
||||||
|
background: #eaf1ff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-dot {
|
||||||
|
width: 12rpx;
|
||||||
|
height: 12rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #2a6ff2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-wrapper {
|
||||||
|
padding-top: 120rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-tip {
|
||||||
|
padding: 24rpx 20rpx 40rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: #2a6ff2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
379
pages/work/profile.vue
Normal file
379
pages/work/profile.vue
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
<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>
|
||||||
|
|
||||||
@ -1,9 +1,213 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>work</div>
|
<view class="work-page">
|
||||||
|
<!-- 顶部用户信息区域 -->
|
||||||
|
<view class="user-header bg-white px-15 py-15">
|
||||||
|
<view class="flex items-center justify-between">
|
||||||
|
<!-- 左侧:用户头像和信息 -->
|
||||||
|
<view class="flex items-center flex-grow">
|
||||||
|
<view class="user-avatar mr-10">
|
||||||
|
<image
|
||||||
|
class="avatar-img"
|
||||||
|
src="/static/default-avatar.png"
|
||||||
|
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 class="status-tag tag-gray" @click="handleVerify">
|
||||||
|
<text class="tag-text text-dark">未认证</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 右侧:操作按钮 -->
|
||||||
|
<view class="flex items-center">
|
||||||
|
<view
|
||||||
|
class="action-btn flex-col items-center mr-15"
|
||||||
|
@click="handleInvitePatient"
|
||||||
|
>
|
||||||
|
<view class="qrcode-icon">
|
||||||
|
<text class="qrcode-text">▦</text>
|
||||||
|
</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 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 class="empty-state">
|
||||||
|
<empty-data text="暂无记录" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
|
import useGuard from "@/hooks/useGuard.js";
|
||||||
|
import EmptyData from "@/components/empty-data.vue";
|
||||||
|
|
||||||
|
const { useLoad } = useGuard();
|
||||||
|
|
||||||
|
// 完善信息
|
||||||
|
const handleCompleteInfo = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/work/profile",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 认证
|
||||||
|
const handleVerify = () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "跳转到认证页面",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 邀请患者
|
||||||
|
const handleInvitePatient = () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "邀请患者",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更多操作
|
||||||
|
const handleMore = () => {
|
||||||
|
uni.showActionSheet({
|
||||||
|
itemList: ["设置", "关于"],
|
||||||
|
success: (res) => {
|
||||||
|
console.log("选择了第" + (res.tapIndex + 1) + "个按钮");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useLoad(() => {
|
||||||
|
console.log("工作台页面加载");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style lang="scss" scoped>
|
||||||
|
.work-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-header {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-avatar {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #e5e5e5;
|
||||||
|
|
||||||
|
.avatar-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
padding: 6rpx 16rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&.tag-orange {
|
||||||
|
background: #ff6b35;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tag-gray {
|
||||||
|
background: #f5f5f5;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-text {
|
||||||
|
font-size: 22rpx;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.qrcode-icon {
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.qrcode-text {
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-text {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.more-icon {
|
||||||
|
font-size: 48rpx;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-section {
|
||||||
|
.section-title {
|
||||||
|
padding-top: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .empty-state {
|
||||||
|
// min-height: 600rpx;
|
||||||
|
// padding: 100rpx 0;
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
// align-items: center;
|
||||||
|
// justify-content: center;
|
||||||
|
// width: 100%;
|
||||||
|
// }
|
||||||
</style>
|
</style>
|
||||||
@ -1,8 +1,20 @@
|
|||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
path: 'pages/home/home',
|
path: 'pages/message/message',
|
||||||
meta: { title: '首页', login: true },
|
meta: { title: '首页', login: true },
|
||||||
style: { navigationStyle: 'custom' }
|
style: { navigationStyle: 'custom' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'pages/work/work',
|
||||||
|
meta: { title: '工作台', login: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'pages/work/profile',
|
||||||
|
meta: { title: '完善个人信息', login: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'pages/work/department-select',
|
||||||
|
meta: { title: '选择科室', login: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,8 @@ export default defineStore("accountStore", () => {
|
|||||||
// IM 相关
|
// IM 相关
|
||||||
const openid = ref("");
|
const openid = ref("");
|
||||||
const isIMInitialized = ref(false);
|
const isIMInitialized = ref(false);
|
||||||
|
// 手机号(从授权登录获取)
|
||||||
|
const mobile = ref(uni.getStorageSync('user_mobile') || '');
|
||||||
|
|
||||||
async function login(phoneCode = '') {
|
async function login(phoneCode = '') {
|
||||||
if (loading.value) return;
|
if (loading.value) return;
|
||||||
@ -34,10 +36,14 @@ export default defineStore("accountStore", () => {
|
|||||||
console.log(res)
|
console.log(res)
|
||||||
if (res.success && res.data && res.data.mobile) {
|
if (res.success && res.data && res.data.mobile) {
|
||||||
account.value = res.data;
|
account.value = res.data;
|
||||||
// 兼容不同字段名
|
|
||||||
openid.value = res.data.openid || res.data.openId || res.data.userId || "";
|
openid.value = res.data.openid || res.data.openId || res.data.userId || "";
|
||||||
isIMInitialized.value = false;
|
isIMInitialized.value = false;
|
||||||
clearInitIMPromise();
|
clearInitIMPromise();
|
||||||
|
// 存储手机号
|
||||||
|
if (res.data.mobile) {
|
||||||
|
mobile.value = res.data.mobile;
|
||||||
|
uni.setStorageSync('user_mobile', res.data.mobile);
|
||||||
|
}
|
||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,5 +74,5 @@ export default defineStore("accountStore", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { account, openid, isIMInitialized, login, initIMAfterLogin }
|
return { account, openid, isIMInitialized, mobile, login, initIMAfterLogin }
|
||||||
})
|
})
|
||||||
@ -7,6 +7,7 @@ const urlsConfig = {
|
|||||||
getTeamData: 'getTeamData',
|
getTeamData: 'getTeamData',
|
||||||
queryWxJoinedTeams: 'queryWxJoinedTeams',
|
queryWxJoinedTeams: 'queryWxJoinedTeams',
|
||||||
wxAppLogin: 'wxAppLogin',
|
wxAppLogin: 'wxAppLogin',
|
||||||
|
getDeptList:'getHlwDeptList',
|
||||||
},
|
},
|
||||||
|
|
||||||
knowledgeBase: {
|
knowledgeBase: {
|
||||||
|
|||||||
@ -97,6 +97,10 @@ async function refreshAccessToken() {
|
|||||||
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) {
|
||||||
|
options.data.corpId = env.MP_CORP_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user