|
|
@@ -0,0 +1,219 @@
|
|
|
+<template>
|
|
|
+ <el-drawer v-model="drawerVisible" title="用户档案详情" size="60%" destroy-on-close>
|
|
|
+ <div class="profile-header">
|
|
|
+ <el-avatar :size="80" :src="currentUser.avatarUrl" />
|
|
|
+ <div class="profile-basic">
|
|
|
+ <div class="name-row">
|
|
|
+ <span class="name">{{ currentUser.name }}</span>
|
|
|
+ <dict-tag :options="sys_user_sex" :value="currentUser.gender" />
|
|
|
+ <span class="phone">{{ currentUser.phone }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="tags-row" style="margin-top: 8px">
|
|
|
+ <el-tag v-for="tag in currentUser.tags" :key="tag.id" :type="tag.colorType || 'info'" effect="light" size="small" style="margin-right: 5px">
|
|
|
+ {{ tag.name }}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-tabs v-model="detailActiveTab" class="profile-tabs">
|
|
|
+ <el-tab-pane label="档案信息" name="info">
|
|
|
+ <div class="section-title">基本信息</div>
|
|
|
+ <el-descriptions :column="2" border>
|
|
|
+ <el-descriptions-item label="姓名">{{ currentUser.name }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="电话">{{ currentUser.phone }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="所属区域">{{ currentUser.areaName || '-' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="所属站点">{{ currentUser.stationName || '-' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="录入来源">{{ currentUser.source || '-' }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="录入时间">{{ currentUser.createTime || '-' }}</el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+
|
|
|
+ <div class="section-title" style="margin-top: 20px">居住信息</div>
|
|
|
+ <el-descriptions :column="2" border>
|
|
|
+ <el-descriptions-item label="详细住址" :span="2">{{ currentUser.address }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="房屋类型">
|
|
|
+ <dict-tag :options="sys_house_type" :value="currentUser.houseType" />
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item label="入门方式">
|
|
|
+ <dict-tag :options="sys_entry_method" :value="currentUser.entryMethod" />
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item label="开门详情" :span="2">
|
|
|
+ {{ currentUser.entryMethod === 'password' ? currentUser.entryPassword : currentUser.keyLocation }}
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <el-tab-pane label="宠物列表" name="pets">
|
|
|
+ <el-table :data="currentPets" border style="width: 100%">
|
|
|
+ <el-table-column label="宠物信息" width="200">
|
|
|
+ <template #default="scope">
|
|
|
+ <div style="display: flex; align-items: center;">
|
|
|
+ <el-avatar :size="30" src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" style="margin-right: 8px;" />
|
|
|
+ {{ scope.row.name }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="breed" label="品种" />
|
|
|
+ <el-table-column prop="gender" label="性别" width="60" />
|
|
|
+ <el-table-column prop="age" label="年龄" width="60" />
|
|
|
+ <el-table-column prop="status" label="健康状态">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag :type="scope.row.status === '健康' ? 'success' : 'warning'" size="small">{{ scope.row.status }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="疫苗接种" width="120" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.vaccine || '-' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <el-tab-pane label="历史订单" name="orders">
|
|
|
+ <el-table :data="mockOrders" border style="width: 100%">
|
|
|
+ <el-table-column prop="orderNo" label="订单编号" width="180" />
|
|
|
+ <el-table-column prop="service" label="服务项目" />
|
|
|
+ <el-table-column prop="pets" label="服务宠物" />
|
|
|
+ <el-table-column prop="time" label="服务时间" width="180" />
|
|
|
+ <el-table-column prop="status" label="状态" width="100">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag type="success" size="small">完成</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <el-tab-pane label="档案日志" name="logs">
|
|
|
+ <el-timeline style="margin-top: 10px; padding-left: 5px;">
|
|
|
+ <el-timeline-item
|
|
|
+ v-for="(log, index) in changeLogs"
|
|
|
+ :key="index"
|
|
|
+ :timestamp="log.createTime"
|
|
|
+ type="primary"
|
|
|
+ >
|
|
|
+ [{{ log.logType }}] {{ log.content }}
|
|
|
+ <div style="font-size: 12px; color: #999; margin-top: 4px">操作人: {{ log.operatorName }}</div>
|
|
|
+ </el-timeline-item>
|
|
|
+ </el-timeline>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </el-drawer>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, getCurrentInstance, toRefs } from 'vue'
|
|
|
+import { getCustomer } from '@/api/archieves/customer'
|
|
|
+import { listPetByUser } from '@/api/archieves/pet'
|
|
|
+import { listAllChangeLog } from '@/api/archieves/changeLog'
|
|
|
+import { listOnStore } from '@/api/system/areaStation'
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ visible: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ customerId: {
|
|
|
+ type: [String, Number],
|
|
|
+ default: null
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+const emit = defineEmits(['update:visible'])
|
|
|
+
|
|
|
+const drawerVisible = computed({
|
|
|
+ get: () => props.visible,
|
|
|
+ set: (val) => emit('update:visible', val)
|
|
|
+})
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance()
|
|
|
+const { sys_user_sex, sys_house_type, sys_entry_method } = toRefs(
|
|
|
+ proxy?.useDict('sys_user_sex', 'sys_house_type', 'sys_entry_method')
|
|
|
+)
|
|
|
+
|
|
|
+const currentUser = ref({})
|
|
|
+const currentPets = ref([])
|
|
|
+const changeLogs = ref([])
|
|
|
+const detailActiveTab = ref('info')
|
|
|
+const allNodes = ref([])
|
|
|
+
|
|
|
+const mockOrders = ref([
|
|
|
+ { orderNo: 'DD20231001001', service: '上门喂养 (标准版)', pets: '旺财', time: '2023-10-01 10:00', amount: '88.00', status: 'completed' },
|
|
|
+ { orderNo: 'DD20230915002', service: '深度洗护套餐', pets: '旺财, 咪咪', time: '2023-09-15 14:00', amount: '158.00', status: 'completed' }
|
|
|
+])
|
|
|
+
|
|
|
+const loadAreaStation = async () => {
|
|
|
+ if(allNodes.value.length === 0) {
|
|
|
+ const res = await listOnStore()
|
|
|
+ allNodes.value = res.data || []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+watch(() => props.visible, async (val) => {
|
|
|
+ if (val && props.customerId) {
|
|
|
+ detailActiveTab.value = 'info'
|
|
|
+ currentUser.value = {}
|
|
|
+ currentPets.value = []
|
|
|
+ changeLogs.value = []
|
|
|
+
|
|
|
+ await loadAreaStation()
|
|
|
+ getCustomer(props.customerId).then((res) => {
|
|
|
+ const data = res.data
|
|
|
+ if (data.areaId) {
|
|
|
+ const area = allNodes.value.find(n => n.id === data.areaId)
|
|
|
+ data.areaName = area ? area.name : '-'
|
|
|
+ } else {
|
|
|
+ data.areaName = '-'
|
|
|
+ }
|
|
|
+ if (data.stationId) {
|
|
|
+ const station = allNodes.value.find(n => n.id === data.stationId)
|
|
|
+ data.stationName = station ? station.name : '-'
|
|
|
+ } else {
|
|
|
+ data.stationName = '-'
|
|
|
+ }
|
|
|
+ currentUser.value = data
|
|
|
+ })
|
|
|
+
|
|
|
+ listPetByUser(props.customerId).then((res) => {
|
|
|
+ currentPets.value = res.data || []
|
|
|
+ })
|
|
|
+
|
|
|
+ listAllChangeLog(props.customerId, 'customer').then((res) => {
|
|
|
+ changeLogs.value = res.data || []
|
|
|
+ })
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.profile-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding-bottom: 20px;
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
+}
|
|
|
+.profile-basic {
|
|
|
+ margin-left: 20px;
|
|
|
+}
|
|
|
+.name-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.name {
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #303133;
|
|
|
+}
|
|
|
+.phone {
|
|
|
+ margin-left: 10px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+.section-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ border-left: 4px solid #409eff;
|
|
|
+ padding-left: 10px;
|
|
|
+ line-height: 1.2;
|
|
|
+}
|
|
|
+</style>
|