|
@@ -1,148 +1,381 @@
|
|
|
<template>
|
|
|
+ <div style="background-color: #f0f2f5; padding-bottom: 20px; min-height: 100%;">
|
|
|
+ <!-- 客户详情 -->
|
|
|
+ <div v-if="showDetail">
|
|
|
+ <div style="padding: 20px; background-color: #fff;">
|
|
|
+ 客户详情
|
|
|
+ </div>
|
|
|
|
|
|
- <div style="background-color: #f0f2f5; padding-bottom: 20px; min-height: 100%; " >
|
|
|
- <div style="padding: 20px; background-color: #fff;">
|
|
|
- 用户详情
|
|
|
- </div>
|
|
|
+ <!-- 用户头像 -->
|
|
|
+ <div style="padding: 20px 10px 0 10px;background-image: linear-gradient(to right, #e0edff, #dfe0fe)">
|
|
|
+ <div style="padding: 20px 10px 0 10px;background-image: linear-gradient(to right, #edf5ff, #ecedff);display: flex;border-radius: 8px;">
|
|
|
+ <div style="padding: 10px">
|
|
|
+ <el-avatar :size="50" :src="qwUserInfo.avatar"/>
|
|
|
+ </div>
|
|
|
+ <div style="padding: 10px;display: flex;flex-direction: column;align-items: flex-start;justify-content: center;">
|
|
|
+ <div>
|
|
|
+ <span style="font-size: 16px;">{{qwUserInfo.name}}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span style="font-size: 14px;color: #8c939d">备注:{{qwUserInfo.remark}}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="contentx">
|
|
|
- <div class="desct">
|
|
|
- 基本信息
|
|
|
+ <!-- 基本信息 -->
|
|
|
+ <div>
|
|
|
+ <div style="display: flex;justify-content: space-between;align-items: center;flex-direction: row;background: #FFF;padding: 10px">
|
|
|
+ <div>
|
|
|
+ 基本信息
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <el-button size="mini" round @click="updateQwDetail">修改用户信息</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="background: #FFF; padding: 0 10px 10px 20px;color: #8c939d">
|
|
|
+ <el-row>
|
|
|
+ <span style="font-size: 14px;">性别:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.sex || '未知'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">年龄:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.age || '未知'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">行为习惯:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.habits || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">患病时间:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.illnessTime || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">疾病:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.disease || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">家人的疾病:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.familyDisease || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">是否线下就诊:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.isLine || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">体质:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.constitution || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">使用药品:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.medicine || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">咨询产品:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.consultProduct || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ <el-row style="margin-top: 10px">
|
|
|
+ <span style="font-size: 14px;">是否已经购买产品:</span>
|
|
|
+ <span style="font-size: 14px;margin-left: 10px">{{qwUserDetail.isBuy || '无'}}</span>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <el-descriptions title="" :column="3" border>
|
|
|
-
|
|
|
- <el-descriptions-item label="会员id" >
|
|
|
- <span>{{item.userId}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="用户昵称" >
|
|
|
- <span>{{item.nickname}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="用户头像" >
|
|
|
- <el-image v-if="item.avatar!=null"
|
|
|
- style="width: 50px;"
|
|
|
- :src="item.avatar">
|
|
|
- </el-image>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="手机号码" >
|
|
|
- <span>{{item.phone}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="用户积分" >
|
|
|
- <span>{{item.integral}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="状态" >
|
|
|
- <span>
|
|
|
- <dict-tag :options="userOptions" :value="item.status"/>
|
|
|
- </span>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="上级昵称" >
|
|
|
- <span>{{item.tuiName}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="上级手机号码" >
|
|
|
- <span>{{item.tuiPhone}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="推广员关联时间" >
|
|
|
- <span>{{item.tuiTime}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="下级人数" >
|
|
|
- <span>{{item.tuiUserCount}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="最后一次登录ip" >
|
|
|
- <span>{{item.lastIp}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="余额" >
|
|
|
- <span>{{item.balance}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="创建时间" >
|
|
|
- <span>{{item.createTime}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="更新时间" >
|
|
|
- <span>{{item.updateTime}}</span>
|
|
|
- </el-descriptions-item>
|
|
|
- </el-descriptions>
|
|
|
- </div>
|
|
|
|
|
|
- <div class="contentx" v-if="item.userId != null" >
|
|
|
- <div class="desct">
|
|
|
- 用户订单
|
|
|
+ <!-- 看课记录 -->
|
|
|
+ <div style="background-color: #FFF">
|
|
|
+ <div style="padding: 10px;">
|
|
|
+ 看课记录
|
|
|
+ </div>
|
|
|
+ <!-- 状态 -->
|
|
|
+ <div class="status-container">
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in logTypeList"
|
|
|
+ :key="index"
|
|
|
+ class="status-item"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="status-color-block"
|
|
|
+ :style="{ backgroundColor: item.color }"
|
|
|
+ ></div>
|
|
|
+ <span class="status-text">{{ item.text }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 近七天看课记录 -->
|
|
|
+ <div>
|
|
|
+ <div class="section-title">
|
|
|
+ 近七天看课记录
|
|
|
+ </div>
|
|
|
+ <div class="course-record-container">
|
|
|
+ <div
|
|
|
+ v-for="item in courseWatch7day"
|
|
|
+ :key="item.id"
|
|
|
+ class="course-record-item"
|
|
|
+ >
|
|
|
+ <span class="course-date">{{ item.date.split('-')[2] }}日</span>
|
|
|
+ <div
|
|
|
+ class="course-status-block"
|
|
|
+ :style="{ backgroundColor: getLogTypeColor(item.logType) }"
|
|
|
+ :title="getLogTypeText(item.logType)"
|
|
|
+ ></div>
|
|
|
+ </div>
|
|
|
+ <div v-if="courseWatch7day.length === 0" class="empty-record">
|
|
|
+ 暂无看课记录
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <userStorerDetails ref="userDetails" />
|
|
|
- </div>
|
|
|
|
|
|
- <div class="contentx" v-if="item.userId != null" >
|
|
|
- <div class="desct">
|
|
|
- 用户看客记录
|
|
|
+ <!-- 按钮 -->
|
|
|
+ <div>
|
|
|
+ <div style="display: flex;justify-content: space-evenly;align-items: center;flex-direction: row;background: #FFF;padding: 10px 0 20px 0">
|
|
|
+ <div>
|
|
|
+ <el-button style="width: 150px;height: 35px;background-color: #1890ff;color: #fff;border: none;
|
|
|
+ border-radius: 22px;
|
|
|
+ font-size: 12px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: background 0.2s;"
|
|
|
+ @click="courseManage">课程管理</el-button>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <el-button style="width: 150px;height: 35px;background-color: #1890ff;color: #fff;border: none;
|
|
|
+ border-radius: 22px;
|
|
|
+ font-size: 12px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: background 0.2s;"
|
|
|
+ @click="remindCourseManage">催课管理</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <userCourseWatchLog ref="userWatchLog" />
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 修改用户信息 -->
|
|
|
+ <user-info-edit
|
|
|
+ v-if="showUpdate"
|
|
|
+ :userDetail="qwUserDetail"
|
|
|
+ @back="handleBack"
|
|
|
+ @save-success="handleSaveSuccess"
|
|
|
+ />
|
|
|
+
|
|
|
+ <!-- 课程管理 -->
|
|
|
+ <course-manage
|
|
|
+ v-if="showCourseManage"
|
|
|
+ :userId="qwUserInfo.id"
|
|
|
+ @back="handleBack"
|
|
|
+ />
|
|
|
+ <!-- 催课管理 -->
|
|
|
+ <remind-course-manage
|
|
|
+ v-if="showRemindCourseManage"
|
|
|
+ :user-id="qwUserDetail.id"
|
|
|
+ @back="handleBack"
|
|
|
+ />
|
|
|
+
|
|
|
+<!-- <div class="contentx" v-if="item.userId != null" >-->
|
|
|
+<!-- <div class="desct">-->
|
|
|
+<!-- 用户订单-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- <userStorerDetails ref="userDetails" />-->
|
|
|
+<!-- </div>-->
|
|
|
+
|
|
|
+<!-- <div class="contentx" v-if="item.userId != null" >-->
|
|
|
+<!-- <div class="desct">-->
|
|
|
+<!-- 用户看客记录-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- <userCourseWatchLog ref="userWatchLog" />-->
|
|
|
+<!-- </div>-->
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import {getUserInfoBySessionId} from "@/api/users/user";
|
|
|
import userStorerDetails from "@/views/qw/qwChat/userDetail/userStorerDetails.vue"
|
|
|
import userCourseWatchLog from "@/views/qw/qwChat/userDetail/userCourseWatchLog.vue";
|
|
|
+import userInfoEdit from "@/views/qw/qwChat/userDetail/userInfoEdit.vue";
|
|
|
+import courseManage from "@/views/qw/qwChat/userDetail/courseManage.vue";
|
|
|
+import remindCourseManage from "@/views/qw/qwChat/userDetail/remindCourseManage.vue";
|
|
|
+import {getQwExternalContactDetails, getQwUserInfo, queryCourseWatchStatistics} from "@/api/qw/im";
|
|
|
|
|
|
export default {
|
|
|
name: "userDetail",
|
|
|
components: {
|
|
|
userStorerDetails,
|
|
|
- userCourseWatchLog
|
|
|
+ userCourseWatchLog,
|
|
|
+ userInfoEdit,
|
|
|
+ courseManage,
|
|
|
+ remindCourseManage
|
|
|
},
|
|
|
data() {
|
|
|
+ // 定义颜色常量
|
|
|
+ const logTypeColors = {
|
|
|
+ notWatched: '#909399', // 未看课
|
|
|
+ watching: '#0bc6ff', // 看课中
|
|
|
+ completed: '#67c23a', // 完课
|
|
|
+ pending: '#f55a4f', // 待看课
|
|
|
+ interrupted: '#ffd700' // 看课中断
|
|
|
+ };
|
|
|
+
|
|
|
return {
|
|
|
- userOptions: [],
|
|
|
- item: {},
|
|
|
+ extId: null,
|
|
|
+ qwUserInfo: {},
|
|
|
+ qwUserDetail: {},
|
|
|
+ showDetail: true,
|
|
|
+ showUpdate: false,
|
|
|
+ courseWatch7day: [],
|
|
|
+ logTypeColors,
|
|
|
+ // 定义状态列表用于渲染
|
|
|
+ logTypeList: [
|
|
|
+ { type: 0, text: '未看课', color: logTypeColors.notWatched },
|
|
|
+ { type: 1, text: '看课中', color: logTypeColors.watching },
|
|
|
+ { type: 2, text: '完课', color: logTypeColors.completed },
|
|
|
+ { type: 3, text: '待看课', color: logTypeColors.pending },
|
|
|
+ { type: 4, text: '看课中断', color: logTypeColors.interrupted }
|
|
|
+ ],
|
|
|
+ showCourseManage: false,
|
|
|
+ showRemindCourseManage: false
|
|
|
}
|
|
|
},
|
|
|
- created() {
|
|
|
- this.getDicts("sys_user_status").then(response => {
|
|
|
- this.userOptions = response.data;
|
|
|
- });
|
|
|
- },
|
|
|
methods: {
|
|
|
- getDetail(sessionId) {
|
|
|
- this.item = {}
|
|
|
- const params = {
|
|
|
- sessionId: sessionId
|
|
|
+ getDetail(extId) {
|
|
|
+ this.extId = extId
|
|
|
+ this.getQwExternalContactDetails()
|
|
|
+ this.getQwUserInfo()
|
|
|
+ this.queryCourseWatchStatistics()
|
|
|
+ },
|
|
|
+ queryCourseWatchStatistics() {
|
|
|
+ const data = {
|
|
|
+ type: 0,
|
|
|
+ qwExternalContactId: this.extId
|
|
|
+ }
|
|
|
+ queryCourseWatchStatistics(data).then(response => {
|
|
|
+ this.courseWatch7day = response.data.data
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getQwExternalContactDetails() {
|
|
|
+ const query = {
|
|
|
+ qwExternalContactId: this.extId
|
|
|
}
|
|
|
- getUserInfoBySessionId(params).then(response => {
|
|
|
- this.item = response.data;
|
|
|
- if (this.item.userId != null) {
|
|
|
- setTimeout(() => {
|
|
|
- this.$refs.userDetails.getUserDetails(this.item.userId);
|
|
|
- }, 1);
|
|
|
- setTimeout(() => {
|
|
|
- this.$refs.userWatchLog.getUserWatchLog(this.item.userId);
|
|
|
- }, 1);
|
|
|
- }
|
|
|
+ getQwExternalContactDetails(query).then(response => {
|
|
|
+ this.qwUserInfo = response.data
|
|
|
})
|
|
|
},
|
|
|
+ getQwUserInfo() {
|
|
|
+ const query = {
|
|
|
+ qwExternalContactId: this.extId
|
|
|
+ }
|
|
|
+ getQwUserInfo(query).then(response => {
|
|
|
+ this.qwUserDetail = response.moreInfo
|
|
|
+ })
|
|
|
+ },
|
|
|
+ updateQwDetail() {
|
|
|
+ this.showDetail = false
|
|
|
+ this.showUpdate = true
|
|
|
+ },
|
|
|
+ handleBack() {
|
|
|
+ this.getQwUserInfo()
|
|
|
+ this.showDetail = true
|
|
|
+ this.showUpdate = false
|
|
|
+ this.showCourseManage = false
|
|
|
+ this.showRemindCourseManage = false
|
|
|
+ },
|
|
|
+ handleSaveSuccess() {
|
|
|
+ this.handleBack()
|
|
|
+ },
|
|
|
+ getLogTypeColor(logType) {
|
|
|
+ const type = parseInt(logType);
|
|
|
+ // 使用对象映射替代switch语句
|
|
|
+ const colorMap = {
|
|
|
+ 0: this.logTypeColors.notWatched,
|
|
|
+ 1: this.logTypeColors.watching,
|
|
|
+ 2: this.logTypeColors.completed,
|
|
|
+ 3: this.logTypeColors.pending,
|
|
|
+ 4: this.logTypeColors.interrupted
|
|
|
+ };
|
|
|
+ return colorMap[type] || '';
|
|
|
+ },
|
|
|
+ getLogTypeText(logType) {
|
|
|
+ const type = parseInt(logType);
|
|
|
+ // 使用对象映射替代switch语句
|
|
|
+ const textMap = {
|
|
|
+ 0: '未看课',
|
|
|
+ 1: '看课中',
|
|
|
+ 2: '完课',
|
|
|
+ 3: '待看课',
|
|
|
+ 4: '看课中断'
|
|
|
+ };
|
|
|
+ return textMap[type] || '';
|
|
|
+ },
|
|
|
+ courseManage() {
|
|
|
+ this.showDetail = false
|
|
|
+ this.showCourseManage = true
|
|
|
+ },
|
|
|
+ remindCourseManage() {
|
|
|
+ this.showDetail = false
|
|
|
+ this.showRemindCourseManage = true
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
-<style>
|
|
|
+<style scoped>
|
|
|
+.status-container {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+ padding: 10px 0 0 20px;
|
|
|
+ color: #8c939d;
|
|
|
+}
|
|
|
+
|
|
|
+.status-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 5px;
|
|
|
+}
|
|
|
|
|
|
-.contentx{
|
|
|
- height: 100%;
|
|
|
- background-color: #fff;
|
|
|
- padding: 0px 20px 20px;
|
|
|
+.status-color-block {
|
|
|
+ border-radius: 4px;
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+}
|
|
|
|
|
|
+.status-text {
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
|
|
|
- margin: 20px;
|
|
|
+.section-title {
|
|
|
+ padding: 10px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #8c939d;
|
|
|
}
|
|
|
-.el-descriptions-item__label.is-bordered-label{
|
|
|
- font-weight: normal;
|
|
|
+
|
|
|
+.course-record-container {
|
|
|
+ display: flex;
|
|
|
+ padding: 0 10px 15px 10px;
|
|
|
+ gap: 10px;
|
|
|
+ overflow-x: auto;
|
|
|
}
|
|
|
-.el-descriptions-item__content {
|
|
|
- max-width: 150px;
|
|
|
- min-width: 100px;
|
|
|
+
|
|
|
+.course-record-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ min-width: 40px;
|
|
|
}
|
|
|
-.desct{
|
|
|
- padding-top: 20px;
|
|
|
- padding-bottom: 20px;
|
|
|
- color: #524b4a;
|
|
|
- font-weight: bold;
|
|
|
+
|
|
|
+.course-date {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #606266;
|
|
|
+ margin-bottom: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.course-status-block {
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ border-radius: 4px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-record {
|
|
|
+ width: 100%;
|
|
|
+ text-align: center;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 14px;
|
|
|
}
|
|
|
</style>
|