<template>
	<view class="bubble-container" :class="{ mine: isMine, other: !isMine }">
		<image class="avatar" :src="avatar" mode="aspectFill"></image>

		<view class="content-wrapper">
			<view
				class="message-bubble"
				:class="['type-' + msg.message_type, { 'no-padding': isMediaOrCard || isSystemPriceUpdate }]"
			>
				<!-- 0. 文本 -->
				<text v-if="msg.message_type === 0" class="text-content" user-select>{{ parsedText }}</text>

				<!-- 1. 图片 -->
				<image
					v-else-if="msg.message_type === 1"
					:src="parsedText"
					mode="widthFix"
					class="media-content image"
					@click="$emit('previewImage', parsedText)"
				></image>

				<!-- 2. 语音 -->
				<view
					v-else-if="msg.message_type === 2"
					class="audio-content"
					:style="{ width: getAudioWidth(msg.duration) }"
					@click="$emit('playAudio', msg)"
				>
					<block v-if="isMine">
						<text class="duration">{{ msg.duration }}''</text>
						<view class="voice-icon-wrap mine" :class="{ playing: isPlaying }">
							<u-icon name="volume-fill" size="20" color="#fff"></u-icon>
						</view>
					</block>
					<block v-else>
						<view class="voice-icon-wrap other" :class="{ playing: isPlaying }">
							<u-icon name="volume-fill" size="20" color="#333"></u-icon>
						</view>
						<text class="duration">{{ msg.duration }}''</text>
					</block>
				</view>

				<!-- 3. 视频 -->
				<video
					v-else-if="msg.message_type === 3"
					:src="videoSrc"
					controls
					class="media-content video"
				></video>

				<!-- 9. 系统消息 -->
				<block v-else-if="msg.message_type === 9">
					<view
						v-if="parsedObj && (parsedObj.type === 'price_update' || parsedObj.type === 'price_adjust')"
						class="service-notify-card"
					>
						<view class="sn-header">
							<text class="sn-title">{{ parsedObj.type === 'price_update' ? '订单改价通知' : '费用调整提醒' }}</text>
						</view>
						<view class="sn-body">
							<block v-if="parsedObj.type === 'price_update'">
								<view class="sn-row">
									<text class="sn-label">变动说明</text>
									<text class="sn-value">{{ parsedObj.message }}</text>
								</view>
								<view class="sn-row">
									<text class="sn-label">最新应付</text>
									<text class="sn-value price">¥{{ parsedObj.total_pay_price }}</text>
								</view>
								<view class="sn-row">
									<text class="sn-label">订单编号</text>
									<text class="sn-value sub">{{ parsedObj.order_no }}</text>
								</view>
							</block>
							<block v-else-if="parsedObj.type === 'price_adjust'">
								<view class="sn-row">
									<text class="sn-label">调整项目</text>
									<text class="sn-value truncate">{{ parsedObj.drug_name || '医疗服务' }}</text>
								</view>
								<view class="sn-row">
									<text class="sn-label">价格变动</text>
									<view class="sn-value-group">
										<text class="old">¥{{ parsedObj.old_price }}</text>
										<u-icon name="arrow-right" size="10" color="#999" style="margin: 0 4rpx"></u-icon>
										<text class="new">¥{{ parsedObj.new_price }}</text>
									</view>
								</view>
								<view class="sn-row">
									<text class="sn-label">变动金额</text>
									<text class="sn-value" :class="parsedObj.adjust_amount >= 0 ? 'color-orange' : 'color-green'">
										{{ parsedObj.adjust_amount >= 0 ? '增加' : '减少' }} ¥{{ Math.abs(parsedObj.adjust_amount) }}
									</text>
								</view>
								<view class="sn-row">
									<text class="sn-label">当前总额</text>
									<text class="sn-value strong">¥{{ parsedObj.total_pay_price }}</text>
								</view>
							</block>
						</view>
					</view>
					<view v-else class="system-inner">
						<text>{{ systemNinePlainText }}</text>
					</view>
				</block>

				<!-- 卡片类 4,10,11,12,13,14 -->
				<view v-else-if="isCardType" class="card-content">
					<!-- 10 挂号 -->
					<block v-if="msg.message_type === 10">
						<view class="card-header bg-green">
							<view class="title-group">
								<u-icon name="calendar-fill" size="16" color="#059669"></u-icon>
								<text class="card-title">预约挂号</text>
							</view>
							<text class="status-tag" :class="'status-' + parsedObj.status">{{ getRegisterStatusText(parsedObj.status) }}</text>
						</view>
						<view class="card-body">
							<view class="info-row">
								<text class="label">订单号</text>
								<text class="value order-font">{{ parsedObj.order_no }}</text>
							</view>
							<view class="info-row">
								<text class="label">就诊人</text>
								<text class="value">{{ (parsedObj.user_patient && parsedObj.user_patient.name) || '未知' }}</text>
							</view>
							<view class="info-row highlight">
								<text class="label">费用</text>
								<text class="value price">¥{{ parsedObj.price }}</text>
							</view>
							<view v-if="parsedObj.chief_complaint" class="text-block">
								<text class="block-label">主诉</text>
								<text class="block-content">{{ parsedObj.chief_complaint }}</text>
							</view>
							<view v-if="parsedObj.illnessInfo" class="text-block">
								<text class="block-label">适用症/症状</text>
								<text class="block-content">{{ parsedObj.illnessInfo }}</text>
							</view>
							<view v-if="parsedObj.illnessInfo" class="info-row">
								<text class="label">是否就诊过</text>
								<text class="value">{{ parsedObj.has_visited === 1 || parsedObj.has_visited === '1' ? '是' : '否' }}</text>
							</view>
							<view v-if="parsedObj.illnessInfo" class="info-row">
								<text class="label">是否使用过药品</text>
								<text class="value">{{ parsedObj.has_used_drug === 1 || parsedObj.has_used_drug === '1' ? '是' : '否' }}</text>
							</view>
							<view v-if="registerCardDrugRows.length" class="drug-list-block">
								<text class="block-label">所选药品</text>
								<view v-for="row in registerCardDrugRows" :key="row._wxKey" class="info-row drug-spec-row">
									<image
										v-if="row.image"
										class="drug-thumb"
										:src="row.image"
										mode="aspectFill"
										@click.stop="$emit('previewImage', row.image)"
									/>
									<view class="drug-name-wrap">
										<text class="label">{{ row.name || '药品' }}</text>
										<text v-if="row.specification" class="spec-text">{{ row.specification }}</text>
									</view>
									<text class="value">×{{ row.quantity }}</text>
								</view>
							</view>
						</view>
						<view
							v-if="registerCardDrugRows.length && canAddExperienceToRx && !isMine"
							class="card-footer card-footer--compact"
						>
							<button
								class="action-btn action-btn--ghost"
								@click.stop="$emit('addRegisterDrugsToRx')"
							>
								添加到处方单
							</button>
						</view>
					</block>

					<!-- 11 复诊用药 -->
					<block v-else-if="msg.message_type === 11 && parsedObj && parsedObj.flow === 'follow_up_drug'">
						<view class="card-header bg-gray">
							<view class="title-group">
								<u-icon name="question-circle-fill" size="16" color="#64748B"></u-icon>
								<text class="card-title">医生助理</text>
							</view>
						</view>
						<view class="card-body">
							<view v-if="parsedObj.question" class="text-block">
								<text class="block-content">{{ parsedObj.question }}</text>
							</view>
							<view v-for="row in followUpDrugs" :key="row._wxKey" class="info-row drug-spec-row">
								<view class="drug-name-wrap">
									<text class="label">{{ row.name || '药品' }}</text>
									<text v-if="row.specification" class="spec-text">{{ row.specification }}</text>
								</view>
								<text class="value">×{{ row.quantity != null ? row.quantity : 1 }}</text>
							</view>
							<view v-if="followUpAnsweredLabel" class="info-row">
								<text class="label">患者选择</text>
								<text class="value">{{ followUpAnsweredLabel }}</text>
							</view>
							<view
								v-if="parsedObj.has_visited === 1 || parsedObj.has_visited === '1' || parsedObj.has_visited === 0 || parsedObj.has_visited === '0'"
								class="info-row"
							>
								<text class="label">是否就诊过</text>
								<text class="value">{{ parsedObj.has_visited === 1 || parsedObj.has_visited === '1' ? '是' : '否' }}</text>
							</view>
							<view v-if="parsedObj.illness_info" class="text-block">
								<text class="block-label">适用症/症状</text>
								<text class="block-content">{{ parsedObj.illness_info }}</text>
							</view>
							<view v-if="parsedObj.supplement" class="text-block">
								<text class="block-label">补充信息</text>
								<text class="block-content">{{ parsedObj.supplement }}</text>
							</view>
							<view v-if="parsedObj.answer_status === 'pending'" class="follow-up-pending-readonly">
								<text class="follow-up-pending-tip">请在挂号后的用药确认页完成选择，此处不可更改</text>
							</view>
						</view>
						<view
							v-if="followUpDrugs.length && canAddExperienceToRx && !isMine"
							class="card-footer card-footer--compact"
						>
							<button
								class="action-btn action-btn--ghost"
								@click.stop="$emit('addRegisterDrugsToRx')"
							>
								添加到处方单
							</button>
						</view>
					</block>

					<!-- 11 就诊经历 -->
					<block v-else-if="msg.message_type === 11">
						<view class="card-header bg-gray">
							<view class="title-group">
								<u-icon name="file-text-fill" size="16" color="#64748B"></u-icon>
								<text class="card-title">患者就诊经历</text>
							</view>
						</view>
						<view class="card-body">
							<view v-if="parsedObj.drug_name" class="info-row">
								<text class="label">药品名称</text>
								<text class="value">{{ parsedObj.drug_name }}</text>
							</view>
							<view v-if="parsedObj.illness_info" class="text-block">
								<text class="block-label">症状描述</text>
								<text class="block-content">{{ parsedObj.illness_info }}</text>
							</view>
							<view class="info-row">
								<text class="label">是否就诊过</text>
								<text class="value">{{ parsedObj.has_visited === '1' ? '是' : '否' }}</text>
							</view>
							<view class="info-row">
								<text class="label">是否使用过药品</text>
								<text class="value">{{ parsedObj.has_used_drug === '1' ? '是' : '否' }}</text>
							</view>
						</view>
						<view
							v-if="parsedObj.drug_name && canAddExperienceToRx && !isMine"
							class="card-footer card-footer--compact"
						>
							<button
								class="action-btn action-btn--ghost"
								@click.stop="$emit('addExperienceToRx', experienceRxPayload)"
							>
								添加到处方单
							</button>
						</view>
					</block>

					<!-- 4 电子处方（医生端仅详情） -->
					<block v-else-if="msg.message_type === 4">
						<view class="card-header bg-blue">
							<view class="title-group">
								<u-icon name="order" size="16" color="#0A84FF"></u-icon>
								<text class="card-title">电子处方</text>
							</view>
							<text class="status-tag blue">{{ getStatusText(parsedObj.status) }}</text>
						</view>
						<view class="card-body">
							<view class="info-row">
								<text class="label">诊断单号</text>
								<text class="value small">{{ parsedObj.order_no }}</text>
							</view>
							<view class="info-row">
								<text class="label">金额</text>
								<text class="value price">¥{{ parsedObj.total_pay_price }}</text>
							</view>
						</view>
						<view class="card-footer">
							<button class="action-btn" @click="$emit('viewPrescription', parsedObj.id, parsedObj.order_no)">查看详情</button>
						</view>
					</block>

					<!-- 12 商品 -->
					<block v-else-if="msg.message_type === 12">
						<view class="card-header bg-blue">
							<view class="title-group">
								<u-icon name="shopping-cart-fill" size="16" color="#0A84FF"></u-icon>
								<text class="card-title">推荐商品</text>
							</view>
						</view>
						<view class="card-body">
							<view class="info-row">
								<text class="label">名称</text>
								<text class="value">{{ parsedObj.product_name }}</text>
							</view>
							<view class="info-row">
								<text class="label">价格</text>
								<text class="value price">¥{{ parsedObj.price }}</text>
							</view>
						</view>
					</block>

					<!-- 13 结束问诊 -->
					<block v-else-if="msg.message_type === 13">
						<view class="card-header bg-green">
							<view class="title-group">
								<u-icon name="checkmark-circle-fill" size="16" color="#059669"></u-icon>
								<text class="card-title">问诊结束</text>
							</view>
						</view>
						<view class="card-body">
							<text class="desc-text">{{ parsedObj.end_reason || parsedObj.reason || parsedObj.message || '本次服务已完成' }}</text>
						</view>
					</block>

					<!-- 14 转诊（只读，与患者端视觉一致） -->
					<block v-else-if="msg.message_type === 14">
						<view class="transfer-readonly">
							<view class="transfer-r-head">
								<u-icon name="order" size="20" color="#ea580c"></u-icon>
								<text class="transfer-r-title">转诊消息</text>
							</view>
							<view class="transfer-r-body">
								<view v-if="parsedObj.transfer_store" class="transfer-r-row">
									<text class="transfer-r-k">转诊诊所</text>
									<text class="transfer-r-v">{{ parsedObj.transfer_store.name || '未知' }}</text>
								</view>
								<view v-if="parsedObj.delegate_store" class="transfer-r-row">
									<text class="transfer-r-k">委托诊所</text>
									<text class="transfer-r-v">{{ parsedObj.delegate_store.name || '未知' }}</text>
								</view>
								<view v-if="parsedObj.prescription_no" class="transfer-r-row">
									<text class="transfer-r-k">处方编号</text>
									<text class="transfer-r-v">{{ parsedObj.prescription_no }}</text>
								</view>
								<view v-if="parsedObj.transfer_reason" class="transfer-r-row">
									<text class="transfer-r-k">转诊原因</text>
									<text class="transfer-r-v">{{ parsedObj.transfer_reason }}</text>
								</view>
								<view v-if="parsedObj.questions && parsedObj.questions.length" class="transfer-qa">
									<text class="transfer-qa-title">咨询问题</text>
									<view v-for="(qa, qix) in transferQuestionsWithKey" :key="qa._wxKey" class="transfer-qa-item">
										<text class="transfer-qa-q">{{ qix + 1 }}. {{ qa.question }}</text>
										<text class="transfer-qa-a">{{ qa.answer }}</text>
									</view>
								</view>
							</view>
							<view class="transfer-r-foot">
								<text v-if="parsedObj.status === 0" class="transfer-r-status">待患者确认转诊</text>
								<text v-else-if="parsedObj.status === 1" class="transfer-r-status ok">患者已同意转诊</text>
								<text v-else-if="parsedObj.status === 3" class="transfer-r-status no">患者已拒绝转诊</text>
								<text v-else class="transfer-r-status">转诊状态：{{ parsedObj.status }}</text>
							</view>
						</view>
					</block>

					<block v-else>
						<view class="card-body"><text>不支持的消息类型</text></view>
					</block>
				</view>

				<text v-else class="text-content">{{ unknownText }}</text>
			</view>
		</view>
	</view>
</template>

<script>
import { parseMessageContent } from '../utils/messageParse.js';
import { withWxKey } from '@/utils/wxListKey.js';

export default {
	name: 'MessageBubble',
	props: {
		msg: { type: Object, required: true },
		isMine: { type: Boolean, default: false },
		avatar: { type: String, default: '' },
		isPlaying: { type: Boolean, default: false },
		/** 接诊中且可开方时，就诊经历卡片显示「加入处方」 */
		canAddExperienceToRx: { type: Boolean, default: false }
	},
	computed: {
		isMediaOrCard() {
			return [1, 3, 4, 10, 11, 12, 13, 14].includes(this.msg.message_type);
		},
		isSystemPriceUpdate() {
			const p = this.parsedObj;
			return this.msg.message_type === 9 && p && (p.type === 'price_update' || p.type === 'price_adjust');
		},
		isCardType() {
			return [4, 10, 11, 12, 13, 14].includes(this.msg.message_type);
		},
		parsedObj() {
			const { message_type, message_content } = this.msg;
			if (![4, 9, 10, 11, 12, 13, 14].includes(message_type)) return null;
			try {
				return typeof message_content === 'object' ? message_content : JSON.parse(message_content);
			} catch (e) {
				return null;
			}
		},
		parsedText() {
			const raw = parseMessageContent(this.msg.message_type, this.msg.message_content);
			if (this.msg.message_type === 0 || this.msg.message_type === 1) {
				return typeof raw === 'string' ? raw : '';
			}
			return '';
		},
		videoSrc() {
			if (this.msg.message_type !== 3) return '';
			const p = parseMessageContent(3, this.msg.message_content);
			if (typeof p === 'string') return p;
			if (p && typeof p === 'object' && p.url) return p.url;
			return '';
		},
		systemNinePlainText() {
			const c = this.msg.message_content;
			if (c == null) return '';
			if (typeof c === 'object') return JSON.stringify(c);
			return String(c);
		},
		registerCardDrugRows() {
			if (this.msg.message_type !== 10) return [];
			const pc = this.parsedObj;
			if (!pc || typeof pc !== 'object') return [];
			const fallbackQty = pc.number != null && pc.number !== '' ? Number(pc.number) : 1;
			const arr = pc.selected_western_drugs;
			if (Array.isArray(arr) && arr.length) {
				return withWxKey(
					arr.map((d) => {
						const q = d && d.quantity != null ? Number(d.quantity) : fallbackQty;
						return {
							name: (d && d.name) || '',
							specification: (d && (d.specification || d.spec || d.drug_spec)) || '',
							image: (d && (d.image || d.drug_image)) || '',
							quantity: q >= 1 ? q : 1,
							id: d && (d.drug_id || d.id),
						};
					}),
					'id',
					'rd'
				);
			}
			if (pc.drug && pc.drug.name) {
				return withWxKey(
					[
						{
							name: pc.drug.name,
							specification: pc.drug.specification || pc.drug.spec || '',
							image: pc.drug.image || pc.drug.drug_image || '',
							quantity: fallbackQty >= 1 ? fallbackQty : 1,
							id: pc.drug.drug_id || pc.drug.id,
						},
					],
					'id',
					'rd'
				);
			}
			return [];
		},
		registerCardDrugNamesLine() {
			return this.registerCardDrugRows.map((r) => r.name).filter(Boolean).join('、');
		},
		followUpAnsweredLabel() {
			const pc = this.parsedObj;
			if (!pc || pc.flow !== 'follow_up_drug') return '';
			const st = pc.answer_status;
			if (st === 'yes' || st === '1') return '是，曾使用过';
			if (st === 'no' || st === '0') return '否，未使用过';
			return '';
		},
		followUpDrugs() {
			const drugs = (this.parsedObj && this.parsedObj.drugs) || [];
			return withWxKey(
				drugs.map((d) => ({
					...d,
					specification: d.specification || d.spec || d.drug_spec || '',
				})),
				'id',
				'fd'
			);
		},
		transferQuestionsWithKey() {
			const qs = (this.parsedObj && this.parsedObj.questions) || [];
			return withWxKey(qs, 'id', 'tq');
		},
		experienceRxPayload() {
			const pc = this.parsedObj;
			if (!pc || this.msg.message_type !== 11) return {};
			return {
				drug_name: pc.drug_name || pc.name,
				drug_id: pc.drug_id != null ? pc.drug_id : pc.id
			};
		},
		unknownText() {
			const c = this.msg.message_content;
			if (c == null) return '[消息]';
			if (typeof c === 'object') return '[卡片消息]';
			const s = String(c);
			return s.length > 120 ? s.slice(0, 120) + '…' : s;
		}
	},
	methods: {
		getAudioWidth(duration) {
			const min = 120;
			const max = 350;
			const unit = 12;
			let w = min + (parseInt(duration, 10) || 0) * unit;
			return Math.min(w, max) + 'rpx';
		},
		getStatusText(status) {
			const map = { 0: '待审核', 1: '已审核', 2: '未通过' };
			return map[status] || '状态未知';
		},
		getRegisterStatusText(status) {
			const map = { 0: '待就诊', 1: '已缴费', 2: '已就诊', 3: '已取消', 4: '已退费' };
			return map[status] || '状态未知';
		}
	}
};
</script>

<style lang="scss" scoped>
$primary: #0a84ff;
$bg-mine: #0a84ff;
$bg-other: #ffffff;
$text-main: #333333;
$text-sub: #666666;
$radius-bubble: 12rpx;

.bubble-container {
	display: flex;
	align-items: flex-start;
	margin-bottom: 30rpx;
	width: 100%;

	.avatar {
		width: 72rpx;
		height: 72rpx;
		border-radius: 10rpx;
		flex-shrink: 0;
		background: #f2f2f2;
	}

	.content-wrapper {
		display: flex;
		flex-direction: column;
		max-width: 72%;
	}

	&.other {
		flex-direction: row;
		.avatar {
			margin-right: 16rpx;
		}
		.message-bubble {
			background-color: $bg-other;
			color: $text-main;
			border-radius: 4rpx $radius-bubble $radius-bubble $radius-bubble;
			&::before {
				content: '';
				position: absolute;
				top: 20rpx;
				left: -10rpx;
				width: 0;
				height: 0;
				border-top: 10rpx solid transparent;
				border-bottom: 10rpx solid transparent;
				border-right: 12rpx solid $bg-other;
			}
			&.no-padding::before {
				display: none;
			}
		}
	}

	&.mine {
		flex-direction: row-reverse;
		.avatar {
			margin-left: 16rpx;
		}
		.message-bubble {
			background-color: $bg-mine;
			color: #fff;
			border-radius: $radius-bubble 4rpx $radius-bubble $radius-bubble;
			&::after {
				content: '';
				position: absolute;
				top: 20rpx;
				right: -10rpx;
				width: 0;
				height: 0;
				border-top: 10rpx solid transparent;
				border-bottom: 10rpx solid transparent;
				border-left: 12rpx solid $bg-mine;
			}
			&.no-padding::after {
				display: none;
			}
		}
	}
}

.message-bubble {
	padding: 18rpx 24rpx;
	font-size: 30rpx;
	line-height: 1.5;
	position: relative;
	word-break: break-all;
	box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.05);
	min-height: 72rpx;
	display: flex;
	align-items: center;

	.text-content {
		color: inherit;
	}
	&.mine.type-0 .text-content {
		color: #fff;
	}

	&.no-padding {
		padding: 0;
		background: transparent !important;
		box-shadow: none;
		&::before,
		&::after {
			display: none;
		}
	}
}

.media-content {
	border-radius: 8rpx;
	&.image {
		max-width: 300rpx;
		display: block;
	}
	&.video {
		width: 300rpx;
		height: 170rpx;
	}
}

.audio-content {
	display: flex;
	align-items: center;
	justify-content: space-between;
	.duration {
		font-size: 26rpx;
		white-space: nowrap;
	}
	.voice-icon-wrap {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 44rpx;
		height: 44rpx;
		&.other {
			margin-right: 6rpx;
		}
		&.mine {
			margin-left: 6rpx;
			transform: rotate(180deg);
		}
		&.playing {
			animation: voice-pulse 1.2s infinite ease-in-out;
		}
	}
}

@keyframes voice-pulse {
	0% {
		opacity: 1;
		transform: scale(1) rotate(var(--rotate-angle, 0deg));
	}
	50% {
		opacity: 0.4;
		transform: scale(0.92) rotate(var(--rotate-angle, 0deg));
	}
	100% {
		opacity: 1;
		transform: scale(1) rotate(var(--rotate-angle, 0deg));
	}
}
.voice-icon-wrap.mine.playing {
	--rotate-angle: 180deg;
	animation: voice-pulse 1.2s infinite ease-in-out;
}
.voice-icon-wrap.other.playing {
	--rotate-angle: 0deg;
	animation: voice-pulse 1.2s infinite ease-in-out;
}

.card-content {
	background: #fff;
	border-radius: 16rpx;
	overflow: hidden;
	border: 1rpx solid #eee;
	width: 480rpx;

	.card-header {
		padding: 16rpx 20rpx;
		display: flex;
		justify-content: space-between;
		align-items: center;
		border-bottom: 1rpx solid #f9f9f9;
		&.bg-green {
			background: #f0fdf4;
		}
		&.bg-blue {
			background: #eff6ff;
		}
		&.bg-gray {
			background: #f8fafc;
		}
		.title-group {
			display: flex;
			align-items: center;
			gap: 8rpx;
			.card-title {
				font-size: 26rpx;
				font-weight: 600;
				color: #333;
			}
		}
		.status-tag {
			font-size: 20rpx;
			padding: 2rpx 10rpx;
			border-radius: 6rpx;
			background: #fff;
			color: $text-sub;
			border: 1rpx solid rgba(0, 0, 0, 0.05);
			&.blue {
				color: $primary;
				border-color: rgba(10, 132, 255, 0.2);
			}
		}
	}

	.card-body {
		padding: 20rpx;
		display: flex;
		flex-direction: column;
		gap: 12rpx;
		.info-row {
			display: flex;
			justify-content: space-between;
			font-size: 24rpx;
			.label {
				color: #888;
			}
			.value {
				color: #333;
				font-weight: 500;
				text-align: right;
				max-width: 70%;
			}
			.order-font {
				font-family: Courier, monospace;
				letter-spacing: 0.5rpx;
			}
			.price {
				color: #ef4444;
				font-size: 28rpx;
				font-weight: bold;
			}
			.small {
				font-size: 22rpx;
				color: #999;
			}
		}
		.drug-spec-row {
			align-items: flex-start;
			.drug-thumb {
				width: 64rpx;
				height: 64rpx;
				border-radius: 8rpx;
				background: #f3f4f6;
				flex-shrink: 0;
				margin-right: 12rpx;
			}
			.drug-name-wrap {
				display: flex;
				flex-direction: column;
				align-items: flex-start;
				gap: 4rpx;
				flex: 1;
				min-width: 0;
			}
			.spec-text {
				display: block;
				font-size: 22rpx;
				color: #9ca3af;
				font-weight: 400;
				text-align: left;
			}
		}
		.drug-list-block {
			.block-label {
				display: block;
				font-size: 22rpx;
				color: #888;
				margin-bottom: 8rpx;
			}
		}
		.desc-text {
			font-size: 26rpx;
			color: #333;
		}
		.text-block {
			background: #f5f5f5;
			padding: 16rpx;
			border-radius: 8rpx;
			.block-label {
				display: block;
				font-size: 22rpx;
				color: #999;
				margin-bottom: 6rpx;
			}
			.block-content {
				font-size: 26rpx;
				color: #333;
				line-height: 1.4;
			}
		}
	}

	.card-footer {
		padding: 16rpx 20rpx;
		border-top: 1rpx solid #f0f0f0;
		&.card-footer--compact {
			padding: 12rpx 20rpx;
		}
		.action-btn {
			width: 100%;
			height: 60rpx;
			line-height: 60rpx;
			font-size: 26rpx;
			border-radius: 30rpx;
			background: $primary;
			color: #fff;
			border: none;
			&::after {
				border: none;
			}
			&.action-btn--ghost {
				background: #f0fdf4;
				color: #059669;
				border: 1rpx solid #bbf7d0;
			}
		}
	}
}

.service-notify-card {
	background: #ffffff;
	border-radius: 12rpx;
	width: 480rpx;
	border: 1rpx solid #eaeaea;
	overflow: hidden;
	.sn-header {
		padding: 24rpx 24rpx 16rpx 24rpx;
		border-bottom: 1rpx solid #f5f5f5;
		.sn-title {
			font-size: 30rpx;
			font-weight: 600;
			color: #333;
		}
	}
	.sn-body {
		padding: 20rpx 24rpx;
		display: flex;
		flex-direction: column;
		gap: 16rpx;
		.sn-row {
			display: flex;
			justify-content: space-between;
			align-items: flex-start;
			line-height: 1.4;
			.sn-label {
				font-size: 26rpx;
				color: #999;
				min-width: 110rpx;
			}
			.sn-value {
				font-size: 26rpx;
				color: #333;
				text-align: right;
				flex: 1;
				&.truncate {
					white-space: nowrap;
					overflow: hidden;
					text-overflow: ellipsis;
					max-width: 320rpx;
				}
				&.price {
					font-weight: 600;
					font-size: 28rpx;
				}
				&.sub {
					color: #999;
					font-family: monospace;
				}
				&.strong {
					font-weight: bold;
					font-size: 30rpx;
				}
				&.color-orange {
					color: #fa8c16;
				}
				&.color-green {
					color: #52c41a;
				}
			}
			.sn-value-group {
				display: flex;
				align-items: center;
				justify-content: flex-end;
				.old {
					color: #999;
					text-decoration: line-through;
					font-size: 24rpx;
				}
				.new {
					color: #333;
					font-weight: 600;
					font-size: 26rpx;
				}
			}
		}
	}
}

.system-inner {
	background: rgba(0, 0, 0, 0.05);
	padding: 8rpx 20rpx;
	border-radius: 10rpx;
	font-size: 22rpx;
	color: #999;
	align-self: center;
	margin: 0 auto;
}

.follow-up-pending-readonly {
	margin-top: 12rpx;
	padding: 16rpx 20rpx;
	background: #f7f8fa;
	border-radius: 12rpx;
	.follow-up-pending-tip {
		font-size: 24rpx;
		color: #909399;
		line-height: 1.5;
	}
}

.transfer-readonly {
	background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);
	border-radius: 16rpx;
	border: 2rpx solid #fed7aa;
	padding: 20rpx;
	width: 100%;
	box-sizing: border-box;
}
.transfer-r-head {
	display: flex;
	align-items: center;
	gap: 12rpx;
	padding-bottom: 16rpx;
	margin-bottom: 12rpx;
	border-bottom: 2rpx solid #fed7aa;
}
.transfer-r-title {
	font-size: 30rpx;
	font-weight: 600;
	color: #1e293b;
}
.transfer-r-body {
	font-size: 26rpx;
	color: #334155;
}
.transfer-r-row {
	display: flex;
	margin-bottom: 12rpx;
	line-height: 1.5;
}
.transfer-r-k {
	color: #64748b;
	width: 160rpx;
	flex-shrink: 0;
}
.transfer-r-v {
	flex: 1;
	color: #1e293b;
}
.transfer-qa {
	margin-top: 16rpx;
	padding: 16rpx;
	background: rgba(255, 255, 255, 0.65);
	border-radius: 12rpx;
	border: 1rpx solid #fed7aa;
}
.transfer-qa-title {
	font-size: 28rpx;
	font-weight: 600;
	color: #1e293b;
	display: block;
	margin-bottom: 12rpx;
}
.transfer-qa-item {
	margin-bottom: 12rpx;
	padding: 12rpx;
	background: #fff;
	border-radius: 8rpx;
}
.transfer-qa-q {
	display: block;
	font-size: 26rpx;
	color: #334155;
	margin-bottom: 8rpx;
}
.transfer-qa-a {
	font-size: 24rpx;
	color: #0a84ff;
}
.transfer-r-foot {
	margin-top: 16rpx;
	padding-top: 12rpx;
	border-top: 2rpx solid #fed7aa;
}
.transfer-r-status {
	font-size: 26rpx;
	color: #64748b;
	&.ok {
		color: #16a34a;
	}
	&.no {
		color: #dc2626;
	}
}
</style>
