解决冲突 api/api.js

This commit is contained in:
haomingming
2025-09-08 09:15:01 +08:00
18 changed files with 4382 additions and 294 deletions
+1 -1
View File
@@ -67,7 +67,7 @@
<view v-else-if="loadMoreStatus === 'more'" class="more">
<text>上拉加载更多</text>
</view>
<view v-else-if="loadMoreStatus === 'noMore'" class="no-more">
<view v-else-if="loadMoreStatus === 'noMore' && guidelinesList.length > 0" class="no-more">
<text>没有更多数据了</text>
</view>
</view>
+422
View File
@@ -0,0 +1,422 @@
<template>
<view class="my-application-page">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
title="我的应用"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
>
<template #right>
<text class="edit-btn" @click="toggleEdit">{{
isEditMode ? "完成" : "编辑"
}}</text>
</template>
</uni-nav-bar>
<scroll-view class="content" scroll-y>
<!-- 我的应用部分 -->
<view class="section">
<view class="section-title">我的应用</view>
<view class="app-grid">
<view
class="app-item"
v-for="(app, index) in myApps"
:key="app.id"
@click="openApp(app)"
>
<view
class="iconbox"
v-if="isEditMode"
@click.stop="removeFromMyApps(index)"
>
<up-icon
name="minus-circle"
color="#fe0001"
size="40rpx"
></up-icon>
</view>
<view class="app-icon">
<image :src="app.icon" mode="aspectFit" class="icon-image" />
</view>
<text class="app-name">{{ app.name }}</text>
</view>
</view>
</view>
<!-- 常用功能部分 -->
<view class="section">
<view class="section-title">常用功能</view>
<view class="app-grid">
<view
class="app-item"
v-for="(app, index) in commonApps"
:key="app.id"
@click="openApp(app)"
>
<view
class="iconbox"
@click.stop="addToMyApps(app)"
v-if="isEditMode"
>
<up-icon
name="plus-circle"
color="#067fe6"
size="40rpx"
></up-icon>
</view>
<view class="app-icon">
<image :src="app.icon" mode="aspectFit" class="icon-image" />
</view>
<text class="app-name">{{ app.name }}</text>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onShow } from "@dcloudio/uni-app";
import api from "@/api/api";
import docUrl from '@/utils/docUrl';
// 编辑模式状态
const isEditMode = ref(false);
// 我的应用列表
const myApps = ref([]);
// 常用功能列表
const commonApps = ref([]);
const blackList=['临床研究','精品课程','名医名科','肝病学院','病例分享','科研项目','肝病检测','我的下载','病例讨论','临床研究']
// 页面路由映射
// 获取用户图标数据
const addUserIcon = () => {
api.addUserIcon({
idStr:myApps.value.map(item => item.id).join(',')
}).then(res => {
console.log('addUserIcon API响应:', res);
if(res.code === '200'){
uni.showToast({
title: '保存成功',
icon: 'none',
duration: 1500
});
}
});
};
const getUserIcon = () => {
api.getUserIcon({}).then(res => {
console.log('getUserIcon API响应:', res);
if (res.code === '200' && res.data && Array.isArray(res.data)) {
// 处理API数据(先过滤黑名单)
const sourceList = res.data.filter(item => !blackList.includes(item.name));
const allApps = sourceList.map(item => ({
id: item.id,
name: item.name,
icon: docUrl + item.img, // 使用docUrl拼接图片路径
bgColor: bgColorMap[item.id] || '#999999', // 使用预设颜色
url: urlMap[item.id] || '', // 使用预设路由
selected: item.selected
}));
// 根据selected字段分离我的应用和常用功能
myApps.value = allApps.filter(app =>
app.selected !== 'false' && app.selected !== false
);
commonApps.value = allApps.filter(app =>
app.selected === 'false' || app.selected === false
);
console.log('我的应用:', myApps.value);
console.log('常用功能:', commonApps.value);
} else {
console.error('获取应用图标失败:', res.message || '未知错误');
uni.showToast({
title: res.message || '获取应用列表失败',
icon: 'error',
duration: 2000
});
}
}).catch(error => {
console.error('获取应用图标异常:', error);
uni.showToast({
title: '网络请求失败',
icon: 'error',
duration: 2000
});
});
};
// 返回上一页
const goBack = () => {
uni.navigateBack();
};
// 切换编辑模式
const toggleEdit = () => {
isEditMode.value = !isEditMode.value;
if(!isEditMode.value){
addUserIcon();
}
};
// 打开应用
const openApp = (app) => {
if (isEditMode.value) return;
let url='';
if(app.name=="肝胆课件"){
url='/pages_app/ppt/ppt'
navTo({
url:url
})
}else if(app.name=="精品课"){
url='/pages_course/course/course'
navTo({
url:url
})
}else if(app.name=="积分商城"){
url='/pages_goods/pointMall/pointMall'
navTo({
url:url
})
}else if(app.name=="肝病新闻"){
url='/pages_app/news/news'
navTo({
url:url
})
}else if(app.name=="我的福利"){
url='/pages_app/myWelfare/myWelfare'
navTo({
url:url
})
}else if(app.name=="专题e站"){
url='https://wx.igandan.com/Esite/index.htm#/home?fromtype=doctor'
// H5 端
// #ifdef H5
window.open(url, '_blank');
// #endif
// App 端
// #ifdef APP-PLUS
plus.runtime.openURL(url);
// #endif
// 小程序端:使用内嵌 webview 页面打开
// #ifdef MP
const encoded = encodeURIComponent(url)
uni.navigateTo({
url: `/pages_app/webview/webview?url=${encoded}`
})
// #endif
}
};
// 添加到我的应用
const addToMyApps = (app) => {
// 检查是否已存在
const exists = myApps.value.some(item => item.id === app.id);
if (exists) {
uni.showToast({
title: '已在我的应用中',
icon: 'none',
duration: 1500
});
return;
}
// 检查是否超过最大数量
if (myApps.value.length >= 3) {
uni.showToast({
title: '最多添加3个应用',
icon: 'none',
duration: 1500
});
return;
}
// 更新应用状态为已选中
app.selected = '1';
// 从常用功能中移除
const commonIndex = commonApps.value.findIndex(item => item.id === app.id);
if (commonIndex > -1) {
commonApps.value.splice(commonIndex, 1);
}
// 添加到我的应用
myApps.value.push(app);
};
// 从我的应用中移除
const removeFromMyApps = (index) => {
const app = myApps.value[index];
// 更新应用状态为未选中
app.selected = 'false';
// 从我的应用中移除
myApps.value.splice(index, 1);
// 添加到常用功能
commonApps.value.push(app);
};
onShow(() => {
// 页面显示时的逻辑
getUserIcon();
});
</script>
<style lang="scss" scoped>
.my-application-page {
background-color: #ffffff;
min-height: 100vh;
}
.content {
position: fixed;
top: calc(var(--status-bar-height) + 64px);
bottom: 0;
left: 0;
width: 100%;
right: 0;
box-sizing: border-box;
background-color: #fff;
}
.edit-btn {
color: #8b2316;
font-size: 28rpx;
font-weight: 500;
}
.section {
margin-bottom: 40rpx;
}
.section-title {
color: #666666;
font-size: 28rpx;
margin-bottom: 20rpx;
padding: 0 30rpx;
}
.app-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
border: 1rpx solid #e0e0e0;
border-left: none;
border-right: none;
}
.app-item {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx 10rpx;
border-right: 1rpx solid #e0e0e0;
border-bottom: 1rpx solid #e0e0e0;
transition: all 0.3s ease;
.iconbox {
position: absolute;
top: 8rpx;
right: 8rpx;
}
&:active {
transform: scale(0.95);
}
// 右边框处理
&:nth-child(3n) {
border-right: none;
}
// 下边框处理(最后一行)
&:nth-last-child(-n + 3) {
border-bottom: none;
}
}
.app-icon {
width: 100rpx;
height: 100rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
}
.icon-image {
width: 60rpx;
height: 60rpx;
}
.app-name {
font-size: 24rpx;
color: #000;
text-align: center;
line-height: 1.2;
font-weight: 500;
}
.delete-btn {
position: absolute;
top: -8rpx;
right: -8rpx;
width: 32rpx;
height: 32rpx;
background-color: #ff4757;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(255, 71, 87, 0.3);
}
.add-btn {
position: absolute;
top: -8rpx;
right: -8rpx;
width: 32rpx;
height: 32rpx;
background-color: #ffffff;
border: 2rpx solid #8b2316;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(139, 35, 22, 0.2);
}
// 编辑模式下的样式调整
.app-item:has(.delete-btn) {
border-right-color: #ff4757;
border-bottom-color: #ff4757;
}
.app-item:has(.add-btn) {
border-right-color: #8b2316;
border-bottom-color: #8b2316;
}
</style>
+532 -31
View File
@@ -20,7 +20,7 @@
<view class="row" @click="onChooseAvatar">
<view class="label"><text>头像</text><text class="req">*</text></view>
<view class="value value-avatar">
<image :src="form.avatar" mode="aspectFill" class="avatar" />
<image :src="docUrl+form.photo" mode="aspectFill" class="avatar" />
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -28,14 +28,14 @@
<!-- 姓名 -->
<view class="row">
<view class="label"><text>姓名</text><text class="req">*</text></view>
<view class="value">{{ form.name }}</view>
<view class="value">{{ form.realName }}</view>
</view>
<!-- 性别 -->
<view class="row" @click="onPickGender">
<view class="label"><text>性别</text><text class="req">*</text></view>
<view class="value with-arrow">
<text>{{ form.gender }}</text>
<text>{{ getGenderText(form.sex) }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -44,7 +44,7 @@
<view class="row" @click="onPickBirthday">
<view class="label"><text>出生日期</text></view>
<view class="value with-arrow">
<text>{{ form.birthday || '' }}</text>
<text>{{ form.birthDate || '' }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -70,11 +70,12 @@
<!-- 专业资料分组 -->
<view class="section-header">专业资料</view>
<!-- 医院 -->
<view class="row" @click="onPickHospital">
<!-- 医院地址 -->
<view class="row" @click="openAreaPicker">
<view class="label"><text>医院</text><text class="req">*</text></view>
<view class="value with-arrow">
<text>{{ form.hospital }}</text>
<text v-if="!regionText" class="placeholder">请选择医院</text>
<text v-else>{{ regionText }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -83,7 +84,7 @@
<view class="row" @click="onPickDept">
<view class="label"><text>科室</text><text class="req">*</text></view>
<view class="value with-arrow">
<text>{{ form.department }}</text>
<text>{{ form.officeName }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -92,7 +93,7 @@
<view class="row" @click="onEditDeptPhone">
<view class="label"><text>科室电话</text><text class="req">*</text></view>
<view class="value with-arrow">
<text>{{ form.departmentPhone }}</text>
<text>{{ form.officePhone }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -101,7 +102,7 @@
<view class="row" @click="onPickTitle">
<view class="label"><text>职称</text></view>
<view class="value with-arrow">
<text>{{ form.title }}</text>
<text>{{ form.positionName }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -110,7 +111,7 @@
<view class="row" @click="onEditLicenseNo">
<view class="label"><text>执业医师证编号</text><text class="req">*</text></view>
<view class="value with-arrow">
<text>{{ form.licenseNo }}</text>
<text>{{ form.certificate }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -119,7 +120,7 @@
<view class="row" @click="onChooseLicenseImg">
<view class="label"><text>执业医师证图片或胸牌</text><text class="req">*</text></view>
<view class="value value-license">
<image :src="form.licenseImg" mode="aspectFill" class="license-thumb" />
<image :src="docUrl+form.certificateImg" mode="aspectFill" class="license-thumb" />
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -128,7 +129,7 @@
<view class="row" @click="onEditSpecialty">
<view class="label"><text>专长</text></view>
<view class="value with-arrow">
<text>{{ form.specialty }}</text>
<text>{{ getSpecialtyText() }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
@@ -137,35 +138,250 @@
<view class="row" @click="onEditIntro">
<view class="label"><text>个人简介</text></view>
<view class="value with-arrow">
<text>{{ form.intro || '暂无简介' }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
</scroll-view>
<!-- 省市区选择器 -->
<view v-if="showAreaPicker" class="picker-mask" @click="closeAreaPicker"></view>
<view v-if="showAreaPicker" class="picker-panel">
<view class="picker-header">
<text class="picker-btn" @click="closeAreaPicker">取消</text>
<text class="picker-title">选择地区</text>
<text class="picker-btn ok" @click="confirmArea">确定</text>
</view>
<picker-view v-if="provinces.length && cities.length && areas.length" class="picker-view" :indicator-style="indicatorStyle" :value="pickerIndex" @change="onAreaChange">
<picker-view-column>
<view v-for="(p,pi) in provinces" :key="pi" class="picker-item">{{ p.name }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(c,ci) in cities" :key="ci" class="picker-item">{{ c.name }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(a,ai) in areas" :key="ai" class="picker-item">{{ a.name }}</view>
</picker-view-column>
</picker-view>
<view v-else class="picker-empty">地区数据加载中...</view>
</view>
<!-- 日期选择器 -->
<view v-if="showDatePicker" class="picker-mask" @click="closeDatePicker"></view>
<view v-if="showDatePicker" class="picker-panel">
<view class="picker-header">
<text class="picker-btn" @click="closeDatePicker">取消</text>
<text class="picker-title">选择出生日期</text>
<text class="picker-btn ok" @click="confirmDate">确定</text>
</view>
<picker-view class="picker-view" :indicator-style="indicatorStyle" :value="datePickerIndex" @change="onDateChange">
<picker-view-column>
<view v-for="(year, index) in years" :key="index" class="picker-item">{{ year }}年</view>
</picker-view-column>
<picker-view-column>
<view v-for="(month, index) in months" :key="index" class="picker-item">{{ month }}月</view>
</picker-view-column>
<picker-view-column>
<view v-for="(day, index) in days" :key="index" class="picker-item">{{ day }}日</view>
</picker-view-column>
</picker-view>
</view>
<!-- 科室选择器 -->
<view v-if="showDeptPicker" class="picker-mask" @click="closeDeptPicker"></view>
<view v-if="showDeptPicker" class="picker-panel">
<view class="picker-header">
<text class="picker-btn" @click="closeDeptPicker">取消</text>
<text class="picker-title">选择科室</text>
<text class="picker-btn ok" @click="confirmDept">确定</text>
</view>
<picker-view class="picker-view" :indicator-style="indicatorStyle" :value="deptPickerIndex" @change="onDeptChange">
<picker-view-column>
<view v-for="(dept, index) in deptList" :key="index" class="picker-item">{{ dept }}</view>
</picker-view-column>
</picker-view>
</view>
<!-- 职称选择器 -->
<view v-if="showTitlePicker" class="picker-mask" @click="closeTitlePicker"></view>
<view v-if="showTitlePicker" class="picker-panel">
<view class="picker-header">
<text class="picker-btn" @click="closeTitlePicker">取消</text>
<text class="picker-title">选择职称</text>
<text class="picker-btn ok" @click="confirmTitle">确定</text>
</view>
<picker-view class="picker-view" :indicator-style="indicatorStyle" :value="titlePickerIndex" @change="onTitleChange">
<picker-view-column>
<view v-for="(title, index) in titleList" :key="index" class="picker-item">{{ title }}</view>
</picker-view-column>
</picker-view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onShow } from "@dcloudio/uni-app";
import api from '@/api/api';
import areaList from '@/utils/areaList.js';
import docUrl from '@/utils/docUrl';
const form = ref({
avatar: '/static/big_background_my.png',
name: '邱建东',
gender: '男',
birthday: '',
mobile: '17600668628',
// 基本资料字段
photo: '',
realName: '',
sex: 0,
birthDate: '',
mobile: '',
email: '',
hospital: '北京博爱医院',
department: '肝病科',
departmentPhone: '1234567890',
title: '主任中医师',
licenseNo: '12345678',
licenseImg: '/static/big_background_my.png',
specialty: '肝炎、肝硬化'
// 专业资料字段
hospitalName: '',
officeName: '',
officePhone: '',
positionName: '',
certificate: '',
certificateImg: '',
intro: '',
// 地址相关字段
provId: 0,
cityId: 0,
countyId: 0,
// 专长列表
specialityList: []
});
const goBack = () => uni.navigateBack();
// 地址选择相关变量
const regionText = ref('');
const provinces = ref([]);
const cities = ref([]);
const areas = ref([]);
const pickerIndex = ref([0,0,0]);
const showAreaPicker = ref(false);
const indicatorStyle = `height: 80rpx;`;
// 日期选择相关变量
const showDatePicker = ref(false);
const years = ref([]);
const months = ref([]);
const days = ref([]);
const datePickerIndex = ref([0, 0, 0]);
// 科室选择相关变量
const showDeptPicker = ref(false);
const deptList = ref([
'内科', '外科', '妇产科', '儿科', '眼科', '耳鼻喉科', '口腔科', '皮肤科',
'神经科', '精神科', '肿瘤科', '康复科', '急诊科', '麻醉科', '病理科',
'检验科', '影像科', '药剂科', '护理部', '肝病科', '消化科', '心内科',
'呼吸科', '肾内科', '内分泌科', '血液科', '风湿科', '感染科', 'ICU',
'手术室', '门诊部', '住院部', '体检中心', '其他'
]);
const deptPickerIndex = ref([0]);
// 职称选择相关变量
const showTitlePicker = ref(false);
const titleList = ref([
'住院医师', '主治医师', '副主任医师', '主任医师',
'住院中医师', '主治中医师', '副主任中医师', '主任中医师',
'住院药师', '主管药师', '副主任药师', '主任药师',
'住院护师', '主管护师', '副主任护师', '主任护师',
'住院技师', '主管技师', '副主任技师', '主任技师',
'助理医师', '执业医师', '执业助理医师',
'医士', '医师', '主管医师', '副主任医师', '主任医师',
'护士', '护师', '主管护师', '副主任护师', '主任护师',
'技师', '主管技师', '副主任技师', '主任技师',
'其他'
]);
const titlePickerIndex = ref([0]);
const goBack = () => uni.navigateBack();
// 获取性别文本
const getGenderText = (sex) => {
const genderMap = { 0: '女', 1: '男' };
return genderMap[sex] || '';
};
const getDiseaseList = async () => {
const res = await api.getDiseaseList({});
console.log('疾病列表API响应:', res);
if (res.code === 200) {
deptList.value = res.data.diseaseList.map(item => item.diseaseName);
}
};
const getPositionList = async () => {
const res = await api.getPositionList({});
console.log('职称列表API响应:', res);
if (res.code === 200 ) {
titleList.value = res.data.positionList.map(item => item.positionName);
}
};
const getOfficeList = async () => {
const res = await api.getOfficeList({});
console.log('科室列表API响应:', res);
if (res.code === 200 ) {
deptList.value = res.data.officeList.map(item => item.officeName);
}
};
// 获取专长文本
const getSpecialtyText = () => {
if (!form.value.specialityList || form.value.specialityList.length === 0) {
return '暂无专长';
}
return form.value.specialityList.map(item => item.diseaseName).join('、');
};
const getExpertByUuid = async () => {
try {
const res = await api.getExpertByUuid({});
console.log('专家信息API响应:', res);
if (res.code === 200 && res.data && res.data.expert) {
const expert = res.data.expert;
const specialityList = res.data.specialityList || [];
// 直接使用API返回的字段结构
form.value = {
photo: expert.photo || '',
realName: expert.realName || '',
sex: expert.sex || 0,
birthDate: expert.birthDate || '',
mobile: expert.mobile || '',
email: expert.email || '',
hospitalName: expert.hospitalName || '',
officeName: expert.officeName || '',
officePhone: expert.officePhone || '',
positionName: expert.positionName || '',
certificate: expert.certificate || '',
certificateImg: expert.certificateImg || '',
intro: expert.intro || '',
provId: expert.provId || 0,
cityId: expert.cityId || 0,
countyId: expert.countyId || 0,
specialityList: specialityList
};
// 设置地址信息(如果有省市区ID)
if (expert.provId && expert.cityId && expert.countyId) {
// 这里可以根据ID设置地址,暂时先设置医院名称
regionText.value = expert.hospitalName || '';
}
console.log('解析后的表单数据:', form.value);
} else {
console.error('获取专家信息失败:', res.msg || '未知错误');
uni.showToast({
title: res.msg || '获取个人信息失败',
icon: 'error',
duration: 2000
});
}
} catch (error) {
console.error('获取专家信息异常:', error);
uni.showToast({
title: '网络请求失败',
icon: 'error',
duration: 2000
});
}
};
// 通用打开裁剪器
const openCropper = (callback, opts = {}) => {
const { destWidth = 600, rectWidth = 300, fileType = 'jpg' } = opts;
@@ -192,20 +408,242 @@
}, { destWidth: 1000, rectWidth: 500 });
};
// 地址选择相关函数
const normalizeNode = (node) => ({
code: node?.code || '',
name: node?.label || node?.value || node?.name || '',
children: Array.isArray(node?.children) ? node.children : []
});
const getAreaTree = () => {
const raw = areaList && (areaList.default || areaList);
return Array.isArray(raw) ? raw.map(normalizeNode) : [];
};
const buildData = () => {
const tree = getAreaTree();
provinces.value = tree.length ? tree : [{ code: '', name: '', children: [] }];
const pIdx = Math.min(pickerIndex.value[0], Math.max(provinces.value.length - 1, 0));
const pNode = provinces.value[pIdx];
cities.value = (pNode?.children || []).map(normalizeNode);
if (!cities.value.length) cities.value = [{ code: '', name: '', children: [] }];
const cIdx = Math.min(pickerIndex.value[1], Math.max(cities.value.length - 1, 0));
const cNode = cities.value[cIdx];
areas.value = (cNode?.children || []).map(normalizeNode);
if (!areas.value.length) areas.value = [{ code: '', name: '' }];
};
const openAreaPicker = () => {
showAreaPicker.value = true;
pickerIndex.value = [0,0,0];
buildData();
};
const closeAreaPicker = () => {
showAreaPicker.value = false;
};
const onAreaChange = (e) => {
const val = (e && e.detail && e.detail.value) ? e.detail.value : [0,0,0];
const [pi, ci, ai] = val;
if (pi !== pickerIndex.value[0]) {
pickerIndex.value = [pi, 0, 0];
buildData();
return;
}
if (ci !== pickerIndex.value[1]) {
pickerIndex.value = [pi, ci, 0];
buildData();
return;
}
pickerIndex.value = [pi, ci, ai];
};
const confirmArea = () => {
const p = provinces.value[pickerIndex.value[0]];
const c = cities.value[pickerIndex.value[1]];
const a = areas.value[pickerIndex.value[2]];
regionText.value = [p?.name, c?.name, a?.name].filter(Boolean).join(' ');
// 更新表单中的医院地址
form.value.hospitalName = regionText.value;
closeAreaPicker();
};
// 日期选择相关函数
const initDatePicker = () => {
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
const currentMonth = currentDate.getMonth() + 1;
const currentDay = currentDate.getDate();
// 生成年份列表(从1900年到今年)
years.value = [];
for (let year = currentYear; year >= 1900; year--) {
years.value.push(year);
}
// 生成月份列表
months.value = [];
for (let month = 1; month <= 12; month++) {
months.value.push(month);
}
// 生成日期列表
updateDays(currentYear, currentMonth);
// 设置默认选中当前日期
datePickerIndex.value = [0, currentMonth - 1, currentDay - 1];
};
const updateDays = (year, month) => {
const daysInMonth = new Date(year, month, 0).getDate();
days.value = [];
for (let day = 1; day <= daysInMonth; day++) {
days.value.push(day);
}
};
const openDatePicker = () => {
showDatePicker.value = true;
initDatePicker();
};
const closeDatePicker = () => {
showDatePicker.value = false;
};
const onDateChange = (e) => {
const val = e.detail.value;
const [yearIndex, monthIndex, dayIndex] = val;
const selectedYear = years.value[yearIndex];
const selectedMonth = months.value[monthIndex];
// 更新日期列表
updateDays(selectedYear, selectedMonth);
// 检查选择的日期是否晚于今天
const selectedDate = new Date(selectedYear, selectedMonth - 1, days.value[dayIndex] || 1);
const today = new Date();
today.setHours(0, 0, 0, 0);
if (selectedDate > today) {
// 如果选择的日期晚于今天,重置为今天
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
const currentMonth = currentDate.getMonth() + 1;
const currentDay = currentDate.getDate();
const yearIdx = years.value.findIndex(y => y === currentYear);
const monthIdx = months.value.findIndex(m => m === currentMonth);
const dayIdx = days.value.findIndex(d => d === currentDay);
if (yearIdx !== -1 && monthIdx !== -1 && dayIdx !== -1) {
datePickerIndex.value = [yearIdx, monthIdx, dayIdx];
}
} else {
datePickerIndex.value = val;
}
};
const confirmDate = () => {
const [yearIndex, monthIndex, dayIndex] = datePickerIndex.value;
const selectedYear = years.value[yearIndex];
const selectedMonth = months.value[monthIndex];
const selectedDay = days.value[dayIndex];
// 格式化日期
const formattedDate = `${selectedYear}-${String(selectedMonth).padStart(2, '0')}-${String(selectedDay).padStart(2, '0')}`;
// 更新表单数据
form.value.birthDate = formattedDate;
closeDatePicker();
};
// 科室选择相关函数
const openDeptPicker = () => {
showDeptPicker.value = true;
// 如果当前有选中的科室,设置默认选中项
if (form.value.officeName) {
const index = deptList.value.findIndex(dept => dept === form.value.officeName);
if (index !== -1) {
deptPickerIndex.value = [index];
}
}
};
const closeDeptPicker = () => {
showDeptPicker.value = false;
};
const onDeptChange = (e) => {
const val = e.detail.value;
deptPickerIndex.value = val;
};
const confirmDept = () => {
const selectedIndex = deptPickerIndex.value[0];
const selectedDept = deptList.value[selectedIndex];
// 更新表单数据
form.value.officeName = selectedDept;
closeDeptPicker();
};
// 职称选择相关函数
const openTitlePicker = () => {
showTitlePicker.value = true;
// 如果当前有选中的职称,设置默认选中项
if (form.value.positionName) {
const index = titleList.value.findIndex(title => title === form.value.positionName);
if (index !== -1) {
titlePickerIndex.value = [index];
}
}
};
const closeTitlePicker = () => {
showTitlePicker.value = false;
};
const onTitleChange = (e) => {
const val = e.detail.value;
titlePickerIndex.value = val;
};
const confirmTitle = () => {
const selectedIndex = titlePickerIndex.value[0];
const selectedTitle = titleList.value[selectedIndex];
// 更新表单数据
form.value.positionName = selectedTitle;
closeTitlePicker();
};
const onPickGender = () => {};
const onPickBirthday = () => {};
const onPickBirthday = () => {
openDatePicker();
};
const onEditPhone = () => {};
const onEditEmail = () => {};
const onPickHospital = () => {};
const onPickDept = () => {};
const onPickDept = () => {
openDeptPicker();
};
const onEditDeptPhone = () => {};
const onPickTitle = () => {};
const onPickTitle = () => {
openTitlePicker();
};
const onEditLicenseNo = () => {};
const onEditSpecialty = () => {};
const onEditIntro = () => {};
onShow(() => {
// 可在此处拉取并回填个人资料
getExpertByUuid();
getPositionList();
});
</script>
@@ -277,4 +715,67 @@
border-radius: 8rpx;
background-color: #f5f5f5;
}
.placeholder {
color: #bbb;
}
/* 地区选择器样式 */
.picker-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0,0,0,0.4);
z-index: 1000;
}
.picker-panel {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
z-index: 1001;
}
.picker-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 24rpx;
border-bottom: 1rpx solid #eee;
}
.picker-title {
font-size: 30rpx;
color: #333;
}
.picker-btn {
color: #666;
font-size: 28rpx;
}
.picker-btn.ok {
color: #38c1b1;
}
.picker-view {
height: 480rpx;
}
.picker-item {
height: 80rpx;
line-height: 80rpx;
text-align: center;
color: #333;
}
.picker-empty {
padding: 40rpx;
text-align: center;
color: #999;
}
</style>
+35 -17
View File
@@ -21,7 +21,7 @@
<uni-icons type="clear" size="20" color="#999"></uni-icons>
</view>
</view>
<view class="cancel-btn" @click="goBack">
<view class="cancel-btn" @click="goSearch">
<text class="cancel-text">搜索</text>
</view>
</view>
@@ -38,7 +38,7 @@
class="category-item"
v-for="(item, index) in categoryList"
:key="index"
@click="onCategoryClick(Index,item.type)"
@click="onCategoryClick(index,item.type)"
>
<view class="category-icon">
<up-image :src="item.icon" width="60rpx" height="60rpx" v-if="tab!=index"></up-image>
@@ -78,7 +78,8 @@
import doctorOn from "@/static/item_doctor_yes.png"
import mall from "@/static/item_mall_no.png"
import mallOn from "@/static/item_mall_yes.png"
const tab=ref(-1);
const tab=ref(0);
const type=ref('');
// 搜索关键词
const searchKeyword = ref('');
@@ -97,10 +98,10 @@
{ name: '指南', icon:zhinan, activeIcon:zhinanOn,type: 'zhinan' },
{ name: '精品课', icon:course,activeIcon:courseOn, type: 'course' },
{ name: '肝胆课件', icon:ppt,activeIcon:pptOn, type: 'ppt' },
{ name: '患者', icon:patient, patientIcon:patientOn,type: 'patient' },
{ name: '名院', icon:doctor,activeIcon:doctorOn, type: 'doctor' },
{ name: '名科', icon:department,activeIcon:departmentOn, type: 'department' },
{ name: '名医', icon:doctor, activeIcon:doctorOn,type: 'doctor' },
// { name: '患者', icon:patient, patientIcon:patientOn,type: 'patient' },
// { name: '名院', icon:doctor,activeIcon:doctorOn, type: 'doctor' },
// { name: '名科', icon:department,activeIcon:departmentOn, type: 'department' },
// { name: '名医', icon:doctor, activeIcon:doctorOn,type: 'doctor' },
{ name: '积分商城', icon:mall,activeIcon:mallOn, type: 'mall' }
]);
@@ -134,34 +135,51 @@
};
// 点击分类
const onCategoryClick = (index,type) => {
tab.value=index;
if(type=='video'){
const goSearch = () => {
if(!searchKeyword.value){
uni.showToast({
title: `请输入搜索内容`,
icon: 'none'
});
return;
}
if(type.value=='video'){
uni.navigateTo({
url: `/pages_app/searchVideo/searchVideo?keywords=${searchKeyword.value}`
})
}else if(type=='videoPatient'){
}else if(type.value=='videoPatient'){
uni.navigateTo({
url: `/pages_app/searchVideo/searchVideo?keywords=${searchKeyword.value}&from=hjsp`
})
}else if(type=='news'){
}else if(type.value=='news'){
uni.navigateTo({
url: `/pages_app/searchNews/searchNews?keywords=${searchKeyword.value}`
})
}else if(type=='kepu'){
}else if(type.value=='kepu'){
uni.navigateTo({
url: `/pages_app/searchNews/searchNews?keywords=${searchKeyword.value}&from=kp`
})
}else if(type=='zhinan'){
}else if(type.value=='zhinan'){
uni.navigateTo({
url: `/pages_app/hot/hot?name=${searchKeyword.value}`
})
}else if(type=='course'){
}else if(type.value=='course'){
uni.navigateTo({
url: `/pages_app/searchNews/searchNews?keywords=${searchKeyword.value}&from=kp`
url: `/pages_course/course/course?keywords=${searchKeyword.value}`
})
}else if(type.value=='ppt'){
uni.navigateTo({
url: `/pages_app/hot/hot?name=${searchKeyword.value}`
})
}else if(type.value=='mall'){
uni.navigateTo({
url: `/pages_goods/pointMall/pointMall?keywords=${searchKeyword.value}`
})
}
}
const onCategoryClick = (index,typeStr) => {
tab.value=index;
type.value=typeStr;
// 这里可以根据分类进行搜索
};
+123
View File
@@ -0,0 +1,123 @@
<template>
<view class="page">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
title="修改邮箱"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
/>
<view class="content">
<!-- 邮箱输入框 -->
<view class="input-wrapper">
<input
class="input"
type="text"
placeholder="请输入您的邮箱"
placeholder-class="ph"
v-model.trim="email"
/>
</view>
<!-- 提示文案 -->
<view class="hint">请填写您的真实邮箱,以便联系上您</view>
</view>
<!-- 底部保存按钮 -->
<view class="footer">
<button class="save-btn" @click="onSave">保存</button>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const email = ref('')
const goBack = () => {
uni.navigateBack()
}
const isValidEmail = (val) => {
if (!val) return false
const re = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/
return re.test(val)
}
const onSave = () => {
if (!isValidEmail(email.value)) {
uni.showToast({ title: '请输入有效的邮箱', icon: 'none' })
return
}
// 这里调用保存接口(占位)
// await api.updateEmail({ email: email.value })
uni.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => goBack(), 800)
}
</script>
<style lang="scss" scoped>
.page {
background-color: #fff;
min-height: 100vh;
}
.content {
padding: 24rpx 30rpx;
}
.input-wrapper {
background: #fff;
border: 2rpx solid #e6e6e6;
border-radius: 16rpx;
padding: 16rpx 20rpx;
}
.input {
height: 72rpx;
line-height: 72rpx;
font-size: 28rpx;
color: #333;
}
.ph {
color: #c7c7c7;
}
.hint {
margin-top: 24rpx;
font-size: 26rpx;
color: #666;
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: env(safe-area-inset-bottom);
padding: 24rpx 30rpx calc(24rpx + env(safe-area-inset-bottom));
background-color: #fff;
}
.save-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
text-align: center;
color: #8b2316;
font-size: 30rpx;
border: 2rpx solid #8b2316;
border-radius: 16rpx;
background: #fff;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
}
</style>
+132
View File
@@ -0,0 +1,132 @@
<template>
<view class="page">
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
title="修改邮箱"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eeeeee"
/>
<view class="content">
{{ eitType === 'email' }}
<!-- 邮箱输入框 -->
<view class="input-wrapper">
<input
v-if="eitType === 'email'"
class="input"
type="text"
:placeholder="placeholder"
placeholder-class="ph"
v-model.trim="content"
>
</input>
<textarea v-model.trim="content" placeholder="请输入您的个人简介(500字以内)" placeholder-class="ph" auto-height v-else > </textarea>
</view>
<!-- 提示文案 -->
<view class="hint">请填写您的真实邮箱,以便联系上您</view>
</view>
<!-- 底部保存按钮 -->
<view class="footer">
<button class="save-btn" @click="onSave">保存</button>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const content = ref('')
const eitType = ref('1ww');
const placeholder = ref('请输入您的邮箱');
const goBack = () => {
uni.navigateBack()
}
const isValidEmail = (val) => {
if (!val) return false
const re = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/
return re.test(val)
}
const onSave = () => {
if (!isValidEmail(email.value)) {
uni.showToast({ title: '请输入有效的邮箱', icon: 'none' })
return
}
// 这里调用保存接口(占位)
// await api.updateEmail({ email: email.value })
uni.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => goBack(), 800)
}
</script>
<style lang="scss" scoped>
.page {
background-color: #fff;
min-height: 100vh;
}
.content {
padding: 24rpx 30rpx;
}
.input-wrapper {
background: #fff;
border: 2rpx solid #e6e6e6;
border-radius: 16rpx;
padding: 16rpx 20rpx;
}
.input {
height: 60rpx;
line-height:60rpx;
font-size: 28rpx;
color: #333;
}
.ph {
color: #c7c7c7;
}
.hint {
margin-top: 24rpx;
font-size: 26rpx;
color: #333;
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: env(safe-area-inset-bottom);
padding: 24rpx 30rpx calc(24rpx + env(safe-area-inset-bottom));
background-color: #fff;
}
.save-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
text-align: center;
color: #8b2316;
font-size: 30rpx;
border: 2rpx solid #8b2316;
border-radius: 16rpx;
background: #fff;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
}
</style>