|
@@ -0,0 +1,990 @@
|
|
|
+<script setup>
|
|
|
+import { reactive, ref, onMounted } from 'vue'
|
|
|
+import { departInterence, InteractionInterence } from "@/api/api.js";
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import _ from 'lodash'
|
|
|
+
|
|
|
+const pageState = reactive({
|
|
|
+ statusType: "", //提问状态筛选框
|
|
|
+ answers: [], //回答者筛选框
|
|
|
+ ReplierIds: "",
|
|
|
+ countFree: 0,
|
|
|
+ countWait: 0,
|
|
|
+ statusOptions: [],
|
|
|
+ answerOptions: [],//不包含被禁用的研究员
|
|
|
+ answerOptionsAll: [],//所有研究员
|
|
|
+ answerOptionsProp: {
|
|
|
+ value: "admin_id",
|
|
|
+ label: "admin_name",
|
|
|
+ children: "children",
|
|
|
+ }, //回答者选择配置
|
|
|
+ tableData: [],
|
|
|
+ tableLoading: false,
|
|
|
+ page_no: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0,
|
|
|
+ tableColumns: [
|
|
|
+ {
|
|
|
+ label: "提问内容",
|
|
|
+ key: "QuestionContent",
|
|
|
+ minWidth: 170,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "提问人",
|
|
|
+ key: "RealName",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "提问时间",
|
|
|
+ key: "CreateTime",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "提问状态",
|
|
|
+ key: "ReplyStatus",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "回答者",
|
|
|
+ key: "answer",
|
|
|
+ minWidth: 150,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "回答时间",
|
|
|
+ key: "ReplyTime",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: "点击量",
|
|
|
+ key: "ClickNum",
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ questionStatusMap: {
|
|
|
+ // 1: "待分配",
|
|
|
+ 2: "待回答",
|
|
|
+ 3: "已回答",
|
|
|
+ 4: "已终止",
|
|
|
+ },
|
|
|
+ deletePopVisible: false,
|
|
|
+ isEditShow: false,
|
|
|
+ currentEdit: {
|
|
|
+ text: "",
|
|
|
+ id: 0,
|
|
|
+ },
|
|
|
+ reflesh: 0,
|
|
|
+ userInfoDialog: false,
|
|
|
+ clickNumDialog: false,
|
|
|
+ clickLogsData: [],
|
|
|
+ clickNum: 0,
|
|
|
+ clickQuestionContent: '',
|
|
|
+ clickLogsTotal: 0,
|
|
|
+ clickLogsCurrentIndex: 1,
|
|
|
+ clickLogsPageSize: 10,
|
|
|
+ questionId: 0,
|
|
|
+ userDetail: {},
|
|
|
+ SortParam: '',//点击量排序
|
|
|
+ SortType: '',
|
|
|
+
|
|
|
+ maxNum: 28,//字数限制
|
|
|
+
|
|
|
+ questionInfoDialog: false,
|
|
|
+ questionInfo: null,
|
|
|
+
|
|
|
+ stopReasonDialog: false,
|
|
|
+ stopReason: '',
|
|
|
+
|
|
|
+ moveAnswerDialog: false,
|
|
|
+ moveQuestionId: 0,
|
|
|
+ moveAnswerOpt: [],
|
|
|
+ moveAnswerId: [],
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+//删除问题
|
|
|
+function handleDeleteAuth(item) {
|
|
|
+ InteractionInterence.deleteQuestion({
|
|
|
+ QuestionId: item.CommunityQuestionId
|
|
|
+ }).then(res => {
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ ElMessage.success('删除成功');
|
|
|
+ getTableData();
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+function handleSelect(type) {
|
|
|
+ pageState.page_no = 1;
|
|
|
+ if (type === "status") {
|
|
|
+ getTableData();
|
|
|
+ } else {
|
|
|
+ let temp = [];
|
|
|
+ pageState.answers.forEach((item) => {
|
|
|
+ temp.push(item[item.length - 1]);
|
|
|
+ });
|
|
|
+ pageState.ReplierIds = _.uniq(temp).join(",");
|
|
|
+ getTableData();
|
|
|
+ }
|
|
|
+}
|
|
|
+/**
|
|
|
+ * 获取级联选择器回显
|
|
|
+ * @param {options} options 树形数组格式(answerOptions)
|
|
|
+ * @param {answerId} answerId 回答者的id,字段为admin_id
|
|
|
+ * @param {keyWord} keyWord 返回项的key
|
|
|
+ * @return [0,1,2] (keyWord=admin_id) 或 ['宏观组','利率债','xx'] (keyWord=admin_name)
|
|
|
+ */
|
|
|
+function getAnswer(options, answerId, keyWord = "admin_id") {
|
|
|
+ const getAnswerOption = (list, value) => {
|
|
|
+ for (let i in list) {
|
|
|
+ if (list[i].admin_id == value) {
|
|
|
+ return [list[i]];
|
|
|
+ }
|
|
|
+ if (list[i].children) {
|
|
|
+ let node = getAnswerOption(list[i].children, value);
|
|
|
+ if (node !== undefined) {
|
|
|
+ return node.concat(list[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const answer = getAnswerOption(options, answerId);
|
|
|
+ return answer.map((i) => i[keyWord]).reverse();
|
|
|
+}
|
|
|
+async function getTableData() {
|
|
|
+ pageState.tableLoading = true;
|
|
|
+ const res = await InteractionInterence.getQuestionList({
|
|
|
+ ReplyStatus: pageState.statusType,
|
|
|
+ ReplierIds: pageState.ReplierIds,
|
|
|
+ CurrentIndex: pageState.page_no,
|
|
|
+ PageSize: pageState.pageSize,
|
|
|
+ SortParam: pageState.SortParam,
|
|
|
+ SortType: pageState.SortType
|
|
|
+ });
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ const { List, Paging, Count } = res.Data;
|
|
|
+ pageState.tableData = List;
|
|
|
+ pageState.tableData && processTableData();
|
|
|
+ pageState.page_no = Paging.CurrentIndex;
|
|
|
+ pageState.total = Paging.Totals;
|
|
|
+ if (Count) {
|
|
|
+ pageState.countFree = Count.free;
|
|
|
+ pageState.countWait = Count.wait;
|
|
|
+ }
|
|
|
+ } else if (res.Ret === 403) {
|
|
|
+ //无权查看
|
|
|
+ pageState.tableData = []
|
|
|
+ }
|
|
|
+ pageState.tableLoading = false;
|
|
|
+}
|
|
|
+//处理table数据,方便answer的回显
|
|
|
+function processTableData() {
|
|
|
+ pageState.tableData.forEach((item) => {
|
|
|
+ if (item.MsgSendStatus === 0) {
|
|
|
+ item.isSent = false;
|
|
|
+ } else {
|
|
|
+ item.isSent = true;
|
|
|
+ }
|
|
|
+ //未回答且没发送通知的问题:回答者一栏显示级联选择器
|
|
|
+ if (item.ReplierAdminId && !item.isSent || item.NeedRedistribute) {
|
|
|
+ //item.answer = getAnswer(pageState.answerOptions, item.ReplierAdminId);
|
|
|
+ item.answer = [item.ResearchGroupFirstId, item.ResearchGroupSecondId, item.ReplierAdminId]
|
|
|
+ }
|
|
|
+ //未分配的提问,回答者一栏显示级联选择器
|
|
|
+ if (!item.ReplierAdminId) {
|
|
|
+ item.answer = []
|
|
|
+ }
|
|
|
+ //已发送通知或已回答的问题:回答者一栏显示文字
|
|
|
+ if (item.isSent && !item.NeedRedistribute || item.ReplyStatus === 3) {
|
|
|
+ /* item.answerText = this.getAnswer(
|
|
|
+ this.answerOptions,
|
|
|
+ item.ReplierAdminId,
|
|
|
+ "admin_name"
|
|
|
+ ).join("/"); */
|
|
|
+ item.answerText = item.ResearchGroupFirstName + '/' + item.ResearchGroupSecondName + '/' + item.ReplierRealName
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+//分配回答者
|
|
|
+async function handleAnswerChange(item) {
|
|
|
+ console.log("item", item);
|
|
|
+ if (item.QuestionContent.length > pageState.maxNum) {
|
|
|
+ ElMessage.warning("字数超限,请修改问题后重试");
|
|
|
+ pageState.tableData.map((i) => {
|
|
|
+ if (item.CommunityQuestionId === i.CommunityQuestionId) {
|
|
|
+ i.answer = [];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ pageState.reflesh++;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const AdminId = item.answer[item.answer.length - 1];
|
|
|
+ const ResearchGroupFirstId = item.answer[0];
|
|
|
+ const ResearchGroupSecondId = item.answer[1];
|
|
|
+ const res = await InteractionInterence.distributeAnswer({
|
|
|
+ QuestionId: item.CommunityQuestionId,
|
|
|
+ AdminId,
|
|
|
+ ResearchGroupFirstId,
|
|
|
+ ResearchGroupSecondId,
|
|
|
+ });
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ if (res.Msg === '操作成功') {
|
|
|
+ //回答者已关注公众号的情况
|
|
|
+ ElMessage.success("分配成功!");
|
|
|
+ } else {
|
|
|
+ //回答者未关注公众号的情况
|
|
|
+ ElMessage.error("该研究员未关注公众号,无法收到消息通知")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ getTableData();
|
|
|
+}
|
|
|
+//发送通知
|
|
|
+function sentMsg(item) {
|
|
|
+ if (!item.answer) return;
|
|
|
+ InteractionInterence.sendMsg({
|
|
|
+ QuestionId: item.CommunityQuestionId,
|
|
|
+ }).then((res) => {
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ ElMessage.success("发送通知成功");
|
|
|
+ getTableData();
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+//获取answerOptions
|
|
|
+async function getResearchGroupList(include = 0) {
|
|
|
+ /* const res = await departInterence.getResearchGroupList({
|
|
|
+ Include: include
|
|
|
+ }); */
|
|
|
+ const res = await departInterence.getTagTree({
|
|
|
+ IncludeDisableMember: include,
|
|
|
+ HasResearcher: 1
|
|
|
+ });
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ //每一级的value:admin_id,label:admin_name固定,方便级联选择器回显;
|
|
|
+ //第二级的researcher_list复制一份为children
|
|
|
+ const { Data } = res;
|
|
|
+ const temp = _.cloneDeep(Data);
|
|
|
+ temp.forEach((item) => {
|
|
|
+ item.admin_id = item.tag_id;
|
|
|
+ item.admin_name = item.tag_name;
|
|
|
+ if (item.tags) {
|
|
|
+ item.children = _.cloneDeep(item.tags)
|
|
|
+ item.children.map((i) => {
|
|
|
+ i.admin_id = i.tag_id;
|
|
|
+ i.admin_name = i.tag_name;
|
|
|
+ i.children = _.cloneDeep(i.researcher_list);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (include === 1) {
|
|
|
+ pageState.answerOptionsAll = temp;
|
|
|
+ } else {
|
|
|
+ pageState.answerOptions = temp;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+//获取statusOptions
|
|
|
+function getStatusOptions() {
|
|
|
+ for (let i in pageState.questionStatusMap) {
|
|
|
+ pageState.statusOptions.push({ value: i, label: pageState.questionStatusMap[i] });
|
|
|
+ }
|
|
|
+}
|
|
|
+//显示编辑问题描述弹窗
|
|
|
+function showEdit(item) {
|
|
|
+ pageState.isEditShow = true;
|
|
|
+ pageState.currentEdit = {
|
|
|
+ id: item.CommunityQuestionId,
|
|
|
+ text: item.QuestionContent,
|
|
|
+ };
|
|
|
+}
|
|
|
+//提交编辑问题
|
|
|
+function handleEditQuestion() {
|
|
|
+ const { id, text } = pageState.currentEdit;
|
|
|
+ if (text.length > pageState.maxNum) {
|
|
|
+ ElMessage.warning("字数超出最长限制");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ InteractionInterence.editQuestion({
|
|
|
+ QuestionId: id,
|
|
|
+ QuestionContent: text,
|
|
|
+ }).then((res) => {
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ ElMessage.success("编辑成功");
|
|
|
+ pageState.isEditShow = false;
|
|
|
+ getTableData();
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+//页码改变
|
|
|
+function handleCurrentChange(page) {
|
|
|
+ pageState.page_no = page;
|
|
|
+ getTableData();
|
|
|
+}
|
|
|
+//提问者详情
|
|
|
+function userInfo(row) {
|
|
|
+ InteractionInterence.questionUser({
|
|
|
+ QuestionId: row.CommunityQuestionId,
|
|
|
+ }).then(res => {
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ pageState.userDetail = res.Data;
|
|
|
+ pageState.userInfoDialog = true;
|
|
|
+ } else if (res.Ret === 403) {
|
|
|
+ //无权查看
|
|
|
+ pageState.userDetail = {}
|
|
|
+ pageState.userInfoDialog = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+function clicksEvent(row) {
|
|
|
+ pageState.questionId = row.CommunityQuestionId
|
|
|
+ pageState.clickLogsData = [];
|
|
|
+ pageState.clickNum = row.ClickNum;
|
|
|
+ pageState.clickQuestionContent = row.QuestionContent;
|
|
|
+ pageState.clickNumDialog = true;
|
|
|
+ getClickLogsData()
|
|
|
+}
|
|
|
+
|
|
|
+function getClickLogsData() {
|
|
|
+ InteractionInterence.questionClickLogs({
|
|
|
+ QuestionId: pageState.questionId,
|
|
|
+ CurrentIndex: pageState.clickLogsCurrentIndex,
|
|
|
+ PageSize: pageState.clickLogsPageSize,
|
|
|
+ }).then(res => {
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ pageState.clickLogsData = res.Data.List;
|
|
|
+ pageState.clickLogsCurrentIndex = res.Data.Paging.CurrentIndex;
|
|
|
+ pageState.clickLogsTotal = res.Data.Paging.Totals;
|
|
|
+ } else if (res.Ret === 403) {
|
|
|
+ //无权查看
|
|
|
+ pageState.clickLogsData = []
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function clickLogsPageChange(currentIndex) {
|
|
|
+ pageState.clickLogsCurrentIndex = currentIndex;
|
|
|
+ getClickLogsData();
|
|
|
+}
|
|
|
+//table排序变化
|
|
|
+function sortChangeHandle({ prop, order }) {
|
|
|
+ console.log(prop, order)
|
|
|
+ //this.page_no = 1;
|
|
|
+ pageState.SortType = order === 'ascending' ? 'asc' : order === 'descending' ? 'desc' : ''
|
|
|
+ if (pageState.SortType.length) {
|
|
|
+ pageState.SortParam = prop
|
|
|
+ } else {
|
|
|
+ pageState.SortParam = ''
|
|
|
+ }
|
|
|
+ getTableData()
|
|
|
+}
|
|
|
+
|
|
|
+async function showQuestionDetail(e) {
|
|
|
+ const res = await InteractionInterence.questionDetail({ QuestionId: e.CommunityQuestionId })
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ pageState.questionInfo = res.Data
|
|
|
+ pageState.questionInfoDialog = true
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function handleShowmoveAnswerDialog(e) {
|
|
|
+ const res = await departInterence.getTagTree({
|
|
|
+ IncludeDisableMember: 0,
|
|
|
+ HasResearcher: 1,
|
|
|
+ CommunityQuestionId: e.CommunityQuestionId
|
|
|
+ });
|
|
|
+ if (res.Ret === 200) {
|
|
|
+ const arr = res.Data || []
|
|
|
+ pageState.moveAnswerOpt = arr.map(item => {
|
|
|
+ let obj = {
|
|
|
+ ...item,
|
|
|
+ label: item.tag_name,
|
|
|
+ value: item.tag_id,
|
|
|
+ children: []
|
|
|
+ }
|
|
|
+ const arr1 = item.tags || []
|
|
|
+ obj.children = arr1.map(item2 => {
|
|
|
+ let obj2 = {
|
|
|
+ ...item2,
|
|
|
+ label: item2.tag_name,
|
|
|
+ value: item2.tag_id,
|
|
|
+ children: []
|
|
|
+ }
|
|
|
+ const arr2 = item2.researcher_list || []
|
|
|
+ obj2.children = arr2.map(item3 => {
|
|
|
+ return {
|
|
|
+ ...item3,
|
|
|
+ label: item3.admin_name,
|
|
|
+ value: item3.admin_id,
|
|
|
+ disabled: !item3.allow_select
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return obj2
|
|
|
+ })
|
|
|
+ return obj
|
|
|
+ })
|
|
|
+ pageState.moveQuestionId = e.CommunityQuestionId
|
|
|
+ pageState.moveAnswerDialog = true
|
|
|
+ }
|
|
|
+}
|
|
|
+// 确认转移
|
|
|
+async function handleConfirmTrans() {
|
|
|
+ const res = await InteractionInterence.questionTransfer({
|
|
|
+ QuestionId: pageState.moveQuestionId,
|
|
|
+ AdminId: pageState.moveAnswerId[2],
|
|
|
+ ResearchGroupFirstId: pageState.moveAnswerId[0],
|
|
|
+ ResearchGroupSecondId: pageState.moveAnswerId[1]
|
|
|
+ })
|
|
|
+ if (res.Ret == 200) {
|
|
|
+ ElMessage.success('转移成功')
|
|
|
+ pageState.moveAnswerId = []
|
|
|
+ pageState.moveAnswerDialog = false
|
|
|
+ getTableData();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ await getResearchGroupList(1);
|
|
|
+ // await getResearchGroupList();
|
|
|
+ getStatusOptions();
|
|
|
+ getTableData();
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="question-wrap">
|
|
|
+ <div class="question-top">
|
|
|
+ <div class="question-info">
|
|
|
+ <span>待分配问题数:{{ pageState.countFree }}</span>
|
|
|
+ <span>待回答提问数:{{ pageState.countWait }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="question-select">
|
|
|
+ <el-select
|
|
|
+ v-model="pageState.statusType"
|
|
|
+ clearable
|
|
|
+ placeholder="提问状态"
|
|
|
+ style="width: 260px;margin-right:10px"
|
|
|
+ @change="handleSelect('status')"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in pageState.statusOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
+ >
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ <el-cascader
|
|
|
+ placeholder="回答者"
|
|
|
+ v-model="pageState.answers"
|
|
|
+ collapse-tags
|
|
|
+ clearable
|
|
|
+ style="width: 260px"
|
|
|
+ :options="pageState.answerOptionsAll"
|
|
|
+ :props="{ ...pageState.answerOptionsProp, multiple: true }"
|
|
|
+ @change="handleSelect('answers')"
|
|
|
+ ></el-cascader>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="question-table">
|
|
|
+ <el-table
|
|
|
+ :data="pageState.tableData"
|
|
|
+ border
|
|
|
+ v-loading="pageState.tableLoading"
|
|
|
+ :key="pageState.reflesh"
|
|
|
+ @sort-change="sortChangeHandle"
|
|
|
+ >
|
|
|
+ <el-table-column
|
|
|
+ v-for="item in pageState.tableColumns"
|
|
|
+ :key="item.label"
|
|
|
+ :label="item.label"
|
|
|
+ :prop="item.key"
|
|
|
+ :min-width="item.minWidth"
|
|
|
+ align="center"
|
|
|
+ :sortable="item.key === 'ClickNum' ? 'custom' : false"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <!-- <div v-if="item.key === 'answer' && (row.ReplyStatus < 3 && !row.isSent || row.NeedRedistribute)">
|
|
|
+ <el-cascader v-model="row.answer" :options="answerOptions" :props="answerOptionsProp"
|
|
|
+ @change="handleAnswerChange(row)"></el-cascader>
|
|
|
+ </div> -->
|
|
|
+ <span v-if="item.key === 'answer'">
|
|
|
+ {{ row.answerText }}
|
|
|
+ </span>
|
|
|
+ <span
|
|
|
+ v-else-if="item.key === 'RealName' && row.UserHasDetail"
|
|
|
+ @click="userInfo(row)"
|
|
|
+ style="cursor: pointer; color: rgb(64, 153, 239)"
|
|
|
+ >
|
|
|
+ {{ row[item.key] }}
|
|
|
+ {{ row.UserQaCount ? `(${row.UserQaCount})` : "" }}
|
|
|
+ </span>
|
|
|
+ <span v-else-if="item.key === 'RealName' && !row.UserHasDetail">
|
|
|
+ {{ row[item.key] }}
|
|
|
+ {{ row.UserQaCount ? `(${row.UserQaCount})` : "" }}
|
|
|
+ </span>
|
|
|
+ <span v-else-if="item.key === 'ReplyStatus'">
|
|
|
+ {{ pageState.questionStatusMap[row[item.key]] }}
|
|
|
+ </span>
|
|
|
+ <span v-else-if="item.key === 'ReplyTime'">
|
|
|
+ {{ row.ReplyStatus === 3 ? row.ReplyTime : "" }}
|
|
|
+ </span>
|
|
|
+ <span v-else-if="item.key === 'ClickNum'">
|
|
|
+ <span
|
|
|
+ v-if="row.ClickNum > 0"
|
|
|
+ @click="clicksEvent(row)"
|
|
|
+ style="cursor: pointer; color: rgb(64, 153, 239)"
|
|
|
+ >
|
|
|
+ {{ row.ClickNum }}</span
|
|
|
+ >
|
|
|
+ <span v-else>{{ "--" }}</span>
|
|
|
+ </span>
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ cursor: pointer;
|
|
|
+ color: rgb(64, 153, 239);
|
|
|
+ "
|
|
|
+ v-else-if="item.key === 'QuestionContent'"
|
|
|
+ @click="showQuestionDetail(row)"
|
|
|
+ >
|
|
|
+ {{ row[item.key] }}
|
|
|
+ <span
|
|
|
+ style="
|
|
|
+ margin-left: 5px;
|
|
|
+ min-width: 16px;
|
|
|
+ max-width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ align-self: center;
|
|
|
+ "
|
|
|
+ @click.stop="showEdit(row)"
|
|
|
+ v-if="row.MsgSendStatus === 0 && row.ReplyStatus < 3"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ style="width: 100%"
|
|
|
+ :src="require('@/assets/img/icons/editquestion.png')"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <span v-else>{{ row[item.key] }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span
|
|
|
+ v-if="row.ReplyStatus === 4"
|
|
|
+ style="color: #409eff; display: inline-block; cursor: pointer"
|
|
|
+ @click="
|
|
|
+ (pageState.stopReasonDialog = true),
|
|
|
+ (pageState.stopReason = row.StopReason)
|
|
|
+ "
|
|
|
+ >终止原因</span
|
|
|
+ >
|
|
|
+ <!-- <span v-if="row.ReplyStatus===2" style="color:#409EFF;display:inline-block;cursor: pointer" @click="handleShowmoveAnswerDialog(row)">转移并通知</span> -->
|
|
|
+ <!-- <span v-if="row.ReplyStatus < 3 && !row.isSent" @click="sentMsg(row)" style="cursor: pointer" :style="{
|
|
|
+ color: row.answer ? 'rgb(64, 153, 239)' : 'gray',
|
|
|
+ cursor: row.answer ? 'pointer' : 'not-allowed',
|
|
|
+ }">发送通知</span> -->
|
|
|
+ <el-popover
|
|
|
+ placement="top"
|
|
|
+ width="160"
|
|
|
+ v-model="row.deletePopVisible"
|
|
|
+ :ref="`pop_${row.CommunityQuestionId}`"
|
|
|
+ >
|
|
|
+ <p>该操作不可撤销,确定删除吗?</p>
|
|
|
+ <div style="text-align: right; margin: 0">
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ @click="row.deletePopVisible = false"
|
|
|
+ >取消</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ @click="handleDeleteAuth(row)"
|
|
|
+ >确定</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <template #reference>
|
|
|
+ <span style="cursor: pointer; color: #d1433a">删除</span>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <template #empty>
|
|
|
+ <div style="line-height: 44px; margin: 60px 0; color: #999">
|
|
|
+ <img
|
|
|
+ src="~@/assets/img/cus_m/nodata.png"
|
|
|
+ alt=""
|
|
|
+ style="display: block; width: 160px; height: 128px; margin: auto"
|
|
|
+ />
|
|
|
+ <span>暂无数据</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ <el-pagination
|
|
|
+ layout="total,prev,pager,next,jumper"
|
|
|
+ background
|
|
|
+ :current-page="pageState.page_no"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ :page-size="pageState.pageSize"
|
|
|
+ :total="pageState.total"
|
|
|
+ style="text-align: end; margin-top: 20px"
|
|
|
+ >
|
|
|
+ </el-pagination>
|
|
|
+ </div>
|
|
|
+ <el-dialog
|
|
|
+ v-if="pageState.isEditShow"
|
|
|
+ v-model="pageState.isEditShow"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :modal-append-to-body="false"
|
|
|
+ @close="pageState.isEditShow = false"
|
|
|
+ width="889px"
|
|
|
+ draggable
|
|
|
+ center
|
|
|
+ >
|
|
|
+ <template #header>
|
|
|
+ <div style="display: flex; align-items: center">
|
|
|
+ <span style="fontsize: 16px">问题编辑</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div class="dialog-container">
|
|
|
+ <div class="input-item">
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ :rows="12"
|
|
|
+ placeholder="请输入提问内容"
|
|
|
+ v-model="pageState.currentEdit.text"
|
|
|
+ required
|
|
|
+ resize="none"
|
|
|
+ >
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ <div class="hint">
|
|
|
+ <span>注:请把问题描述控制在{{ pageState.maxNum }}个字以内</span>
|
|
|
+ <span
|
|
|
+ >超出字数:<span style="color: #c94040ff">{{
|
|
|
+ pageState.currentEdit.text.length - pageState.maxNum > 0
|
|
|
+ ? pageState.currentEdit.text.length - pageState.maxNum
|
|
|
+ : 0
|
|
|
+ }}</span
|
|
|
+ >字</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <div class="foot-container">
|
|
|
+ <el-button type="primary" @click="handleEditQuestion"
|
|
|
+ >确 定</el-button
|
|
|
+ >
|
|
|
+ <el-button @click="pageState.isEditShow = false">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog
|
|
|
+ draggable
|
|
|
+ :append-to-body="true"
|
|
|
+ :model-value="pageState.userInfoDialog"
|
|
|
+ width="500px"
|
|
|
+ title="提问者详情"
|
|
|
+ center
|
|
|
+ >
|
|
|
+ <template #header>
|
|
|
+ <div style="display: flex; align-items: center">
|
|
|
+ <span style="font-size: 16px">提问者详情</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <div class="detail-wrap">
|
|
|
+ <div class="main">
|
|
|
+ <table class="table-wrap" style="border: none !important">
|
|
|
+ <tbody>
|
|
|
+ <tr>
|
|
|
+ <td class="table-item" style="width: 25%; text-align: right">
|
|
|
+ 提问者内容:
|
|
|
+ </td>
|
|
|
+ <td class="table-item" style="width: 75%; text-align: left">
|
|
|
+ {{ pageState.userDetail.QuestionContent }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td class="table-item" style="width: 25%; text-align: right">
|
|
|
+ 提问者姓名:
|
|
|
+ </td>
|
|
|
+ <td class="table-item" style="width: 75%; text-align: left">
|
|
|
+ {{ pageState.userDetail.RealName }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td class="table-item" style="width: 25%; text-align: right">
|
|
|
+ 公司名称:
|
|
|
+ </td>
|
|
|
+ <td class="table-item" style="width: 75%; text-align: left">
|
|
|
+ {{ pageState.userDetail.CompanyName }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td class="table-item" style="width: 25%; text-align: right">
|
|
|
+ 客户状态:
|
|
|
+ </td>
|
|
|
+ <td class="table-item" style="width: 75%; text-align: left">
|
|
|
+ {{ pageState.userDetail.CompanyStatus }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ <tr>
|
|
|
+ <td class="table-item" style="width: 25%; text-align: right">
|
|
|
+ 所属销售:
|
|
|
+ </td>
|
|
|
+ <td class="table-item" style="width: 75%; text-align: left">
|
|
|
+ {{ pageState.userDetail.SellerName }}
|
|
|
+ </td>
|
|
|
+ </tr>
|
|
|
+ </tbody>
|
|
|
+ </table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <div class="foot-container">
|
|
|
+ <el-button type="primary" @click="userInfoDialog = false"
|
|
|
+ >知道了</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ draggable
|
|
|
+ :append-to-body="true"
|
|
|
+ :model-value="pageState.clickNumDialog"
|
|
|
+ width="840px"
|
|
|
+ title="点击量详情"
|
|
|
+ center
|
|
|
+ >
|
|
|
+ <template #header>
|
|
|
+ <div style="display: flex; align-items: center">
|
|
|
+ <span style="font-size: 16px">点击量详情</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <div>点击量:{{ pageState.clickNum }}</div>
|
|
|
+ <div>提问内容:{{ pageState.clickQuestionContent }}</div>
|
|
|
+ <div>
|
|
|
+ <el-table
|
|
|
+ :data="pageState.clickLogsData"
|
|
|
+ style="width: 100%; margin: 20px 0 30px"
|
|
|
+ border
|
|
|
+ >
|
|
|
+ <el-table-column prop="RealName" label="用户姓名" align="center">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="CompanyName" label="公司名称" align="center">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ prop="CompanyStatus"
|
|
|
+ label="客户状态"
|
|
|
+ align="center"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="ClickNum" label="点击次数" align="center">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="SourceAgent" label="点击来源" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <span v-if="scope.row.SourceAgent == 1">小程序</span>
|
|
|
+ <span v-else>pc</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ prop="LastCreateTime"
|
|
|
+ label="最后一次点击时间"
|
|
|
+ align="center"
|
|
|
+ min-width="140"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <!-- 分页 -->
|
|
|
+ <div style="text-align: end; margin-bottom: 24px">
|
|
|
+ <el-pagination
|
|
|
+ small
|
|
|
+ layout="prev,pager,next,jumper"
|
|
|
+ :current-page="pageState.clickLogsCurrentIndex"
|
|
|
+ @current-change="clickLogsPageChange"
|
|
|
+ :page-size="pageState.clickLogsPageSize"
|
|
|
+ :total="pageState.clickLogsTotal"
|
|
|
+ class="pagination-wrap"
|
|
|
+ >
|
|
|
+ </el-pagination>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <!-- 问答详情弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ draggable
|
|
|
+ :append-to-body="true"
|
|
|
+ :model-value="pageState.questionInfoDialog"
|
|
|
+ width="800px"
|
|
|
+ title="提问详情"
|
|
|
+ center
|
|
|
+ >
|
|
|
+ <div class="question-detail-wrap" v-if="pageState.questionInfo">
|
|
|
+ <div class="left">
|
|
|
+ <div class="item">
|
|
|
+ <span class="lable">提问人</span>
|
|
|
+ <span>{{ pageState.questionInfo.RealName }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <span class="lable">提问时间</span>
|
|
|
+ <span>{{ pageState.questionInfo.CreateTime }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <span class="lable">提问内容</span>
|
|
|
+ <div style="padding: 10px; background: #ededed">
|
|
|
+ {{ pageState.questionInfo.QuestionContent }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="right">
|
|
|
+ <div style="margin-bottom: 20px">问答流程</div>
|
|
|
+ <el-timeline>
|
|
|
+ <el-timeline-item
|
|
|
+ :timestamp="item.CreateTime"
|
|
|
+ placement="bottom"
|
|
|
+ color="#409EFF"
|
|
|
+ v-for="item in pageState.questionInfo.ProcessList"
|
|
|
+ :key="item.CreateTime"
|
|
|
+ >
|
|
|
+ <p>{{ item.Remark }}</p>
|
|
|
+ </el-timeline-item>
|
|
|
+ </el-timeline>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <!-- 终止原因 -->
|
|
|
+ <el-dialog
|
|
|
+ draggable
|
|
|
+ :append-to-body="true"
|
|
|
+ :model-value="pageState.stopReasonDialog"
|
|
|
+ width="400px"
|
|
|
+ title="终止原因"
|
|
|
+ center
|
|
|
+ >
|
|
|
+ <div style="padding-bottom: 30px">
|
|
|
+ <p style="margin-bottom: 20px">{{ pageState.stopReason }}</p>
|
|
|
+ <div style="text-align: center">
|
|
|
+ <el-button type="primary" @click="pageState.stopReasonDialog = false"
|
|
|
+ >知道了</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <!-- 转移回答者弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ draggable
|
|
|
+ :append-to-body="true"
|
|
|
+ :model-value="pageState.moveAnswerDialog"
|
|
|
+ width="550px"
|
|
|
+ title="问题转移并通知"
|
|
|
+ center
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <div>
|
|
|
+ <span>选择研究员</span>
|
|
|
+ <el-cascader
|
|
|
+ style="width: 400px"
|
|
|
+ v-model="pageState.moveAnswerId"
|
|
|
+ :options="pageState.moveAnswerOpt"
|
|
|
+ ></el-cascader>
|
|
|
+ </div>
|
|
|
+ <div style="text-align: center; margin: 30px 0">
|
|
|
+ <el-button type="primary" @click="handleConfirmTrans">确定</el-button>
|
|
|
+ <el-button type="primary" plain @click="pageState.moveAnswerDialog = false"
|
|
|
+ >取消</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style scoped lang="scss">
|
|
|
+.question-wrap {
|
|
|
+ /* height: calc(100vh - 120px); */
|
|
|
+ background-color: #fff;
|
|
|
+ box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.05);
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 30px 20px;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ .question-top {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ }
|
|
|
+
|
|
|
+ .question-table {
|
|
|
+ margin-top: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dialog-container {
|
|
|
+ .hint {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+
|
|
|
+ span {
|
|
|
+ color: #999999ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.detail-wrap {
|
|
|
+ //max-height: 70vh;
|
|
|
+ //overflow-y: scroll;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+
|
|
|
+ .main {
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .table-wrap {
|
|
|
+ border: 0;
|
|
|
+ width: 100%;
|
|
|
+ // text-align: center;
|
|
|
+ border-top: 1px solid #dcdfe6;
|
|
|
+ border-left: 1px solid #dcdfe6;
|
|
|
+
|
|
|
+ .table-item {
|
|
|
+ border: none !important;
|
|
|
+ padding: 14px 10px;
|
|
|
+ border-right: 1px solid #dcdfe6;
|
|
|
+ border-bottom: 1px solid #dcdfe6;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.question-detail-wrap {
|
|
|
+ display: flex;
|
|
|
+ padding-bottom: 30px;
|
|
|
+ .left {
|
|
|
+ flex: 1;
|
|
|
+ .item {
|
|
|
+ display: flex;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ .lable {
|
|
|
+ width: 80px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .right {
|
|
|
+ flex: 1;
|
|
|
+ border-left: 1px solid #ededed;
|
|
|
+ height: 400px;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-left: 20px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|