This commit is contained in:
xiezhijun
2021-06-08 18:52:27 +08:00
17 changed files with 657 additions and 113 deletions

View File

@ -1,8 +1,8 @@
<template>
<div class="topic_comment_item" @click="handOnClick(data)">
<div class="comment_avatar">
<el-avatar size="medium" :src="data.fromAvatar || ''">{{
data.fromName.substr(-1)
<el-avatar size="medium" :src="data.fromAvatar">{{
data.fromName && data.fromName.substr(-1)
}}</el-avatar>
</div>
<div class="comment_content">
@ -31,6 +31,7 @@ export default {
dietician: "主任营养师",
after_sale: "售后营养师",
dietician_assistant: "营养师助理",
manager: "总经理",
},
};
},

View File

@ -1,6 +1,25 @@
<template>
<div class="message_browser_wrapper">
<div class="topic_list" @scroll="handleOnScroll">
<div class="customers_list" @scroll="handleOnScroll" v-loading="cusLoading">
<div v-if="customerList && customerList.length">
<div
v-for="customer in customerList"
:key="customer.uid"
:class="`customer_item ${
customer.uid === selCusId ? 'customer_item_sel' : ''
}`"
@click="handleOnCustomerClick(customer)"
>
<el-avatar size="medium" :src="customer.avatar">
{{ customer.name && customer.name.substr(-1) }}
</el-avatar>
<span class="customer_name">
{{ customer.name }}
</span>
</div>
</div>
</div>
<div class="topic_list" v-loading="topicLoading">
<div v-if="topicList && topicList.length">
<div
v-for="topic in topicList"
@ -29,7 +48,7 @@
</div>
<div v-else class="topic_list_empty">暂无消息</div>
</div>
<div class="topic_detail">
<div class="topic_detail" v-loading="detailLoading">
<div class="topic_detail_list">
<div
class="topic_detail_title"
@ -125,7 +144,16 @@ export default {
window.removeEventListener("message", this.handleOnMessage);
},
computed: {
...mapState(["topicList", "selTopicId", "detailData"]),
...mapState([
"cusLoading",
"topicLoading",
"detailLoading",
"topicList",
"selCusId",
"selTopicId",
"detailData",
"customerList",
]),
},
methods: {
handleOnScroll({ target }) {
@ -133,7 +161,7 @@ export default {
target.clientHeight + parseInt(target.scrollTop) ===
target.scrollHeight
) {
this.fetchTopicListApi();
this.fetchCustomerListActions();
}
},
handleOnMessage({ data }) {
@ -181,6 +209,14 @@ export default {
formatDate(date) {
return dayjs(date).format("MM-DD HH:mm");
},
handleOnCustomerClick(data) {
if (this.selCusId !== data.uid) {
this.replyTarget = "";
this.replyContent = "";
this.replyObj = {};
this.fetchTopicListApi({ fromUid: data.uid });
}
},
handleOnTopicClick(data) {
if (data.topicId !== this.selTopicId) {
this.replyTarget = "";
@ -242,6 +278,7 @@ export default {
"fetchTopicDetailActions",
"postTopicReplyActions",
"fetchTopicListApi",
"fetchCustomerListActions",
]),
...mapMutations(["clean", "save"]),
...globalMapActions(["updateUnreadCount"]),
@ -251,13 +288,40 @@ export default {
<style lang="scss" scoped>
.message_browser_wrapper {
display: flex;
.customers_list {
flex: 1;
overflow: auto;
border-right: 1px solid #f0f0f0;
.customer_item {
padding: 8px 12px;
cursor: pointer;
display: flex;
align-items: center;
&:hover {
background: #dedede;
}
.customer_name {
margin-left: 8px;
}
}
.customer_item_sel {
background: #f0f0f0;
}
}
.topic_list {
flex: 2;
overflow: auto;
border-right: 1px solid #f0f0f0;
.topic_item {
display: flex;
padding: 8px 16px;
padding: 8px 12px;
cursor: pointer;
&:hover {
@ -318,7 +382,7 @@ export default {
}
.topic_item_sel {
background: #dedede;
background: #f0f0f0;
}
.topic_list_empty {
@ -353,6 +417,13 @@ export default {
.topic_detail_title {
display: flex;
cursor: pointer;
& > :nth-child(1) {
flex: 0 0 40px;
}
& > :nth-child(2) {
flex: 1 0 0;
}
}
.comment_reply_item {

View File

@ -1,38 +1,98 @@
<template>
<div v-loading="healthDataLoading">
<HealthyView
dev
:data="healthyDataType === 0 ? healthyData : {}"
v-show="healthyDataType === 0"
/>
<BodySignView
dev
:data="healthyDataType === 1 ? healthyData : {}"
v-show="healthyDataType === 1"
/>
</div>
<el-tabs v-model="activeName" class="message_userinfo_wrapper">
<el-tab-pane label="客户信息" name="health">
<div
v-loading="healthDataLoading"
:style="{ height: getTabContentHeight(), overflow: 'auto' }"
>
<HealthyView
dev
:data="healthyDataType === 0 ? healthyData : {}"
v-show="healthyDataType === 0"
/>
<BodySignView
dev
:data="healthyDataType === 1 ? healthyData : {}"
v-show="healthyDataType === 1"
/>
<div v-if="customerData.id" class="customer_service_info">
<div class="info_item">
<span>主任营养师</span>
<span>
{{ customerData.dietitianName || "无" }}
</span>
</div>
<div class="info_item">
<span>营养师助理</span>
<span>{{ customerData.assDietitianName || "无" }}</span>
</div>
<div class="info_item">
<span>售后营养师</span>
<span>{{ customerData.afterDietitianName || "无" }}</span>
</div>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="食谱计划" name="plan">
<div :style="{ height: getTabContentHeight(), overflow: 'auto' }">
<RecipesPlan />
</div>
</el-tab-pane>
</el-tabs>
</template>
<script>
import { createNamespacedHelpers } from "vuex";
import HealthyView from "@/components/HealthyView";
import BodySignView from "@/components/BodySignView";
const {
mapActions,
mapState,
mapMutations,
mapGetters,
} = createNamespacedHelpers("message");
import RecipesPlan from "./recipesPlan";
const { mapActions, mapState, mapMutations, mapGetters } =
createNamespacedHelpers("message");
export default {
name: "SignUserInfo",
components: {
HealthyView,
BodySignView,
RecipesPlan,
},
data() {
return {};
return {
activeName: "health",
};
},
methods: {
getTabContentHeight() {
const tabPanelElm = document.querySelector(".el-tabs");
if (tabPanelElm) {
return `${tabPanelElm.clientHeight - 68}px`;
}
return "";
},
},
computed: {
...mapState(["healthyData", "healthyDataType", "healthDataLoading"]),
...mapState([
"healthyData",
"healthyDataType",
"healthDataLoading",
"customerData",
]),
},
};
</script>
<style lang="scss" scoped>
.message_userinfo_wrapper {
.customer_service_info {
position: absolute;
right: 30%;
top: 68px;
.info_item {
margin-bottom: 10px;
font-size: 14px;
& > span:nth-child(1) {
color: #8c8c8c;
}
}
}
}
</style>

View File

@ -0,0 +1,220 @@
<template>
<div class="recipes_plan_wrapper">
<div class="header">
<section>
<el-button
v-if="cusOutId"
type="primary"
icon="el-icon-share"
size="mini"
class="copyBtn"
:data-clipboard-text="copyValue"
@click="handleOnRecipesLinkClick"
>食谱链接
</el-button>
<el-popover
placement="top"
trigger="click"
v-if="cusOutId"
style="margin: 0 12px"
>
<VueQr :text="copyValue" :logoSrc="logo" :size="256" />
<el-button
slot="reference"
size="mini"
icon="el-icon-picture-outline"
type="primary"
@click="handleCopy(scope.row.path)"
>二维码</el-button
>
</el-popover>
<!-- <el-button icon="el-icon-view" size="mini" @click="handleInnerOpen"
>查看暂停记录
</el-button> -->
</section>
<section>
<el-button
icon="el-icon-refresh"
size="mini"
@click="getRecipesPlanActions({ cusId })"
circle
/>
</section>
</div>
<el-table :data="planList" v-loading="planListLoading">
<el-table-column label="审核状态" align="center">
<template slot-scope="scope">
<el-tag :type="getReviewType(scope.row.reviewStatus)">
{{ getReviewStatusName(scope.row.reviewStatus) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="计划" align="center" width="130">
<template slot-scope="scope">
{{ `${scope.row.startNumDay}${scope.row.endNumDay}` }}
</template>
</el-table-column>
<el-table-column label="日期" align="center" width="200">
<template slot-scope="scope">
{{ `${scope.row.startDate}${scope.row.endDate}` }}
</template>
</el-table-column>
<el-table-column label="订阅情况" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.subscribed ? 'success' : 'danger'">
{{ scope.row.subscribed ? "已订阅" : "未订阅" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="发送" align="center">
<template slot-scope="scope">
<el-switch
v-model="!!scope.row.sendFlag"
@change="(val) => handleOnSendChange(val, scope.row)"
/>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button
type="text"
:icon="
scope.row.recipesId ? 'el-icon-edit' : 'el-icon-edit-outline'
"
@click="handleOnRecipesEditClick(scope.row)"
>
{{ `${scope.row.recipesId ? "编辑" : "制作"}` }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 暂停记录抽屉 -->
<!-- <PlanPauseDrawer ref="planPauseRef" /> -->
</div>
</template>
<script>
import Clipboard from "clipboard";
import { createNamespacedHelpers } from "vuex";
const { mapActions, mapState, mapMutations, mapGetters } =
createNamespacedHelpers("message");
// import PlanPauseDrawer from "./PlanPauseDrawer";
import VueQr from "vue-qr";
const logo = require("@/assets/logo/logo_b.png");
export default {
name: "RecipesPlanDrawer",
components: {
// PlanPauseDrawer,
VueQr,
},
data() {
return {
logo,
title: "",
cusOutId: "",
copyValue: "",
cusId: "",
};
},
watch: {
planList(val, newVal) {
console.log({ val, newVal });
this.cusOutId = val.reduce((str, cur) => {
if (!str && cur.recipesId && cur.reviewStatus === 2) {
str = cur.outId;
this.cusId = cur.cusId;
}
return str;
}, "");
if (this.cusOutId) {
this.copyValue =
window.location.origin.replace("manage", "sign") +
"/recipes/detail/" +
this.cusOutId;
}
},
},
computed: {
...mapState(["planList", "planListLoading", "healthyData"]),
},
methods: {
getReviewStatusName(status) {
switch (status) {
case 1:
return "未审核";
case 2:
return "已审核";
case 3:
return "制作中";
case 0:
default:
return "未制作";
}
},
getReviewType(status) {
switch (status) {
case 1:
return "danger";
case 2:
return "success";
case 3:
return "";
case 0:
default:
return "info";
}
},
// handleInnerOpen() {
// this.$refs["planPauseRef"].showDrawer(this.data);
// this.innerVisible = true;
// this.innerTitle = `「${this.data.name}」暂停记录`;
// },
handleOnRecipesLinkClick() {
new Clipboard(".copyBtn");
this.$message({
message: "拷贝成功",
type: "success",
});
},
handleOnRecipesEditClick(data) {
window.open(
"/recipes/build/" + this.healthyData.name + "/" + data.id,
"_blank"
);
},
handleOnSendChange(val, data) {
console.log({ val, data });
const { id } = data;
if (data.reviewStatus === 2) {
this.updateRecipesPlanActions({
id,
sendFlag: val ? 1 : 0,
callback: (type, msg) => {
this.$message[type](msg);
},
});
} else {
this.$message.error("未审核的食谱不能发送");
}
},
...mapActions(["getRecipesPlanActions", "updateRecipesPlanActions"]),
},
};
</script>
<style lang="scss" scoped>
/deep/ :focus {
outline: 0;
}
.recipes_plan_wrapper {
// height: calc(100vh - 77px);
.header {
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: space-between;
}
}
</style>