Files
xk-client-wx/subPackages/register/components/RegisterPatientStep.vue
2026-08-08 18:36:38 +08:00

971 lines
29 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container safe-area-inset-bottom">
<view class="header-section">
<view class="title-row">
<text class="main-title">您需要为谁{{ registerType === '3' || registerType === '2' ? '复诊' : '挂号' }}</text>
<view class="register-type-tag">
<text class="type-label">{{ registerTypeLabel }}</text>
</view>
</view>
<text v-if="showDelegateInfo" class="delegate-info">
委托诊所:{{ delegateStoreName }} 委托医生:{{ delegateDoctorName }}
</text>
<text class="sub-title">请选择患者信息,以便医生给出更准确的诊疗建议,患者信息仅医生可见</text>
</view>
<view class="detail">
<view class="one" :class="actived==item.id ? 'active' :''" @click="choose(item.id)"
v-for="item in setInfoList" :key="item.id">
<view class="name">
{{item.name}}
<text class="iconfont icon-bianji" v-if="actived==item.id" @click.stop="toEdit"></text>
</view>
<text class="patient-meta">{{(item.sex)% 2 == 1 ? "男" : "女"}} &nbsp; {{item.age}}岁</text>
<image class="choose-badge" src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/choose/choosed.png" mode=""></image>
</view>
<view class="other" @click="goAdd(0)">
<text class="add-plus">+</text>
</view>
</view>
<view class="card follow-up-card modern-card" v-if="showFollowUpForm">
<view class="section-header">
<text class="title-text">患者主诉</text>
<text class="req-tag">* 必填</text>
</view>
<view class="input-wrapper">
<textarea
class="chief-textarea"
v-model="chiefComplaint"
placeholder="请简要描述症状、持续时间等..."
placeholder-style="color:#94A3B8; font-size: 28rpx;"
maxlength="2000"
auto-height
/>
</view>
<view class="section-divider"></view>
<view class="section-header">
<text class="title-text">选择相关西药</text>
<text class="req-tag">* 必选</text>
</view>
<view class="hint-box">
<text class="sub-hint">请至少选择一种药品;仅展示本门店与总后台均已上架的西药;数量仅作展示,提交按药品种类关联。</text>
</view>
<view class="drug-container">
<FollowUpDrugDrawer
v-model="selectedFollowUpDrugs"
:store-id="resolveRegisterStoreId()"
/>
</view>
</view>
<view class="card" v-if="showHealthInfo" style="margin-top: 0;">
<view class="card_title">健康信息</view>
<view class="card_names">
<text class="health-label">肝功能</text>
<u-radio-group v-model="liver" size="44rpx">
<u-radio size="44rpx" active-color="#2979FF" :name="liver">{{liver}}</u-radio>
</u-radio-group>
</view>
<view class="card_names">
<text class="health-label">肾功能</text>
<u-radio-group v-model="renal" size="44rpx">
<u-radio :name="renal">{{renal}}</u-radio>
</u-radio-group>
</view>
<view class="card_history">
<view class="name">
<text class="health-label">过敏史</text>
<u-radio-group v-model="allergic" size="44rpx">
<u-radio :name="allergic">{{allergic}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="allergicList[0]!='' && allergic === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in allergicList" :key="index"
:text="item" mode="dark" />
</view>
</view>
<view class="card_history">
<view class="name">
<text class="health-label">现病史</text>
<u-radio-group v-model="present" size="44rpx">
<u-radio :name="present">{{present}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="presentList[0]!='' && present === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in presentList" :key="index"
:text="item" mode="dark" />
</view>
</view>
<view class="card_history">
<view class="name">
<text class="health-label">既往史</text>
<u-radio-group v-model="person" size="44rpx">
<u-radio :name="person">{{person}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="personList[0]!='' && person === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in personList" :key="index"
:text="item" mode="dark" />
</view>
</view>
<view class="card_history">
<view class="name">
<text class="health-label">家族史</text>
<u-radio-group v-model="family" size="44rpx">
<u-radio :name="family">{{family}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="familyList[0]!='' && family === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in familyList" :key="index"
:text="item" mode="dark" />
</view>
</view>
<view class="card_history">
<view class="name">
<text class="health-label">流行病学史</text>
<u-radio-group v-model="epidemic" size="44rpx">
<u-radio :name="epidemic">{{epidemic}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="epidemicList[0]!='' && epidemic === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in epidemicList" :key="index"
:text="item" mode="dark" />
</view>
</view>
<view class="card_history">
<view class="name">
<text class="health-label">个人史</text>
<u-radio-group v-model="personal" size="44rpx">
<u-radio :name="personal">{{personal}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="personalList[0]!='' && personal === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in personalList" :key="index"
:text="item" mode="dark" />
</view>
</view>
<view class="card_history" v-if="showMenstrualHistory">
<view class="name">
<text class="health-label">月经史</text>
<u-radio-group v-model="menstrual" size="44rpx">
<u-radio :name="menstrual">{{menstrual}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="menstrualList[0]!='' && menstrual === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in menstrualList" :key="index"
:text="item" mode="dark" />
</view>
</view>
<view class="card_history" v-if="showMaritalHistory">
<view class="name">
<text class="health-label">婚育史</text>
<u-radio-group v-model="marital" size="44rpx">
<u-radio :name="marital">{{marital}}</u-radio>
</u-radio-group>
</view>
<view class="tabs" v-if="maritalList[0]!='' && marital === '有'">
<u-tag bg-color="#2979FF" color="#FFFFFF" v-for="(item,index) in maritalList" :key="index"
:text="item" mode="dark" />
</view>
</view>
</view>
<view class="footer">
<view class="infos" @click="subScriptionMessage">下一步</view>
</view>
<u-toast ref="uToast" />
</view>
</template>
<script>
import {
userList,
userEidtPatient,
registe,
storeInfo,
doctorDetail,
} from '@/request/api/api.js';
import { getClinicOnlineConsultationInfoApi } from '@/request/api/product';
import { createRegisterInfoApi, saveRegisterInfoApi } from '@/request/api/order';
import request from '@/request/api/request';
export default {
name: 'RegisterPatientStep',
props: {
doctorId: {
type: [String, Number],
default: '',
},
registerTypeProp: {
type: String,
default: '0',
},
initialRInfo: {
type: Object,
default: () => ({}),
},
delegateStoreIdProp: {
type: String,
default: '',
},
},
data() {
return {
Did: '',
actived: 1,
infoList: [],
register_id: '',
liver: '',
renal: '',
allergic: '',
allergicList: [],
present: '无',
presentList: [],
person: '',
personList: [],
family: '',
familyList: [],
epidemic: '无',
epidemicList: [],
personal: '无',
personalList: [],
menstrual: '无',
menstrualList: [],
marital: '无',
maritalList: [],
heathList: [],
rInfo: {},
registerType: '0',
delegateStoreId: '',
delegateStoreName: '',
delegateDoctorName: '',
chiefComplaint: '',
selectedFollowUpDrugs: [],
};
},
computed: {
setInfoList() {
return this.infoList.map((item) => ({ ...item }));
},
registerTypeLabel() {
const typeMap = {
'0': '线下就诊',
'1': '在线问诊',
'2': '在线复诊',
'3': '在线复诊'
};
return typeMap[this.registerType] || '未知类型';
},
hasPrefilledFollowUpInfo() {
const r = this.rInfo;
return !!(r && typeof r === 'object' && !Array.isArray(r) && r.info_id);
},
showFollowUpForm() {
const t = this.registerType;
return (t === '2' || t === '3') && !this.hasPrefilledFollowUpInfo;
},
showDelegateInfo() {
const isFollowUp = this.registerType === '2' || this.registerType === '3';
return isFollowUp && !!(this.delegateStoreName || this.delegateDoctorName);
},
showHealthInfo() {
return this.registerType === '0'
&& !!this.actived
&& this.infoList.some((p) => p.id === this.actived);
},
// 当前选中就诊人(用于月经史/婚育史展示规则)
activePatient() {
return this.infoList.find((p) => p.id === this.actived) || null;
},
showMenstrualHistory() {
const p = this.activePatient;
return !!(p && Number(p.sex) === 2);
},
showMaritalHistory() {
const p = this.activePatient;
if (!p) {
return false;
}
const sex = Number(p.sex);
const age = Number(p.age) || 0;
return (sex === 1 && age > 22) || (sex === 2 && age > 20);
},
},
watch: {
doctorId: {
immediate: true,
handler(val) {
this.Did = val;
},
},
registerTypeProp: {
immediate: true,
handler(val) {
if (val) this.registerType = val;
},
},
initialRInfo: {
immediate: true,
deep: true,
handler(val) {
this.rInfo = val ? { ...val } : {};
},
},
delegateStoreIdProp: {
immediate: true,
handler(val) {
this.delegateStoreId = val || '';
this.loadDelegateDisplayInfo();
},
},
},
mounted() {
this.getInfolist();
},
methods: {
resolveRegisterStoreId() {
return (this.registerType !== '0' && this.delegateStoreId)
? this.delegateStoreId
: (uni.getStorageSync('store_id') || '11001');
},
async loadDelegateDisplayInfo() {
if (this.registerType !== '2' && this.registerType !== '3') return;
const currentStoreId = uni.getStorageSync('store_id') || '11001';
try {
if (this.registerType === '2') {
const res = await getClinicOnlineConsultationInfoApi({ store_id: currentStoreId });
const result = res.data?.result;
if (res.data?.code === 0 && result) {
this.delegateStoreName = result.delegate_store_name || result.store_name || '';
this.delegateDoctorName = result.doctor_name || '';
}
} else {
const storeId = this.delegateStoreId || this.resolveRegisterStoreId();
const [storeRes, doctorRes] = await Promise.all([
storeInfo({ method: 'post', data: { store_id: storeId } }),
doctorDetail({ method: 'post', data: { doctor_id: this.Did, store_id: currentStoreId } }),
]);
if (storeRes.data?.errcode == 0) {
this.delegateStoreName = storeRes.data.data?.store?.name || '';
}
const doctorData = doctorRes.data?.data || doctorRes.data?.result;
if (doctorRes.data?.errcode == 0 || doctorRes.data?.code === 0) {
this.delegateDoctorName = doctorData?.name || '';
}
}
} catch (e) {
console.warn('loadDelegateDisplayInfo', e);
}
},
followUpDrugIdsForApi() {
const ids = [];
const seen = new Set();
for (const it of this.selectedFollowUpDrugs || []) {
const id = Number(it.id);
if (id > 0 && !seen.has(id)) {
seen.add(id);
ids.push(id);
}
}
return ids;
},
validateFollowUpFields() {
const chief = String(this.chiefComplaint || '').trim();
if (!chief) return '请填写患者主诉';
if (this.followUpDrugIdsForApi().length === 0) return '请至少选择一种药品';
return '';
},
/**
* 在线复诊必须有就诊人身份证:列表接口已解密回传 id_card,空则引导去编辑页补填
* 普通挂号不强制
*/
ensureFollowUpPatientIdCard() {
if (this.registerType !== '2' && this.registerType !== '3') {
return true;
}
if (!this.actived) {
uni.showToast({ title: '请选择就诊人', icon: 'none' });
return false;
}
const patient = this.infoList.find((p) => p.id === this.actived) || null;
const idCard = patient ? String(patient.id_card || '').trim() : '';
if (!idCard) {
uni.showToast({
title: '复诊需补充就诊人身份证',
icon: 'none',
});
setTimeout(() => {
uni.navigateTo({ url: '/subPackages/my/myinfo-edit?id=' + this.actived });
}, 500);
return false;
}
return true;
},
async prepareFollowUpRegisterInfo() {
let params = typeof this.rInfo === 'string' ? JSON.parse(this.rInfo) : { ...(this.rInfo || {}) };
if (params.info_id) {
return params;
}
const err = this.validateFollowUpFields();
if (err) {
throw new Error(err);
}
const chief = String(this.chiefComplaint || '').trim();
const storeId = this.resolveRegisterStoreId();
const westernDrugQty = {};
let qtySum = 0;
for (const d of this.selectedFollowUpDrugs || []) {
const id = Number(d.id);
const q = Math.min(99, Math.max(1, Number(d.quantity) || 1));
if (id > 0) {
westernDrugQty[String(id)] = q;
qtySum += q;
}
}
const createRes = await createRegisterInfoApi({
doctor_id: Number(this.Did),
drug_id: '',
has_visited: '',
has_used_drug: '',
illnessInfo: '',
type: 2,
number: qtySum >= 1 ? qtySum : 1,
store_id: Number(storeId) || storeId,
chief_complaint: chief,
drug_ids: this.followUpDrugIdsForApi(),
western_drug_qty: JSON.stringify(westernDrugQty),
});
const infoId = createRes.data?.result?.info_id;
if (!infoId) {
throw new Error('创建就诊信息失败');
}
const followUpDrugs = (this.selectedFollowUpDrugs || [])
.map((d) => ({
drug_id: Number(d.id),
name: d.drug_name || d.name || '',
quantity: Math.min(99, Math.max(1, Number(d.quantity) || 1)),
// 适用症透传到挂号后助手提问页(一个药一题)
indications: d.indications || '',
indications_array: Array.isArray(d.indications_array) ? d.indications_array : [],
}))
.filter((d) => d.drug_id > 0);
const followUpNumber = followUpDrugs.reduce((s, r) => s + (Number(r.quantity) || 1), 0) || 1;
return { ...params, info_id: infoId, follow_up_drugs: followUpDrugs, follow_up_number: followUpNumber, number: followUpNumber };
},
goAdd() {
uni.navigateTo({ url: '/subPackages/my/myinfo-add?id=' });
},
toEdit() {
uni.navigateTo({ url: '/subPackages/my/myinfo-edit?id=' + this.actived });
},
choose(id) {
this.actived = id;
this.getHeath();
},
getInfolist() {
userList({
method: 'post',
data: {
store_id: uni.getStorageSync('store_id') || '11001',
}
}).then((res) => {
if (res.data.errcode == 0) {
this.infoList = res.data.data;
this.infoList.filter(item => {
if (item.is_default == 1) {
this.actived = item.id;
}
});
this.getHeath();
}
});
},
normalizeRInfo(followUpRInfo) {
if (typeof followUpRInfo === 'string') {
try {
return JSON.parse(followUpRInfo);
} catch (e) {
return {};
}
}
return followUpRInfo || {};
},
emitRegisterCreated(followUpRInfo, isHas) {
const rInfoObj = this.normalizeRInfo(followUpRInfo);
const payload = {
register_id: this.register_id,
doctor_id: this.Did,
rInfo: rInfoObj,
};
if (isHas) {
this.$refs.uToast.show({
title: '您已挂号该医生,请继续问诊服务',
type: 'default',
icon: false
});
setTimeout(() => {
this.$emit('register-created', payload);
}, 900);
} else {
this.$emit('register-created', payload);
}
},
async afterRegisterCreated(followUpRInfo) {
if (this.registerType === '3' || this.registerType === '2') {
const params = this.normalizeRInfo(followUpRInfo);
if (params.info_id) {
try {
await request('/xkApi/order/update-register-info-register-id', {
method: 'POST',
data: {
info_id: params.info_id,
register_id: this.register_id,
}
});
} catch (error) {
console.error('更新就诊信息关联失败:', error);
}
} else {
try {
await saveRegisterInfoApi({
register_id: this.register_id,
doctor_id: params.doctor_id || this.Did,
drug_id: params.drug_id || params.id,
has_visited: params.has_visited || params.hasVisited,
has_used_drug: params.has_used_drug || params.hasUsedDrug,
illnessInfo: params.illness_info || params.illnessInfo,
type: params.type,
number: params.number,
store_id: uni.getStorageSync('store_id') || '11001',
});
} catch (error) {
console.error('保存患者就诊信息失败:', error);
}
}
}
uni.setStorageSync('register_id', this.register_id);
this.emitRegisterCreated(followUpRInfo, false);
},
async getAsk() {
uni.showLoading({ title: '加载中...', mask: true });
const storeId = this.resolveRegisterStoreId();
let followUpRInfo = this.rInfo;
if (this.showFollowUpForm) {
try {
followUpRInfo = await this.prepareFollowUpRegisterInfo();
this.rInfo = followUpRInfo;
} catch (e) {
uni.hideLoading();
this.$refs.uToast.show({
title: e.message || '提交失败',
type: 'default',
icon: false
});
return;
}
}
const originStoreId = uni.getStorageSync('store_id') || '';
const shouldSendOriginStoreId =
this.registerType === '2' ||
this.registerType === '3' ||
(this.registerType !== '0' && !!this.delegateStoreId);
registe({
method: 'post',
data: {
user_id: uni.getStorageSync('user_id'),
user_patient_id: this.actived,
store_id: storeId,
origin_store_id: shouldSendOriginStoreId ? originStoreId : 0,
service_user_id: this.Did,
register_type: this.registerType
}
}).then(async (res) => {
if (res.data.errcode == 0) {
this.register_id = res.data.data.register_id;
if (this.registerType === '3' || this.registerType === '2') {
await this.afterRegisterCreated(followUpRInfo);
return;
}
uni.setStorageSync('register_id', this.register_id);
this.emitRegisterCreated(followUpRInfo, res.data.data.isHas == 1);
} else {
this.$refs.uToast.show({
title: res.data.msg,
type: 'default',
icon: false
});
}
}).finally(() => {
uni.hideLoading();
});
},
getHeath() {
userEidtPatient({
method: 'post',
data: {
user_patient_id: this.actived,
store_id: uni.getStorageSync('store_id') || '11001',
}
}).then((res) => {
if (res.data.errcode == 0) {
this.heathList = res.data.data;
this.liver = (this.heathList.liver_function) % 2 == 0 ? '正常' : '异常';
this.renal = (this.heathList.renal_function) % 2 == 0 ? '正常' : '异常';
this.allergic = (this.heathList.allergic_status) % 2 == 0 ? '无' : '有';
this.allergicList = (this.heathList.allergic_history) == 'Array' ? [] : (this.heathList.allergic_history || []);
this.present = (this.heathList.present_status || 0) % 2 == 0 ? '无' : '有';
this.presentList = this.heathList.present_history || [];
this.person = (this.heathList.person_status) % 2 == 0 ? '无' : '有';
this.personList = (this.heathList.person_history) == 'Array' ? [] : (this.heathList.person_history || []);
this.family = (this.heathList.family_status) % 2 == 0 ? '无' : '有';
this.familyList = (this.heathList.family_history) == 'Array' ? [] : (this.heathList.family_history || []);
this.epidemic = (this.heathList.epidemic_status || 0) % 2 == 0 ? '无' : '有';
this.epidemicList = this.heathList.epidemic_history || [];
this.personal = (this.heathList.personal_status || 0) % 2 == 0 ? '无' : '有';
this.personalList = this.heathList.personal_history || [];
this.menstrual = (this.heathList.menstrual_status || 0) % 2 == 0 ? '无' : '有';
this.menstrualList = this.heathList.menstrual_history || [];
this.marital = (this.heathList.marital_status || 0) % 2 == 0 ? '无' : '有';
this.maritalList = this.heathList.marital_history || [];
}
});
},
subScriptionMessage() {
// 在线复诊:先校验就诊人是否已填身份证
if (!this.ensureFollowUpPatientIdCard()) {
return;
}
if (this.showFollowUpForm) {
const err = this.validateFollowUpFields();
if (err) {
this.$refs.uToast.show({
title: err,
type: 'default',
icon: false
});
return;
}
}
uni.requestSubscribeMessage({
tmplIds: [
'O5P8ZZB6T01V5Z66tkbhmzlobSaSRoEfdoCLATuP2Mw',
'ddT3v-m_Sr4kXwGCBLf0O4P89mOS5q10LFMZeEuQm10'
],
complete: () => {
this.getAsk();
}
});
},
refreshPatientList() {
this.getInfolist();
},
},
};
</script>
<style lang="scss" scoped>
.container {
width: 750rpx;
max-height: 100%;
min-height: 100vh;
box-sizing: border-box;
background-color: #F8FAFC;
padding-bottom: 200rpx;
padding-bottom: calc(140rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
.header-section {
padding: 32rpx 32rpx 0;
.title-row {
display: flex;
align-items: center;
margin-bottom: 12rpx;
.main-title {
font-size: 38rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 600;
color: #0F172A;
margin-right: 16rpx;
}
.register-type-tag {
background: linear-gradient(135deg, #4175EE 0%, #298dff 100%);
padding: 4rpx 16rpx;
border-radius: 8rpx;
box-shadow: 0 2rpx 8rpx rgba(65, 117, 238, 0.2);
.type-label {
color: #FFFFFF;
font-size: 24rpx;
font-weight: 500;
}
}
}
.sub-title {
display: block;
font-size: 24rpx;
font-weight: 400;
color: #64748B;
line-height: 1.5;
}
.delegate-info {
display: block;
font-size: 26rpx;
font-weight: 400;
color: #4175EE;
line-height: 1.5;
margin-bottom: 8rpx;
}
}
.detail {
width: 710rpx;
min-height: 124rpx;
margin: 32rpx;
padding-bottom: 8rpx;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
.one {
width: 218rpx;
height: 124rpx;
border-radius: 8rpx;
margin: 0 16rpx 16rpx 0;
border: 2rpx solid #CBD5E1;
position: relative;
background: #FFFFFF;
.name {
margin: 16rpx 0 8rpx 32rpx;
height: 44rpx;
font-size: 32rpx;
font-weight: 400;
color: #0F172A;
display: flex;
justify-content: space-between;
align-items: center;
padding-right: 18rpx;
.iconfont {
font-size: 32rpx;
color: #94A3B8;
}
}
.patient-meta {
font-size: 28rpx;
color: #94A3B8;
margin-left: 32rpx;
}
.choose-badge {
width: 50rpx;
height: 50rpx;
position: absolute;
right: -2rpx;
bottom: -1rpx;
display: none;
}
&.active {
border: 2rpx solid #536DFE;
background: rgba(83, 109, 254, 0.04);
.choose-badge {
display: block;
}
}
}
.other {
width: 218rpx;
height: 124rpx;
line-height: 104rpx;
text-align: center;
border-radius: 8rpx;
border: 2rpx dashed #CBD5E1;
background: #FFFFFF;
.add-plus {
font-size: 68rpx;
color: #94A3B8;
}
}
}
.card {
width: 710rpx;
background: #FFFFFF;
border-radius: 16rpx;
margin: 20rpx auto 40rpx;
padding: 0 32rpx 40rpx;
box-shadow: 0 4rpx 24rpx rgba(15, 23, 42, 0.02);
.card_title {
height: 114rpx;
line-height: 114rpx;
font-size: 34rpx;
font-weight: 600;
color: #1E293B;
border-bottom: 1rpx solid #F1F5F9;
}
.card_names {
width: 646rpx;
padding: 34rpx 0 32rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 30rpx;
border-bottom: 1rpx solid #F1F5F9;
.health-label {
color: #1E293B;
}
}
.card_history {
width: 646rpx;
padding: 34rpx 0 32rpx 0;
font-size: 30rpx;
border-bottom: 1rpx solid #F1F5F9;
.name {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10rpx;
.health-label {
color: #1E293B;
}
}
.tabs {
display: flex;
flex-wrap: wrap;
::v-deep .u-tag {
margin: 10rpx 20rpx 10rpx 0;
}
}
}
.card_history:last-child {
border-bottom: 0;
}
}
.modern-card {
padding: 32rpx;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #0F172A;
position: relative;
padding-left: 18rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 8rpx;
height: 28rpx;
background: #4175EE;
border-radius: 4rpx;
}
}
.req-tag {
color: #EF4444;
font-size: 24rpx;
background: rgba(239, 68, 68, 0.08);
padding: 4rpx 12rpx;
border-radius: 6rpx;
}
}
.section-divider {
height: 1rpx;
background-color: #F1F5F9;
margin: 40rpx 0 32rpx;
}
.input-wrapper {
background: #F8FAFC;
border-radius: 12rpx;
.chief-textarea {
width: 100%;
min-height: 160rpx;
padding: 24rpx;
box-sizing: border-box;
font-size: 28rpx;
color: #334155;
line-height: 1.5;
}
}
.hint-box {
background: #F1F5F9;
border-radius: 8rpx;
padding: 16rpx 24rpx;
margin-bottom: 24rpx;
.sub-hint {
font-size: 24rpx;
color: #64748B;
line-height: 1.6;
}
}
}
.footer {
width: 750rpx;
min-height: 104rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-top: 2rpx solid #F1F5F9;
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
background-color: #FFFFFF;
z-index: 100;
.infos {
width: 686rpx;
height: 90rpx;
line-height: 90rpx;
text-align: center;
margin: 16rpx 0;
font-size: 32rpx;
font-weight: 500;
background: linear-gradient(135deg, #4175EE 0%, #298dff 100%);
box-shadow: 0 8rpx 20rpx rgba(65, 117, 238, 0.3);
border-radius: 198rpx;
color: #FFFFFF;
}
}
}
</style>