9.8 17:44

This commit is contained in:
zoujiandong
2025-09-08 17:44:31 +08:00
parent 1556ea2ec7
commit d827caed33
11 changed files with 2779 additions and 195 deletions
+194 -41
View File
@@ -26,9 +26,12 @@
</view>
<!-- 姓名 -->
<view class="row">
<view class="row" @click="onEdit('name',form.realName)">
<view class="label"><text>姓名</text><text class="req">*</text></view>
<view class="value">{{ form.realName }}</view>
<view class="value with-arrow">
<text>{{ form.realName }}</text>
<uni-icons type="right" size="18" color="#bbb" />
</view>
</view>
<!-- 性别 -->
@@ -59,7 +62,7 @@
</view>
<!-- 邮箱 -->
<view class="row" @click="onEditEmail">
<view class="row" @click="onEdit('email',form.email)">
<view class="label"><text>邮箱</text></view>
<view class="value with-arrow">
<text>{{ form.email || '' }}</text>
@@ -90,7 +93,7 @@
</view>
<!-- 科室电话 -->
<view class="row" @click="onEditDeptPhone">
<view class="row" @click="onEdit('officePhone',form.officePhone)">
<view class="label"><text>科室电话</text><text class="req">*</text></view>
<view class="value with-arrow">
<text>{{ form.officePhone }}</text>
@@ -108,7 +111,7 @@
</view>
<!-- 执业医师证编号 -->
<view class="row" @click="onEditLicenseNo">
<view class="row" @click="onEdit('certificate',form.certificate)">
<view class="label"><text>执业医师证编号</text><text class="req">*</text></view>
<view class="value with-arrow">
<text>{{ form.certificate }}</text>
@@ -135,7 +138,7 @@
</view>
<!-- 个人简介 -->
<view class="row" @click="onEditIntro">
<view class="row" @click="onEdit('intro',form.intro)">
<view class="label"><text>个人简介</text></view>
<view class="value with-arrow">
<text>{{ form.intro || '暂无简介' }}</text>
@@ -197,7 +200,7 @@
</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>
<view v-for="(office, index) in officeList" :key="index" class="picker-item">{{ office.name }}</view>
</picker-view-column>
</picker-view>
</view>
@@ -212,19 +215,57 @@
</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>
<view v-for="(title, index) in titleList" :key="index" class="picker-item">{{ title.name }}</view>
</picker-view-column>
</picker-view>
</view>
</view>
<!-- 专长多选弹窗 -->
<view v-if="showSpecialtyPicker" class="picker-mask" @click="closeSpecialtyPicker"></view>
<view v-if="showSpecialtyPicker" class="picker-panel specialties" @click.stop>
<view class="picker-header">
<text class="picker-btn" @click="closeSpecialtyPicker">取消</text>
<text class="picker-title">请选择专长</text>
<text class="picker-btn ok" @click="confirmSpecialties">确定</text>
</view>
<view class="specialty-grid">
<view
v-for="(item,idx) in specialtyOptions"
:key="idx"
class="specialty-item"
:class="{ selected: isSpecialtySelected(item), disabled: isMaxSelected && !isSpecialtySelected(item) }"
@click.stop="toggleSpecialty(item)"
>
<text>{{ item }}</text>
</view>
</view>
<view class="tips">最多可选择10项{{ selectedSpecialties.length }}/10</view>
</view>
<qf-image-cropper v-if="showCropper" :src="cropperSrc" :width="400" :height="400" :radius="30" @crop="handleCrop"></qf-image-cropper>
<!-- 性别选择器 -->
<view v-if="showGenderPicker" class="picker-mask" @click="closeGenderPicker"></view>
<view v-if="showGenderPicker" class="picker-panel" @click.stop>
<view class="picker-header">
<text class="picker-btn" @click="closeGenderPicker">取消</text>
<text class="picker-title">选择性别</text>
<text class="picker-btn ok" @click="confirmGender">确定</text>
</view>
<picker-view class="picker-view" :indicator-style="indicatorStyle" :value="genderPickerIndex" @change="onGenderChange">
<picker-view-column>
<view v-for="(g, gi) in genderList" :key="gi" class="picker-item">{{ g }}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onShow } from "@dcloudio/uni-app";
import { ref,computed } from 'vue';
import { onShow,onLoad,onUnload} from "@dcloudio/uni-app";
import api from '@/api/api';
import areaList from '@/utils/areaList.js';
import docUrl from '@/utils/docUrl';
import navTo from '@/utils/navTo';
import QfImageCropper from '@/components/qf-image-cropper/qf-image-cropper.vue';
const form = ref({
// 基本资料字段
photo: '',
@@ -264,9 +305,31 @@
const months = ref([]);
const days = ref([]);
const datePickerIndex = ref([0, 0, 0]);
const cropperSrc = ref('');
const showCropper = ref(false);
// 科室选择相关变量
const showDeptPicker = ref(false);
// 性别选择
const showGenderPicker = ref(false)
const genderList = ref(['男', '女'])
const genderPickerIndex = ref([0])
const onPickGender = () => {
// 打开时根据当前值预选
const idx = genderList.value.findIndex(g => g === getGenderText(form.value.sex))
genderPickerIndex.value = [idx >= 0 ? idx : 0]
showGenderPicker.value = true
}
const closeGenderPicker = () => { showGenderPicker.value = false }
const onGenderChange = (e) => { genderPickerIndex.value = e.detail.value }
const confirmGender = () => {
const idx = genderPickerIndex.value[0] || 0
const g = genderList.value[idx]
// 写回 form.sex(0男/1女 或根据你项目定义)
form.value.sex = g === '男' ? 0 : 1
showGenderPicker.value = false
}
const deptList = ref([
'内科', '外科', '妇产科', '儿科', '眼科', '耳鼻喉科', '口腔科', '皮肤科',
'神经科', '精神科', '肿瘤科', '康复科', '急诊科', '麻醉科', '病理科',
@@ -275,49 +338,67 @@
'手术室', '门诊部', '住院部', '体检中心', '其他'
]);
const deptPickerIndex = ref([0]);
const onEdit = (name,value) => {
navTo({
url: `/pages_app/writeInfo/writeInfo?editType=${name}&value=${value}`
});
};
// 职称选择相关变量
const showTitlePicker = ref(false);
const titleList = ref([
'住院医师', '主治医师', '副主任医师', '主任医师',
'住院中医师', '主治中医师', '副主任中医师', '主任中医师',
'住院药师', '主管药师', '副主任药师', '主任药师',
'住院护师', '主管护师', '副主任护师', '主任护师',
'住院技师', '主管技师', '副主任技师', '主任技师',
'助理医师', '执业医师', '执业助理医师',
'医士', '医师', '主管医师', '副主任医师', '主任医师',
'护士', '护师', '主管护师', '副主任护师', '主任护师',
'技师', '主管技师', '副主任技师', '主任技师',
'其他'
]);
const titleList = ref([]);
const diseaseList = ref([]);
const officeList = ref([]);
const titlePickerIndex = ref([0]);
// 专长多选
const showSpecialtyPicker = ref(false)
const specialtyOptions = ref([
'肝炎','药物肝病','中西医结合','肝硬化','肝衰竭','乙型肝炎','肝癌介入','寄生虫病',
'产科肝病','胆结石','小儿肝病','肝癌外科','胆囊炎','免疫肝病','脂肪肝病','胆囊息肉',
'酒精肝病','肝癌内科','先天肝病','中医肝胆','肝移植','其他'
])
const selectedSpecialties = ref([])
const isMaxSelected = computed(() => selectedSpecialties.value.length >= 10)
const onEditSpecialty = () => {
selectedSpecialties.value = (form.value.specialityList || []).map(i => i.diseaseName || i)
showSpecialtyPicker.value = true
}
const goBack = () => uni.navigateBack();
const closeSpecialtyPicker = () => { showSpecialtyPicker.value = false }
const isSpecialtySelected = (name) => selectedSpecialties.value.includes(name)
const toggleSpecialty = (name) => {
const i = selectedSpecialties.value.indexOf(name)
if (i > -1) { selectedSpecialties.value.splice(i,1); return }
if (isMaxSelected.value) return
selectedSpecialties.value.push(name)
}
const confirmSpecialties = () => {
form.value.specialityList = selectedSpecialties.value.map(n => ({ diseaseName: n }))
showSpecialtyPicker.value = false
}
// 获取性别文本
const getGenderText = (sex) => {
const genderMap = { 0: '', 1: '' };
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);
diseaseList.value = res.data;
}
};
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);
titleList.value = res.data
}
};
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);
officeList.value = res.data
}
};
@@ -395,17 +476,40 @@
}
});
};
const cropType = ref('avatar');
const onChooseAvatar = () => {
openCropper((path) => {
form.value.avatar = path;
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album'],
success: (res) => {
cropperSrc.value = res.tempFilePaths[0];
showCropper.value = true;
}
});
};
const handleCrop = (e) => {
console.log(e);
if(cropType.value === 'avatar'){
form.value.photo = e.tempFilePath;
}else{
form.value.certificateImg = e.tempFilePath;
}
showCropper.value = false;
};
const onChooseLicenseImg = () => {
openCropper((path) => {
form.value.licenseImg = path;
}, { destWidth: 1000, rectWidth: 500 });
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album'],
success: (res) => {
cropperSrc.value = res.tempFilePaths[0];
cropType.value = 'license';
showCropper.value = true;
}
});
};
// 地址选择相关函数
@@ -615,7 +719,8 @@
const confirmTitle = () => {
const selectedIndex = titlePickerIndex.value[0];
const selectedTitle = titleList.value[selectedIndex];
console.log(titleList.value[selectedIndex]);
const selectedTitle = titleList.value[selectedIndex].name;
// 更新表单数据
form.value.positionName = selectedTitle;
@@ -623,7 +728,6 @@
closeTitlePicker();
};
const onPickGender = () => {};
const onPickBirthday = () => {
openDatePicker();
};
@@ -637,14 +741,31 @@
openTitlePicker();
};
const onEditLicenseNo = () => {};
const onEditSpecialty = () => {};
const onEditIntro = () => {};
onLoad(() => {
getExpertByUuid();
});
onShow(() => {
// 可在此处拉取并回填个人资料
getExpertByUuid();
uni.$off('writeInfoSaved')
uni.$on('writeInfoSaved', ({ editType, content }) => {
switch (editType) {
case 'email': form.value.email = content; break
case 'name': form.value.realName = content; break
case 'officePhone': form.value.officePhone = content; break
case 'certificate': form.value.certificate = content; break
case 'intro': form.value.intro = content; break
default: break
}
})
getPositionList();
getOfficeList();
//getDiseaseList();
});
onUnload(() => {
uni.$off('writeInfoSaved')
})
</script>
<style lang="scss" scoped>
@@ -778,4 +899,36 @@
text-align: center;
color: #999;
}
/* 专长弹窗 */
.picker-panel.specialties { max-height: 70vh; }
.specialty-grid {
padding: 24rpx;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20rpx;
max-height: calc(70vh - 160rpx);
overflow-y: auto;
}
.specialty-item {
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
padding: 24rpx 10rpx;
text-align: center;
font-size: 26rpx;
color: #333;
background: #fff;
}
.specialty-item.selected {
border-color: #8B2316;
color: #8B2316;
background: #fff7f5;
}
.specialty-item.disabled {
opacity: .5;
}
.tips {
padding: 16rpx 24rpx;
font-size: 24rpx;
color: #999;
}
</style>
+9 -6
View File
@@ -112,7 +112,7 @@
const remindPatient = ref(true);
const headerYear = ref('');
const headerDay = ref('');
const patientUuid = ref('');
// 返回上一页
const goBack = () => {
uni.navigateBack();
@@ -141,12 +141,15 @@
// 选择患者
const selectPatient = () => {
uni.showActionSheet({
itemList: ['张三', '李四', '王五', '赵六'],
success: (res) => {
selectedPatient.value = ['张三', '李四', '王五', '赵六'][res.tapIndex];
navTo({
url:'/pages_app/selectPatientSingle/selectPatientSingle',
events: {
onPatientsSelected: (data) => {
selectedPatient.value = data.realName;
patientUuid.value = data.uuid;
}
}
});
})
};
// 选择日期
@@ -0,0 +1,155 @@
<template>
<view class="select-page">
<uni-nav-bar
left-icon="left"
title="选择患者"
@clickLeft="goBack"
fixed
color="#8B2316"
height="140rpx"
:border="false"
backgroundColor="#eee"
>
<!-- <template #right>
<view class="confirm-btn" :class="{ active: selectedIds.length > 0 }" @click="confirmSelect">
<text class="confirm-text">确定({{ selectedIds.length }})</text>
</view>
</template> -->
</uni-nav-bar>
<!-- 搜索框 -->
<view class="search-bar">
<view class="input-wrap">
<input class="search-input" v-model.trim="keyword" placeholder="搜索患者的备注名、昵称或手机号" placeholder-class="ph" @confirm="onSearch" />
</view>
<view class="search-btn" @click="onSearch">
<uni-icons type="search" size="50rpx" color="#999" />
</view>
</view>
<!-- 列表 -->
<scroll-view class="list" scroll-y>
<view class="item" @click="toggle(p.uuid)" v-for="p in availablePatientList" :key="p.uuid">
<image class="avatar" :src="docUrl + (p.photo || '')" mode="aspectFill" />
<view class="name">{{ p.realName || '-' }}</view>
<view class="check" >
<view class="circle" :class="{ active: selectedIds.includes(p.uuid) }"></view>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import docUrl from '@/utils/docUrl.js'
import { onShow,onLoad} from "@dcloudio/uni-app";
import api from '@/api/api.js'
const keyword = ref('')
const selectedIds = ref([])
const patientList = ref([])
const selectedDetail = ref([])
// 计算属性:显示所有患者,但标记已选中的状态
const availablePatientList = computed(() => {
return patientList.value
})
const patientListByGBK = async () => {
const res = await api.patientListByGBK();
if(res.code == 1){
patientList.value = res.data;
}
};
onLoad(() => {
// 读取已选中的成员ID
try {
const preSelected = uni.getStorageSync('preSelectedIds')
if (Array.isArray(preSelected)) {
selectedIds.value = [...preSelected]
// 清理缓存
uni.removeStorageSync('preSelectedIds')
}
} catch (e) {}
})
onShow(() => {
patientListByGBK();
// 根据已选中的ID更新selectedDetail
updateSelectedDetail();
});
// 根据已选中的ID更新selectedDetail
const updateSelectedDetail = () => {
selectedDetail.value = selectedIds.value.map(id => {
const p = patientList.value.find(x => x.uuid === id)
return { uuid: id, realName: p?.realName || '', photo: p?.photo || '' }
})
}
const toggle = (id) => {
const i = selectedIds.value.indexOf(id)
if (i > -1) {
// 如果已选中,则取消选中
selectedIds.value.splice(i, 1)
const di = selectedDetail.value.findIndex(it => it.uuid === id)
if (di > -1) selectedDetail.value.splice(di, 1)
} else {
// 如果未选中,则选中
selectedIds.value.push(id)
const p = patientList.value.find(x => x.uuid === id)
selectedDetail.value.push({ uuid: id, realName: p?.realName || '', photo: p?.photo || '' })
}
}
const onSearch = () => {}
const goBack = () => uni.navigateBack()
const confirmSelect = (id) => {
const payload =patientList.value.find(x => x.uuid === id)
// 通过事件通道回传
try {
const pages = getCurrentPages()
const curr = pages[pages.length - 1]
const ec = curr?.getOpenerEventChannel?.()
ec?.emit && ec.emit('onPatientsSelected', payload)
} catch (e) {}
// 兜底:使用本地存储
try { uni.setStorageSync('patientsSelectedPayload', payload) } catch (e) {}
uni.navigateBack()
}
</script>
<style lang="scss" scoped>
.select-page{
min-height: 100vh; background:#fefefe;
}
.confirm-text{ color:#fff; font-size: 28rpx;white-space: nowrap; }
.confirm-btn{ background:#7f7f7f; padding: 10rpx 18rpx; border-radius: 26rpx; }
.confirm-btn.active{ background:#8B2316; }
.search-bar{
border: 2rpx solid #eee;
margin: 20rpx 30rpx; display:flex; align-items:center; gap: 16rpx;
.input-wrap{ flex:1; background:#fff; border-radius: 12rpx; padding: 16rpx 20rpx; }
.search-input{ font-size: 28rpx; color:#333; }
.ph{ color:#bfbfbf; }
.search-btn{
display: flex;
align-items: center;
justify-content: center;
width: 88rpx; height: 72rpx; background:#fff;
}
}
.list{ border-radius: 12rpx; }
.item{background:#fff; display:flex; align-items:center;padding: 24rpx 30rpx; border-bottom: 2rpx solid #eee; }
.avatar{ width: 96rpx; height:96rpx; border-radius: 16rpx; background:#ffe; }
.name{ flex:1; margin-left: 20rpx; font-size: 32rpx; color:#333; }
.check{ padding-left: 12rpx; }
.circle{ width: 40rpx; height: 40rpx; border-radius: 50%; border: 2rpx solid #cfcfcf; }
.circle.active{ background:#8B2316; border-color:#8B2316; position: relative; }
.circle.active::after{ content:''; position:absolute; left: 14rpx; top: 6rpx; width: 10rpx; height: 18rpx; border: 4rpx solid #fff; border-top: 0; border-left: 0; transform: rotate(45deg); }
</style>
+10 -1
View File
@@ -191,7 +191,16 @@
};
const selectPatient=()=>{
if(from.value=='patientMsg'){
navTo({url:'/pages_app/selectPatient/selectPatient'})
navTo({
url:'/pages_app/selectPatient/selectPatient',
events: {
onPatientsSelected: ({ ids, list }) => {
//console.log(ids, list)
patientUuid.value = list.map(item=>item.uuid).join(',');
patientName.value = list.map(item=>item.realName).join(',');
}
}
})
}
};
+69 -15
View File
@@ -3,7 +3,7 @@
<!-- 顶部导航栏 -->
<uni-nav-bar
left-icon="left"
title="修改邮箱"
:title="title"
@clickLeft="goBack"
fixed
color="#8B2316"
@@ -11,21 +11,28 @@
:border="false"
backgroundColor="#eeeeee"
/>
<view class="content">
<!-- 邮箱输入框 -->
<!-- 输入区域邮箱或其他文本 -->
<view class="input-wrapper">
<input
v-if="editType === 'email'"
class="input"
type="text"
placeholder="请输入您的邮箱"
:placeholder="placeholder"
placeholder-class="ph"
v-model.trim="email"
/>
v-model.trim="content"
>
</input>
<textarea v-else v-model.trim="content" :placeholder="placeholderTextArea" placeholder-class="ph" auto-height> </textarea>
</view>
<!-- 提示文案 -->
<view class="hint">请填写您的真实邮箱以便联系上您</view>
<view class="hint">{{ hint }}</view>
</view>
<!-- 底部保存按钮 -->
@@ -37,8 +44,47 @@
<script setup>
import { ref } from 'vue'
const title = ref('修改邮箱');
import { onLoad } from '@dcloudio/uni-app';
const content = ref('')
const editType = ref('');
const placeholder = ref('请输入您的邮箱');
const placeholderTextArea = ref('请输入您的个人简介(500字以内)');
const hint = ref('请填写您的真实邮箱,以便联系上您');
onLoad((options) => {
editType.value = options && options.editType ? options.editType : '';
content.value = (options && options.value) ? options.value : '';
switch (editType.value) {
case 'email':
title.value = '修改邮箱';
placeholder.value = '请输入您的邮箱';
hint.value = '请填写您的真实邮箱,以便联系上您';
break;
case 'name':
title.value = '修改姓名';
placeholder.value = '请输入您的姓名';
hint.value = '';
break;
case 'officePhone':
title.value = '修改科室电话';
placeholder.value = '请输入您的科室电话';
hint.value = '';
break;
case 'certificate':
title.value = '修改执业医师证编号';
placeholder.value = '请输入您的执业医师证编号';
hint.value = '';
break;
case 'intro':
title.value = '修改个人简介';
placeholderTextArea.value = '请输入您的个人简介(500字以内)';
hint.value = '';
break;
default:
break;
}
})
const email = ref('')
const goBack = () => {
uni.navigateBack()
@@ -51,15 +97,20 @@ const isValidEmail = (val) => {
}
const onSave = () => {
if (!isValidEmail(email.value)) {
// 校验:邮箱时才校验格式
if (editType.value === 'email' && !isValidEmail(content.value)) {
uni.showToast({ title: '请输入有效的邮箱', icon: 'none' })
return
}
// 这里调用保存接口(占位)
// await api.updateEmail({ email: email.value })
// 将数据回传到上一页(personInfo),监听事件名:writeInfoSaved
uni.$emit('writeInfoSaved', {
editType: editType.value,
content: content.value
})
uni.showToast({ title: '保存成功', icon: 'success' })
setTimeout(() => goBack(), 800)
setTimeout(() => goBack(), 300)
}
</script>
@@ -71,6 +122,9 @@ const onSave = () => {
.content {
padding: 24rpx 30rpx;
textarea{
min-height:400rpx;
}
}
.input-wrapper {
@@ -81,8 +135,8 @@ const onSave = () => {
}
.input {
height: 72rpx;
line-height: 72rpx;
height: 60rpx;
line-height:60rpx;
font-size: 28rpx;
color: #333;
}
@@ -94,7 +148,7 @@ const onSave = () => {
.hint {
margin-top: 24rpx;
font-size: 26rpx;
color: #666;
color: #333;
}
.footer {
-132
View File
@@ -1,132 +0,0 @@
<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>