| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- <template>
- <el-drawer
- v-model="drawerVisible"
- title="宠物护理工作小结"
- direction="rtl"
- size="750px"
- destroy-on-close
- class="care-summary-drawer"
- >
- <div class="care-summary-container" v-if="order">
- <!-- Pet Header -->
- <div class="summary-header">
- <div class="avatar-wrapper">
- <el-avatar :size="80" :src="order.petAvatar" shape="circle" class="pet-summary-avatar">{{ order.petName?.charAt(0) }}</el-avatar>
- </div>
- <div class="pet-summary-info">
- <div class="summary-name-row">
- <span class="name">{{ order.petName }}</span>
- <div class="tags-group">
- <el-tag :type="order.petGender==='male'?'':'danger'" effect="light" round>
- <el-icon><component :is="order.petGender==='male'?'Male':'Female'" /></el-icon>
- {{ order.petAge }}
- </el-tag>
- <el-tag v-for="tag in (order.petTags||[])" :key="tag" type="warning" effect="plain" round>{{ formatTag(tag) }}</el-tag>
- </div>
- </div>
- <div class="summary-sub-row">
- <div class="info-item">
- <span class="lbl">品种</span>
- <span class="val">{{ order.petBreed || '未知' }}</span>
- </div>
- <div class="divider-v"></div>
- <div class="info-item">
- <span class="lbl">体重</span>
- <span class="val">{{ order.petWeight }}</span>
- </div>
- <div class="divider-v"></div>
- <div class="info-item">
- <span class="lbl">主人</span>
- <span class="val">{{ order.userName || '未知' }}</span>
- </div>
- </div>
- </div>
- </div>
- <!-- Info Groups -->
- <div class="summary-section">
- <div class="sec-title">
- <span class="icon-box"><el-icon><List /></el-icon></span>
- 基本信息
- </div>
- <el-descriptions :column="2" border class="spacious-desc">
- <el-descriptions-item label="性格关键词">{{ order.petPersonality }}</el-descriptions-item>
- <el-descriptions-item label="健康状况">
- <el-tag :type="order.healthStatus==='健康'?'success':'danger'" effect="light" size="small">{{ order.healthStatus }}</el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="疫苗情况">
- <div class="flex-align">
- <span style="color:#67c23a; margin-right:8px;" v-if="order.vaccineImg"><el-icon><CircleCheckFilled /></el-icon> 已接种</span>
- <span v-else style="color:#909399;">未接种</span>
- <el-image
- v-if="order.vaccineImg"
- style="width: 24px; height: 24px; border-radius:4px; vertical-align:middle; cursor:zoom-in;"
- :src="order.vaccineImg"
- :preview-src-list="[order.vaccineImg]"
- :preview-teleported="true"
- />
- </div>
- </el-descriptions-item>
- <el-descriptions-item label="过敏史">
- <span :style="{color: order.allergy ? '#f56c6c' : 'inherit'}">{{ order.allergy || '无' }}</span>
- </el-descriptions-item>
- </el-descriptions>
- </div>
- <div class="summary-section">
- <div class="sec-title">
- <span class="icon-box text-blue"><el-icon><HomeFilled /></el-icon></span>
- 服务环境
- </div>
- <el-descriptions :column="2" border class="spacious-desc">
- <el-descriptions-item label="到家时间">{{ order.homeTime }}</el-descriptions-item>
- <el-descriptions-item label="房屋类型">{{ order.houseType }}</el-descriptions-item>
- <el-descriptions-item label="入户方式" :span="2">
- <span style="font-weight:bold;">{{ order.entryMethod }}</span>
- <span style="margin-left:8px; color:#909399;">({{ order.entryDetail }})</span>
- </el-descriptions-item>
- </el-descriptions>
- </div>
- <!-- Service Log -->
- <div class="summary-section main-log">
- <div class="sec-title" style="border:none; padding-left:0; margin-bottom:16px;">
- <div class="left">
- <span class="icon-box text-orange"><el-icon><Notebook /></el-icon></span>
- 服务内容记录
- </div>
- <el-button v-if="!isEditingSummary" type="primary" link icon="Edit" @click="isEditingSummary = true">编辑</el-button>
- </div>
-
- <div v-if="isEditingSummary" class="edit-area">
- <el-input
- v-model="careSummaryText"
- type="textarea"
- :rows="12"
- placeholder="请输入详细的护理服务小结..."
- resize="none"
- />
- <div class="edit-actions">
- <el-button @click="isEditingSummary = false">取消</el-button>
- <el-button type="primary" @click="saveCareSummary">保存内容</el-button>
- </div>
- </div>
- <div v-else class="log-content-box">
- <pre class="log-text">{{ careSummaryText }}</pre>
- </div>
- </div>
-
- <!-- Footer Info -->
- <div class="summary-footer">
- <div class="footer-info">
- <div class="f-row">
- <span class="lbl">护宠师</span>
- <span class="val user-active">{{ order.fulfillerName || '当前履约者' }}</span>
- </div>
- <div class="f-row">
- <span class="lbl">提交时间</span>
- <span class="val">{{ order.summaryTime || '2024-02-04 17:00' }}</span>
- </div>
- </div>
- <div class="footer-action">
- <el-button size="large" @click="drawerVisible = false">关闭</el-button>
- </div>
- </div>
- </div>
- </el-drawer>
- </template>
- <script setup>
- import { ref, computed, watch } from 'vue'
- const props = defineProps({
- visible: Boolean,
- order: Object
- })
- const emit = defineEmits(['update:visible', 'submit'])
- const drawerVisible = computed({
- get: () => props.visible,
- set: (val) => emit('update:visible', val)
- })
- const careSummaryText = ref('')
- const isEditingSummary = ref(false)
- watch(() => props.visible, (val) => {
- if (val && props.order) {
- isEditingSummary.value = false
- if (!props.order.careSummary) {
- careSummaryText.value = `1. 精神/身体状态:${props.order.petName}精神状态良好,愿意互动。
- 2. 进食/饮水:食欲正常,饮水适当,已清洗碗具。
- 3. 排泄情况:排便正常,颜色形状正常,已清理。
- 4. 卫生情况:猫砂盆/地面已清理干净,无异味。
- 5. 互动情况:陪玩了20分钟,${props.order.petName}很开心。
- 6. 特殊情况/备注:无特殊异常。`
- } else {
- careSummaryText.value = props.order.careSummary
- }
- }
- })
- const saveCareSummary = () => {
- emit('submit', careSummaryText.value)
- isEditingSummary.value = false
- }
- const formatTag = (tag) => {
- if (!tag) return '';
- if (typeof tag === 'string') {
- try {
- const obj = JSON.parse(tag);
- return typeof obj === 'object' ? (obj.name || tag) : obj;
- } catch (e) {
- return tag;
- }
- }
- return tag.name || tag;
- }
- </script>
- <style scoped>
- /* Enhanced Care Summary Styles */
- .care-summary-drawer :deep(.el-drawer__header) { margin-bottom: 0; padding: 20px 24px; border-bottom: 1px solid #f0f0f0; }
- .care-summary-drawer :deep(.el-drawer__body) { padding: 0; overflow-y: auto; background: #fff; }
- .care-summary-container { padding: 32px 40px; }
- /* 1. Header */
- .summary-header { display: flex; gap: 24px; align-items: flex-start; margin-bottom: 32px; padding-bottom: 24px; border-bottom: 1px dashed #e4e7ed; }
- .avatar-wrapper { border: 4px solid #f2f6fc; border-radius: 50%; }
- .pet-summary-info { flex: 1; display:flex; flex-direction:column; gap:12px; padding-top: 4px; }
- .summary-name-row { display: flex; align-items: center; gap: 16px; margin-bottom: 4px; }
- .summary-name-row .name { font-size: 24px; font-weight: 800; color: #303133; letter-spacing: 0.5px; }
- .tags-group { display: flex; gap: 8px; align-items: center; }
- .summary-sub-row { display: flex; align-items: center; background: #f9fafe; padding: 10px 16px; border-radius: 8px; align-self: flex-start; }
- .info-item { display: flex; flex-direction: column; gap: 2px; }
- .info-item .lbl { font-size: 11px; color: #909399; text-transform: uppercase; }
- .info-item .val { font-size: 14px; font-weight: bold; color: #606266; }
- .divider-v { width: 1px; height: 24px; background: #ebeef5; margin: 0 16px; }
- /* 2. Sections */
- .summary-section { margin-bottom: 40px; }
- .sec-title {
- font-size: 16px; font-weight: 700; color: #303133; margin-bottom: 16px;
- display:flex; align-items:center; gap:8px;
- justify-content: space-between;
- }
- .sec-title .left { display: flex; align-items: center; gap: 8px; }
- .icon-box {
- width: 28px; height: 28px; background: #ecf5ff; color: #409eff; border-radius: 6px;
- display: flex; align-items: center; justify-content: center; font-size: 16px;
- }
- .icon-box.text-blue { background: #ecf5ff; color: #409eff; }
- .icon-box.text-orange { background: #fdf6ec; color: #e6a23c; }
- /* 3. Descriptions */
- .spacious-desc :deep(.el-descriptions__cell) { padding: 12px 16px!important; }
- .spacious-desc :deep(.el-descriptions__label) { width: 100px; color: #606266; font-weight: 500; background: #fafafa; }
- .flex-align { display: flex; align-items: center; }
- /* 4. Log Area */
- .main-log { background: #fff; }
- .log-content-box {
- background: #fff;
- border: 1px solid #ebeef5; border-radius: 8px;
- padding: 24px;
- box-shadow: 0 2px 12px rgba(0,0,0,0.02);
- position: relative;
- }
- .log-content-box::before {
- content: ''; position: absolute; top: 0; left: 0; width: 4px; height: 100%; background: #e6a23c; border-top-left-radius: 8px; border-bottom-left-radius: 8px;
- }
- .log-text {
- white-space: pre-wrap; font-family: 'Inter', system-ui, sans-serif; margin: 0; line-height: 1.8; font-size: 15px; color: #303133; text-align: justify;
- }
- .edit-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 12px; }
- /* 5. Footer */
- .summary-footer {
- margin-top: 60px; padding-top: 24px; border-top: 1px solid #ebeef5;
- display: flex; justify-content: space-between; align-items: center;
- }
- .footer-info { display: flex; gap: 32px; }
- .f-row { display: flex; flex-direction: column; gap: 4px; }
- .f-row .lbl { font-size: 12px; color: #909399; }
- .f-row .val { font-size: 15px; font-weight: 600; color: #303133; }
- .f-row .val.user-active { color: #409eff; }
- </style>
|