|
|
@@ -0,0 +1,3094 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+
|
|
|
+ <div style="margin: 30px;">模板编号:【{{this.form.id}}】</div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ margin-top: 10px;
|
|
|
+ margin-left: 50px;
|
|
|
+ margin-right: 100px;
|
|
|
+ margin-bottom: 60px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <el-form
|
|
|
+ ref="form"
|
|
|
+ :model="form"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-form-item
|
|
|
+ label="名称"
|
|
|
+ prop="name"
|
|
|
+ >
|
|
|
+ {{ form.name }}
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="状态">
|
|
|
+ <dict-tag
|
|
|
+ :options="statusOptions"
|
|
|
+ :value="form.status"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="间隔天数"
|
|
|
+ prop="gap"
|
|
|
+ >
|
|
|
+ {{ form.gap }}天
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="规则"
|
|
|
+ prop="setting"
|
|
|
+ >
|
|
|
+ <!-- 操作条件:表单类型不为查看且(模板类型不为新客对话或没有天数) -->
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ class="el-icon-plus"
|
|
|
+ :underline="false"
|
|
|
+ @click='addDay()'
|
|
|
+ v-if="formType != 3 && (form.sendType != 4 || days.length < 1)"
|
|
|
+ >
|
|
|
+ 添加天数
|
|
|
+ </el-link>
|
|
|
+
|
|
|
+ <!-- 操作条件:不为新客对话且表单类型属于查看 -->
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ class="el-icon-sort"
|
|
|
+ :underline="false"
|
|
|
+ @click='openUpdateDaySorts()'
|
|
|
+ style="margin-left: 20px"
|
|
|
+ v-if="form.sendType != 4 && formType != 3"
|
|
|
+ >
|
|
|
+ 修改天数排序
|
|
|
+ </el-link>
|
|
|
+
|
|
|
+ <!-- 操作条件:不为新客对话且表单类型属于查看 -->
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ class="el-icon-sort"
|
|
|
+ :underline="false"
|
|
|
+ @click='openUpdateSorts()'
|
|
|
+ style="margin-left: 20px"
|
|
|
+ v-if="form.sendType != 4 && formType != 3"
|
|
|
+ >
|
|
|
+ 修改规则排序
|
|
|
+ </el-link>
|
|
|
+
|
|
|
+ <!-- 具体规则维护 -->
|
|
|
+ <el-tabs
|
|
|
+ v-model="tabIndex"
|
|
|
+ type="card"
|
|
|
+ @tab-remove="delDay"
|
|
|
+ v-if="days && days.length > 0"
|
|
|
+ :before-leave="leave"
|
|
|
+ @tab-click="tabClick"
|
|
|
+ >
|
|
|
+ <el-tab-pane
|
|
|
+ v-for="(item, dayIndex) in days"
|
|
|
+ :closable="formType != 3"
|
|
|
+ :key="dayIndex"
|
|
|
+ :name="dayIndex + ''"
|
|
|
+ >
|
|
|
+ <el-badge
|
|
|
+ slot="label"
|
|
|
+ :is-dot="!item.id"
|
|
|
+ class="item"
|
|
|
+ style="display: inline-block"
|
|
|
+ >
|
|
|
+ <span>{{ '第' + item.dayNum + '天' }}</span>
|
|
|
+ </el-badge>
|
|
|
+
|
|
|
+ <el-row v-loading="loading">
|
|
|
+ <el-col :span="22">
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ background-color: #fbfbfb;
|
|
|
+ padding: 15px;
|
|
|
+ border: 1px solid #e6e6e6;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <el-form
|
|
|
+ :model="item"
|
|
|
+ label-width="80px"
|
|
|
+ >
|
|
|
+ <el-form-item label="内容名称"
|
|
|
+ v-if="form.sendType != 4"
|
|
|
+ style="height: 50px;"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="item.name"
|
|
|
+ placeholder="内容名称,仅内部可见"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 具体规则 -->
|
|
|
+ <el-form-item label="规则">
|
|
|
+ <div
|
|
|
+ v-for="(ruleItem, ruleIndex) in item.rules"
|
|
|
+ :key="ruleIndex"
|
|
|
+ style="
|
|
|
+ background-color: #fdfdfd;
|
|
|
+ padding: 15px;
|
|
|
+ border: 1px solid #e6e6e6;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <el-row>
|
|
|
+ <el-col
|
|
|
+ :span="22"
|
|
|
+ >
|
|
|
+ <el-form
|
|
|
+ :model="ruleItem"
|
|
|
+ label-width="70px"
|
|
|
+ >
|
|
|
+ <!-- 第一天 -->
|
|
|
+ <div v-if="item.dayNum == 1">
|
|
|
+ <el-form-item
|
|
|
+ label="时间"
|
|
|
+ >
|
|
|
+ <el-time-picker
|
|
|
+ :disabled="formType == 3"
|
|
|
+ class="custom-input"
|
|
|
+ v-model="ruleItem.time"
|
|
|
+ value-format="HH:mm"
|
|
|
+ format="HH:mm"
|
|
|
+ :picker-options="{ selectableRange: ['01:00:00 - 01:30:00','05:00:00 - 23:59:59'] }"
|
|
|
+ placeholder="时间"
|
|
|
+ style="width: 100px;height: 20px;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 其他天 -->
|
|
|
+ <div v-else>
|
|
|
+ <el-form-item
|
|
|
+ label="时间"
|
|
|
+ >
|
|
|
+ <el-time-picker
|
|
|
+ :disabled="formType == 3"
|
|
|
+ class="custom-input"
|
|
|
+ v-model="ruleItem.time"
|
|
|
+ value-format="HH:mm"
|
|
|
+ format="HH:mm"
|
|
|
+ :picker-options="{ selectableRange: ['00:01:00 - 00:30:00','05:00:00 - 23:59:59']}"
|
|
|
+ placeholder="时间"
|
|
|
+ style="width: 100px;height: 20px;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 填写条件:第一条,且消息类型为科普 -->
|
|
|
+ <el-form-item label="官方群发"
|
|
|
+ v-if="ruleIndex == 0 && ruleItem.type == 2"
|
|
|
+ >
|
|
|
+ <el-switch
|
|
|
+ v-model="ruleItem.isOfficial"
|
|
|
+ active-color="#13ce66"
|
|
|
+ inactive-color="#DCDFE6"
|
|
|
+ :active-value="ruleIndex === 0 ? 1 : 0"
|
|
|
+ :inactive-value="0"
|
|
|
+ @change="isOfficialChange(ruleItem)"
|
|
|
+ :disabled="ruleIndex !== 0"
|
|
|
+ >
|
|
|
+ </el-switch>
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ color: #999;
|
|
|
+ font-size: 14px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 5px
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ 请注意:官方群发 【第1天】 只能设置1点-1点30 的时间,【其他天数时间】 只能设置0点-0点30。此处仅为生成发送记录时间!<!-- 实际发送可由 客服在公司规定的【暂早上7点】,在企业微信的【群发助手】处点击发送 -->
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 禁用条件:操作为查看或内容为官方群发 -->
|
|
|
+ <el-form-item label="消息类别">
|
|
|
+ <el-radio-group
|
|
|
+ v-model="ruleItem.type"
|
|
|
+ :disabled="formType == 3 || ruleItem.isOfficial == '1'"
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <el-radio
|
|
|
+ v-for="dict in msgTypeOptions"
|
|
|
+ :key="dict.dictValue"
|
|
|
+ :label="Number(dict.dictValue)"
|
|
|
+ >
|
|
|
+ {{ dict.dictLabel }}
|
|
|
+ </el-radio>
|
|
|
+ </div>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="科普"
|
|
|
+ v-if="ruleItem.type == 2"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <!-- 禁用条件:操作类型为查看 -->
|
|
|
+ <el-select
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="ruleItem.courseId"
|
|
|
+ placeholder="默认50条,可输入关键字检索"
|
|
|
+ style=" margin-right: 10px; width: 230px;"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :loading="ruleItem.courseLoading"
|
|
|
+ remote
|
|
|
+ :remote-method="(keyword) => handleCourseRemoteSearch(keyword, ruleItem)"
|
|
|
+ @change="courseChangeUpdate(ruleItem, dayIndex, ruleIndex)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (ruleItem.meta && ruleItem.meta.courseList ? ruleItem.meta.courseList : [])"
|
|
|
+ :key="dict.dictValue"
|
|
|
+ :label="dict.dictLabel"
|
|
|
+ :value="parseInt(dict.dictValue)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+
|
|
|
+ <el-select
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="ruleItem.videoId"
|
|
|
+ placeholder="请选择小节"
|
|
|
+ size="mini"
|
|
|
+ style=" margin-right: 10px;"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ @change="videoIdChange(ruleItem, dayIndex, ruleIndex)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (ruleItem.meta && ruleItem.meta.videoList ? ruleItem.meta.videoList : [])"
|
|
|
+ :key="dict.dictValue"
|
|
|
+ :label="dict.dictLabel"
|
|
|
+ :value="parseInt(dict.dictValue)"
|
|
|
+ >
|
|
|
+ <div :style="{ color: dict.isPause == 1 ? '#f56c6c' : 'inherit', display: 'flex', alignItems: 'center' }">
|
|
|
+ <span>{{ dict.dictLabel }}</span>
|
|
|
+ <span v-if="dict.isPause == 1" style="font-size: 12px; margin-left: 8px; color: #f56c6c;">
|
|
|
+ (该科普已被关闭,无法正常发送)
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+
|
|
|
+ <!-- 禁用条件:操作类型为查看 -->
|
|
|
+ <!-- 渲染条件:消息类型不为AI触达 -->
|
|
|
+ <el-select
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="ruleItem.courseType"
|
|
|
+ placeholder="请选择消息类型"
|
|
|
+ size="mini"
|
|
|
+ style=" margin-right: 10px;"
|
|
|
+ v-if="ruleItem.type != 4 "
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in sysFsSopWatchStatus"
|
|
|
+ :key="dict.dictValue"
|
|
|
+ :label="dict.dictLabel"
|
|
|
+ :value="Number(dict.dictValue)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 科普相关填写项 -->
|
|
|
+ <div v-if="ruleItem.type == 2"
|
|
|
+ v-for="(content, contentIndex) in ruleItem.setting"
|
|
|
+ :key="contentIndex"
|
|
|
+ style="
|
|
|
+ background-color: #fdfdfd;
|
|
|
+ border: 1px solid #e6e6e6;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <el-row style="padding-bottom: 20px">
|
|
|
+ <el-col :span="22">
|
|
|
+ <el-form
|
|
|
+ :model="content"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-form-item label="内容类别"
|
|
|
+ style="margin: 2%"
|
|
|
+ >
|
|
|
+
|
|
|
+ <div v-if="form.sendType == 2">
|
|
|
+ <el-radio-group
|
|
|
+ v-model="content.contentType"
|
|
|
+ :disabled="formType == 3"
|
|
|
+ @change="handleContentTypeChange(ruleItem)"
|
|
|
+ >
|
|
|
+ <el-radio
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictValue"
|
|
|
+ :disabled="(ruleItem.type != 2 && [9].includes(Number(item.dictValue))
|
|
|
+ || (ruleItem.isOfficial == 1 && [6, 9, 12].includes(Number(item.dictValue))))"
|
|
|
+ v-for="item in sysQwSopAiContentType"
|
|
|
+ >{{ item.dictLabel }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 科普 -->
|
|
|
+ <el-form-item label="内容" v-if="content.contentType == 9">
|
|
|
+ <div>
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item
|
|
|
+ label="链接标题:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.linkTitle"
|
|
|
+ placeholder="请输入链接标题"
|
|
|
+ style="width: 90%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="链接描述:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ :disabled="formType == 3"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ v-model="content.linkDescribe"
|
|
|
+ placeholder="请输入链接描述"
|
|
|
+ style="width: 90%;margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="链接封面:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.linkImageUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :file-size="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ style="margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <div v-if="ruleItem.type != 2 " style="margin-top: 1%">
|
|
|
+ <el-form-item
|
|
|
+ label="链接地址:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.linkUrl"
|
|
|
+ placeholder="请输入链接地址"
|
|
|
+ style="width: 90%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ <div v-if="ruleItem.type == 2 ">
|
|
|
+ <el-form-item
|
|
|
+ label="链接地址:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-tag
|
|
|
+ type="warning"
|
|
|
+ v-model="content.isBindUrl = 1 "
|
|
|
+ >选择的科普小节
|
|
|
+ 即为卡片链接地址
|
|
|
+ </el-tag>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ <el-form-item label="课节过期时间">
|
|
|
+ <el-row>
|
|
|
+ <el-input
|
|
|
+ type="number"
|
|
|
+ v-model="content.expiresDays"
|
|
|
+ style="width: 200px"
|
|
|
+ >
|
|
|
+ <template slot="append">天</template>
|
|
|
+ </el-input>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <span class="tip">填写0或不填时,默认为系统配置的默认时间</span>
|
|
|
+ </el-row>
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 文本 -->
|
|
|
+ <el-form-item label="内容" v-else-if="content.contentType == 11">
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ color: #999;
|
|
|
+ font-size: 14px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ 多语句分割符:|&| 例如:'语句1|&|语句2'
|
|
|
+ </div>
|
|
|
+ <el-input
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.value"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ placeholder="内容"
|
|
|
+ style="width: 90%;margin-top: 10px;"
|
|
|
+ @keydown.native="handleKeydown($event, dayIndex, ruleIndex, contentIndex)"
|
|
|
+ :ref="`textarea-${dayIndex}-${ruleIndex}-${contentIndex}`"
|
|
|
+ />
|
|
|
+ <!-- 修改按钮部分 -->
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ @click="toggleSalesCall(dayIndex, ruleIndex, contentIndex)"
|
|
|
+ style="margin-top: 10px;"
|
|
|
+ >
|
|
|
+ {{ content.isSalesCallAdded ? '移除#客服称呼#' : '添加#客服称呼#' }}
|
|
|
+ </el-link>
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ style="margin-top: 10px;margin-left:10px"
|
|
|
+ @click="showOpenContent(dayIndex, ruleIndex, contentIndex)"
|
|
|
+ >
|
|
|
+ 查看分割内容
|
|
|
+ </el-link>
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ style="margin-top: 10px;margin-left:10px"
|
|
|
+ @click="cppySpliter()"
|
|
|
+ >
|
|
|
+ 复制分隔符
|
|
|
+ </el-link>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 语音 -->
|
|
|
+ <el-form-item label="内容" v-else-if="content.contentType == 12">
|
|
|
+ <div>
|
|
|
+ <el-input
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.value"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ maxlength="66"
|
|
|
+ show-word-limit
|
|
|
+ placeholder="输入要转为语音的内容"
|
|
|
+ style="width: 90%;margin-top: 10px;"
|
|
|
+ @input="handleInputVideoText(content.value, content)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 图片 -->
|
|
|
+ <el-form-item label="内容" v-else-if="content.contentType == 2">
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.imgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 视频 -->
|
|
|
+ <el-form-item label="内容" v-else-if="content.contentType == 6">
|
|
|
+ <div>
|
|
|
+ <el-upload
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.videoUrl"
|
|
|
+ class="avatar-uploader"
|
|
|
+ :action="uploadUrl"
|
|
|
+ :show-file-list="false"
|
|
|
+ :on-success="(res, file) => handleAvatarSuccessVideo(res, file, content)"
|
|
|
+ :before-upload="beforeAvatarUploadVideo"
|
|
|
+ >
|
|
|
+ <i class="el-icon-plus avatar-uploader-icon"></i>
|
|
|
+ </el-upload>
|
|
|
+ <video
|
|
|
+ v-if="content.videoUrl"
|
|
|
+ :src="content.videoUrl"
|
|
|
+ controls
|
|
|
+ style="width: 200px;height: 100px"
|
|
|
+ >
|
|
|
+ </video>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 疗法 -->
|
|
|
+ <el-form-item label="内容" v-else-if="content.contentType == 20">
|
|
|
+
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item
|
|
|
+ label="选择疗法:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ :disabled="formType == 3"
|
|
|
+ v-model="content.packageId"
|
|
|
+ placeholder="默认50条,可输入关键字检索"
|
|
|
+ style=" margin-right: 10px; width: 230px;"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :loading="content.meta.pkgLoading"
|
|
|
+ remote
|
|
|
+ :remote-method="(keyword) => handlePkgRemoteSearch(keyword, content)"
|
|
|
+ @change="pkgChangeUpdate(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (content.meta && content.meta.pkgList ? content.meta.pkgList : [])"
|
|
|
+ :key="dict.packageId"
|
|
|
+ :label="`${dict.packageName}(${dict.packageId})`"
|
|
|
+ :value="parseInt(dict.packageId)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="疗法名称:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ disabled
|
|
|
+ :rows="3"
|
|
|
+ v-model="content.packageName"
|
|
|
+ style="width: 90%;margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="疗法封面:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="true"
|
|
|
+ v-model="content.packageImgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :file-size="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ style="margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 直播 -->
|
|
|
+ <el-form-item label="内容" v-else-if="content.contentType == 21">
|
|
|
+ <div>
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item label="直播分组"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="content.liveGroupTypeId"
|
|
|
+ placeholder="请选择直播分组"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :disabled="formType == 3"
|
|
|
+ @change="liveGroupTypeChange(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in liveGroupTypeList"
|
|
|
+ :key="dict.id"
|
|
|
+ :label="dict.liveGroupType"
|
|
|
+ :value="dict.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="直播间"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="content.liveId"
|
|
|
+ placeholder="请先选择直播分组"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ :disabled="formType == 3 || !content.liveGroupTypeId"
|
|
|
+ @change="liveChange(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (content.meta && content.meta.liveList ? content.meta.liveList : [])"
|
|
|
+ :key="dict.liveId"
|
|
|
+ :label="dict.liveName"
|
|
|
+ :value="parseInt(dict.liveId)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="标题"
|
|
|
+ prop="liveTitle"
|
|
|
+ style="margin-bottom: 5px;"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-model="content.liveTitle"
|
|
|
+ placeholder="请输入消息标题,最长为64字节"
|
|
|
+ :rows="2"
|
|
|
+ maxlength="64"
|
|
|
+ type="textarea"
|
|
|
+ disabled
|
|
|
+ @input="checkByteLength(content.contentType, 'liveTitle')"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="封面"
|
|
|
+ prop="liveImgUrl"
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ v-model="content.liveImgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="10"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ disabled
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 民品 -->
|
|
|
+ <el-form-item label="内容" v-else-if="22 == content.contentType">
|
|
|
+ <div>
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item
|
|
|
+ label="选择民品:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="content.productId"
|
|
|
+ placeholder="默认50条,可输入关键字检索"
|
|
|
+ style=" margin-right: 10px; width: 230px;"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :loading="content.meta.productLoading"
|
|
|
+ remote
|
|
|
+ :remote-method="(keyword) => handleProductRemoteSearch(keyword, content)"
|
|
|
+ @change="productChangeUpdate(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (content.meta && content.meta.productList ? content.meta.productList : [])"
|
|
|
+ :key="dict.productId"
|
|
|
+ :label="`${dict.productName}(${dict.productId})`"
|
|
|
+ :value="parseInt(dict.productId)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="民品名称:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ disabled
|
|
|
+ :rows="3"
|
|
|
+ v-model="content.productName"
|
|
|
+ style="width: 90%;margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="民品封面:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="true"
|
|
|
+ v-model="content.productImgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :file-size="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ style="margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 药品 -->
|
|
|
+ <el-form-item label="内容" v-else-if="23 == content.contentType">
|
|
|
+ <div>
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item
|
|
|
+ label="选择药品:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="content.medicinesId"
|
|
|
+ placeholder="默认50条,可输入关键字检索"
|
|
|
+ style=" margin-right: 10px; width: 230px;"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :loading="content.meta.medicinesLoading"
|
|
|
+ remote
|
|
|
+ :remote-method="(keyword) => handleMedicinesRemoteSearch(keyword, content)"
|
|
|
+ @change="medicinesChangeUpdate(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (content.meta && content.meta.medicinesList ? content.meta.medicinesList : [])"
|
|
|
+ :key="dict.productId"
|
|
|
+ :label="`${dict.productName}(${dict.productId})`"
|
|
|
+ :value="parseInt(dict.productId)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="药品名称:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ disabled
|
|
|
+ :rows="3"
|
|
|
+ v-model="content.medicinesName"
|
|
|
+ style="width: 90%;margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="药品封面:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="true"
|
|
|
+ v-model="content.medicinesImgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :file-size="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ style="margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 短视频 -->
|
|
|
+ <el-form-item label="内容" v-else-if="24 == content.contentType">
|
|
|
+ <div>
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item
|
|
|
+ label="选择短视频:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="content.shortVideoId"
|
|
|
+ placeholder="默认50条,可输入关键字检索"
|
|
|
+ style=" margin-right: 10px; width: 230px;"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :loading="content.meta.shortVideoLoading"
|
|
|
+ remote
|
|
|
+ :remote-method="(keyword) => handleShortVideoRemoteSearch(keyword, content)"
|
|
|
+ @change="shortVideoChangeUpdate(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (content.meta && content.meta.shortVideoList ? content.meta.shortVideoList : [])"
|
|
|
+ :key="dict.videoId"
|
|
|
+ :label="`${dict.title}(${dict.videoId})`"
|
|
|
+ :value="parseInt(dict.videoId)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="短视频名称:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ disabled
|
|
|
+ :rows="3"
|
|
|
+ v-model="content.shortVideoName"
|
|
|
+ style="width: 90%;margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="短视频封面:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="true"
|
|
|
+ v-model="content.shortVideoImgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :file-size="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ style="margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 文章 -->
|
|
|
+ <el-form-item label="内容" v-else-if="25 == content.contentType">
|
|
|
+ <div>
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item
|
|
|
+ label="选择文章:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="content.articleId"
|
|
|
+ placeholder="默认50条,可输入关键字检索"
|
|
|
+ style=" margin-right: 10px; width: 230px;"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :loading="content.meta.articleLoading"
|
|
|
+ remote
|
|
|
+ :remote-method="(keyword) => handleArticleRemoteSearch(keyword, content)"
|
|
|
+ @change="articleChangeUpdate(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (content.meta && content.meta.articleList ? content.meta.articleList : [])"
|
|
|
+ :key="dict.articleId"
|
|
|
+ :label="`${dict.title}(${dict.articleId})`"
|
|
|
+ :value="parseInt(dict.articleId)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="文章名称:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ disabled
|
|
|
+ :rows="3"
|
|
|
+ v-model="content.articleName"
|
|
|
+ style="width: 90%;margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="文章封面:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="true"
|
|
|
+ v-model="content.articleImgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :file-size="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ style="margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 公开课 -->
|
|
|
+ <el-form-item label="内容" v-else-if="26 == content.contentType">
|
|
|
+ <div>
|
|
|
+ <el-card class="box-card">
|
|
|
+ <el-form-item
|
|
|
+ label="选择公开课:"
|
|
|
+ label-width="100px"
|
|
|
+ required
|
|
|
+ >
|
|
|
+ <el-select
|
|
|
+ v-model="content.openClassVideoId"
|
|
|
+ placeholder="默认50条,可输入关键字检索"
|
|
|
+ style=" margin-right: 10px; width: 230px;"
|
|
|
+ size="mini"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ :loading="content.meta.openClassVideoLoading"
|
|
|
+ remote
|
|
|
+ :remote-method="(keyword) => handleOpenClassVideoRemoteSearch(keyword, content)"
|
|
|
+ @change="openClassVideoChangeUpdate(content)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="dict in (content.meta && content.meta.openClassVideoList ? content.meta.openClassVideoList : [])"
|
|
|
+ :key="dict.videoId"
|
|
|
+ :label="`${dict.title}(${dict.videoId})`"
|
|
|
+ :value="parseInt(dict.videoId)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="公开课名称:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ disabled
|
|
|
+ :rows="3"
|
|
|
+ v-model="content.openClassVideoName"
|
|
|
+ style="width: 90%;margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="公开课封面:"
|
|
|
+ label-width="100px"
|
|
|
+ >
|
|
|
+ <ImageUpload
|
|
|
+ :disabled="true"
|
|
|
+ v-model="content.openClassVideoImgUrl"
|
|
|
+ type="image"
|
|
|
+ :num="1"
|
|
|
+ :file-size="1"
|
|
|
+ :width="150"
|
|
|
+ :height="150"
|
|
|
+ style="margin-top: 1%;"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <el-col
|
|
|
+ :span="1"
|
|
|
+ :offset="1"
|
|
|
+ >
|
|
|
+ <!-- 删除内容节点 -->
|
|
|
+ <i
|
|
|
+ class="el-icon-delete"
|
|
|
+ @click="delContentNode(dayIndex, ruleIndex, contentIndex)"
|
|
|
+ style="margin-top: 20px;"
|
|
|
+ v-if="ruleItem.setting.length > 1 && (formType != 3)"
|
|
|
+ ></i>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 改状态(已停用,暂注释)
|
|
|
+ <div v-if="ruleItem.type == 5"
|
|
|
+ style="
|
|
|
+ background-color: #fdfdfd;
|
|
|
+ border: 1px solid #e6e6e6;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding: 8px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+
|
|
|
+ <el-form-item label="添加标签" style="padding: 5px;">
|
|
|
+ <div>
|
|
|
+ <el-button size="medium" icon="el-icon-circle-plus-outline" plain
|
|
|
+ @click="openTagPage(ruleItem, 0)">添加标签</el-button>
|
|
|
+ </div>
|
|
|
+ <div style="padding-left: 5px;">
|
|
|
+ <el-tag style="margin-left: 5px" size="medium" :key="s.id" v-for="s in ruleItem.addTag" closable
|
|
|
+ :disable-transitions="false" @close="handleCloseTag(ruleItem, 0, s)">
|
|
|
+ <span>{{ s.name }}</span>
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="移除标签" style="padding: 5px;">
|
|
|
+ <div>
|
|
|
+ <el-button size="medium" icon="el-icon-circle-plus-outline" plain
|
|
|
+ @click="openTagPage(ruleItem, 1)">移除标签</el-button>
|
|
|
+ </div>
|
|
|
+ <div style="padding-left: 5px;">
|
|
|
+ <el-tag style="margin-left: 5px" size="medium" :key="s.id" v-for="s in ruleItem.delTag" closable
|
|
|
+ :disable-transitions="false" @close="handleCloseTag(ruleItem, 1, s)">
|
|
|
+ <span>{{ s.name }}</span>
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="绑定客服" style="padding: 5px;">
|
|
|
+ <div>
|
|
|
+ <el-button size="medium" icon="el-icon-circle-plus-outline" plain
|
|
|
+ @click="openCustomerPage(ruleItem, 0)">绑定客服</el-button>
|
|
|
+ </div>
|
|
|
+ <div style="padding-left: 5px;">
|
|
|
+ <el-tag style="margin-left: 5px" size="medium" :key="s.id" v-for="s in ruleItem.addCustomer" closable
|
|
|
+ :disable-transitions="false" @close="handleCloseCustomer(ruleItem, 0, s)">
|
|
|
+ <span>{{ s.roleName }}</span>
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="解绑客服" style="padding: 5px;">
|
|
|
+ <div>
|
|
|
+ <el-button size="medium" icon="el-icon-circle-plus-outline" plain
|
|
|
+ @click="openCustomerPage(ruleItem, 1)">解绑客服</el-button>
|
|
|
+ </div>
|
|
|
+ <div style="padding-left: 5px;">
|
|
|
+ <el-tag style="margin-left: 5px" size="medium" :key="s.id" v-for="s in ruleItem.delCustomer" closable
|
|
|
+ :disable-transitions="false" @close="handleCloseCustomer(ruleItem, 1, s)">
|
|
|
+ <span>{{ s.roleName }}</span>
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ -->
|
|
|
+
|
|
|
+ <!-- 添加内容节点 -->
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ class="el-icon-plus"
|
|
|
+ :underline="false"
|
|
|
+ @click='addContentNode(ruleItem)'
|
|
|
+ v-if="formType != 3 && [2].includes(Number(ruleItem.type))"
|
|
|
+ >添加内容
|
|
|
+ </el-link>
|
|
|
+
|
|
|
+ </el-form>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <el-col
|
|
|
+ :span="1"
|
|
|
+ :offset="1"
|
|
|
+ >
|
|
|
+ <i
|
|
|
+ class="el-icon-delete"
|
|
|
+ @click="delRuleNode(dayIndex, ruleIndex)"
|
|
|
+ style="margin-top: 20px;"
|
|
|
+ v-if="item.rules.length > 1 && formType != 3"
|
|
|
+ ></i>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 操作为非查看,且模板类型不为 新客对话和群聊则可以添加规则 -->
|
|
|
+ <el-link
|
|
|
+ type="primary"
|
|
|
+ class="el-icon-plus"
|
|
|
+ :underline="false"
|
|
|
+ @click='addRuleNode(dayIndex)'
|
|
|
+ v-if="formType != 3 && form.sendType != 4 && form.sendType != 5"
|
|
|
+ >
|
|
|
+ 添加规则
|
|
|
+ </el-link>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 操作为非查看 -->
|
|
|
+ <div
|
|
|
+ v-if="formType != 3"
|
|
|
+ style="float: right;"
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="saveDay"
|
|
|
+ v-if="!item.voice || item.voice == 0"
|
|
|
+ >
|
|
|
+ 保存({{ '第' + (1 + (form.gap * dayIndex)) + '天' }})
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ disabled
|
|
|
+ v-if="item.voice == 1"
|
|
|
+ >
|
|
|
+ 语言生成中
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="leave(tabIndex)"
|
|
|
+ v-if="item.voice == 1"
|
|
|
+ >
|
|
|
+ 刷新状态
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ title="修改天数排序"
|
|
|
+ :visible.sync="openSort"
|
|
|
+ width="1500px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <draggable
|
|
|
+ v-model="dayList"
|
|
|
+ @end="onDragEndDay"
|
|
|
+ style="padding: 20px"
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ v-for="(item, dayIndex) in dayList"
|
|
|
+ :class="item.newDay != item.dayNum ? 'red':''"
|
|
|
+ >第{{
|
|
|
+ item.newDay
|
|
|
+ }}天(第{{ item.dayNum }}天)
|
|
|
+ </el-button>
|
|
|
+ </draggable>
|
|
|
+
|
|
|
+ <div style="float: right;" slot="footer">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="saveSorts"
|
|
|
+ >保存</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ title="修改规则排序"
|
|
|
+ :visible.sync="openSort2"
|
|
|
+ width="1500px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <draggable
|
|
|
+ v-model="ruleList"
|
|
|
+ @end="onDragEnd"
|
|
|
+ style="padding: 20px"
|
|
|
+ >
|
|
|
+ <el-button v-for="(item, ruleIndex) in ruleList">{{ item.time }}</el-button>
|
|
|
+ </draggable>
|
|
|
+
|
|
|
+ <div style="float: right;" slot="footer">
|
|
|
+ <el-button @click="autoSortsRules">自动排序</el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="saveSortsRules"
|
|
|
+ >保存</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ title="查看分割后内容"
|
|
|
+ :visible.sync="openShowContent"
|
|
|
+ width="800px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <el-table
|
|
|
+ stripe
|
|
|
+ :data="contentListData"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-table-column
|
|
|
+ type="index"
|
|
|
+ label="序号"
|
|
|
+ width="50"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column
|
|
|
+ prop="content"
|
|
|
+ label="内容"
|
|
|
+ width="700"
|
|
|
+ >
|
|
|
+ <template #default="{ row }">
|
|
|
+ <div v-html="row.content.replace(/\n/g, '<br>')"></div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <div style="float: right;">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="comfirmContent"
|
|
|
+ >确定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 绑定app客服角色 -->
|
|
|
+ <el-dialog title="选择绑定的客服"
|
|
|
+ :visible.sync="customerConfigForBind.visible"
|
|
|
+ width="1300px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <CusRoleList
|
|
|
+ :selected="customerConfigForBind.selected"
|
|
|
+ @confirm="customerConfirmCallForBind"
|
|
|
+ @selectionChange="customerSelectionChangeCallForBind"
|
|
|
+ />
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 解绑app客服角色 -->
|
|
|
+ <el-dialog title="选择解绑的客服"
|
|
|
+ :visible.sync="customerConfigForUnbind.visible"
|
|
|
+ width="1300px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <CusRoleList
|
|
|
+ :selected="customerConfigForUnbind.selected"
|
|
|
+ @confirm="customerConfirmCallForUnbind"
|
|
|
+ @selectionChange="customerSelectionChangeCallForUnbind"
|
|
|
+ />
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 绑定标签 -->
|
|
|
+ <el-dialog title="选择绑定的标签"
|
|
|
+ :visible.sync="tagConfigForBind.visible"
|
|
|
+ width="1000px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <select-tag
|
|
|
+ :tagSelected="tagConfigForBind.selected"
|
|
|
+ @tagSubmit="tagSubmitForBind"
|
|
|
+ @tagCancel="tagCancelForBind"
|
|
|
+ @tagSelection="tagSelectionChangeCallForBind"
|
|
|
+ />
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 解绑标签 -->
|
|
|
+ <el-dialog title="选择解绑的标签"
|
|
|
+ :visible.sync="tagConfigForUnbind.visible"
|
|
|
+ width="1000px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <select-tag
|
|
|
+ :tagSelected="tagConfigForUnbind.selected"
|
|
|
+ @tagSubmit="tagSubmitForUnbind"
|
|
|
+ @tagCancel="tagCancelForUnbind"
|
|
|
+ @tagSelection="tagSelectionChangeCallForUnbind"
|
|
|
+ />
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+import draggable from 'vuedraggable';
|
|
|
+import {
|
|
|
+ listSopTemp,
|
|
|
+ getSopTemp,
|
|
|
+ sortDay,
|
|
|
+ dayListFun,
|
|
|
+ addOrUpdateSetting,
|
|
|
+ selectRulesInfo,
|
|
|
+ delRules
|
|
|
+} from "@/api/app/sop/template";
|
|
|
+import {courseList, videoList} from "@/api/app/course";
|
|
|
+import { getPackageOptions,} from "@/api/app/pkg";
|
|
|
+import { getLiveOptions as fetchLiveOptionsApi, getLiveGroupTypeList as fetchLiveGroupTypeListApi } from "@/api/app/live";
|
|
|
+import { listRole } from '@/api/app/user/userList';
|
|
|
+import { getTagByIds } from "@/api/app/tag/tagGroup";
|
|
|
+import ImageUpload from "@/views/qw/sop/ImageUpload";
|
|
|
+import { getMedicinesOptions, } from "@/api/app/medicines";
|
|
|
+import { getProductOptions, } from "@/api/app/product";
|
|
|
+import { getShortVideoOptions, } from "@/api/app/shortVideo";
|
|
|
+import { getArticleOptions } from "@/api/app/article";
|
|
|
+import { getOpenClassVideoOptions, } from "@/api/app/openClassVideo";
|
|
|
+
|
|
|
+import selectTag from "@/views/app/tagGroup/selectTag.vue";
|
|
|
+import CusRoleList from '@/views/app/user/CusRoleList.vue';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "UpdateSopTemp",
|
|
|
+ components: { ImageUpload, draggable, selectTag, CusRoleList, },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ uploadUrl: process.env.VUE_APP_BASE_API + "/app/common/uploadOSS2",
|
|
|
+ uploadUrlByVoice: process.env.VUE_APP_BASE_API + "/app/common/uploadOSSByHOOKVoice",
|
|
|
+ //上传语音的遮罩层
|
|
|
+ voiceLoading: false,
|
|
|
+ openSort: false,
|
|
|
+ openSort2: false,
|
|
|
+ openShowContent: false,
|
|
|
+ contentList: [],
|
|
|
+ contentListData: [],
|
|
|
+ // 遮罩层
|
|
|
+ loading: false,
|
|
|
+ loading2: false,
|
|
|
+ loading3: false,
|
|
|
+ // 导出遮罩层
|
|
|
+ exportLoading: false,
|
|
|
+ // 选中数组
|
|
|
+ dayList: [],
|
|
|
+ ruleList: [],
|
|
|
+ ids: [],
|
|
|
+ sysFsSopWatchStatus: [],
|
|
|
+ //插件版
|
|
|
+ sysQwSopAiContentType: [],
|
|
|
+ msgTypeOptions: [],//消息类别选项
|
|
|
+ courseList: [],//默认科普
|
|
|
+ pkgList: [],//默认疗法
|
|
|
+ liveGroupTypeList: [],//直播分组
|
|
|
+ liveList: [],//默认直播间
|
|
|
+ productList: [],//默认民品列表
|
|
|
+ medicinesList: [],//默认药品列表
|
|
|
+ shortVideoList: [],//默认短视频列表
|
|
|
+ articleList: [],//默认文章列表
|
|
|
+ openClassVideoList: [],//默认公开课列表
|
|
|
+ // 非单个禁用
|
|
|
+ single: true,
|
|
|
+ // 非多个禁用
|
|
|
+ multiple: true,
|
|
|
+ // 显示搜索条件
|
|
|
+ showSearch: true,
|
|
|
+ // 总条数
|
|
|
+ id: "",
|
|
|
+ total: 0,
|
|
|
+ tabIndex: null,
|
|
|
+ // sop模板天数列表
|
|
|
+ days: [],
|
|
|
+ data: [],
|
|
|
+ // 弹出层标题
|
|
|
+ title: "",
|
|
|
+ // 是否显示弹出层
|
|
|
+ open: false,
|
|
|
+ // 状态字典
|
|
|
+ statusOptions: [],
|
|
|
+ videoNumOptions: {
|
|
|
+ title: '选择视频号',
|
|
|
+ open: false,
|
|
|
+ content: null,
|
|
|
+ rulesIndex: null,
|
|
|
+ contentIndex: null,
|
|
|
+ },
|
|
|
+ //1 修改 2 复制 3 查看
|
|
|
+ formType: null,
|
|
|
+ queryParams1: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ dataStatus: '1',
|
|
|
+ name: null,
|
|
|
+ type: null
|
|
|
+ },
|
|
|
+ // 查询参数
|
|
|
+ form: {
|
|
|
+ name: null,
|
|
|
+ setting: null,
|
|
|
+ status: "1",
|
|
|
+ sort: 1,
|
|
|
+ companyId: null,
|
|
|
+ gap: 1,
|
|
|
+ },
|
|
|
+ // 表单校验
|
|
|
+ rules: {
|
|
|
+ name: [
|
|
|
+ { required: true, message: '名称不能为空', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ status: [
|
|
|
+ { required: true, message: '状态不能为空', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ sort: [
|
|
|
+ { required: true, message: '排序不能为空', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ gap: [
|
|
|
+ { required: true, message: '间隔天数不能为空', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ customerConfigForBind: {
|
|
|
+ visible: false,
|
|
|
+ selected: [],
|
|
|
+ currentRuleItem: null,
|
|
|
+ },
|
|
|
+ customerConfigForUnbind: {
|
|
|
+ visible: false,
|
|
|
+ selected: [],
|
|
|
+ currentRuleItem: null,
|
|
|
+ },
|
|
|
+ tagConfigForBind: {
|
|
|
+ visible: false,
|
|
|
+ selected: [],
|
|
|
+ currentRuleItem: null,
|
|
|
+ },
|
|
|
+ tagConfigForUnbind: {
|
|
|
+ visible: false,
|
|
|
+ selected: [],
|
|
|
+ currentRuleItem: null,
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.init();
|
|
|
+ //模板id
|
|
|
+ const id = this.$route.params && this.$route.params.id;
|
|
|
+ this.id = id;
|
|
|
+ //表单操作类型,1 修改 2 复制 3 查看
|
|
|
+ this.formType = this.$route.params && this.$route.params.type;
|
|
|
+ this.initTempInfo(id);
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async init() {
|
|
|
+ this.getDicts("app_sop_plugin_settingType").then(response => {
|
|
|
+ this.sysQwSopAiContentType = response.data;
|
|
|
+ });
|
|
|
+ this.getDicts("app_sop_watch_status").then(response => {
|
|
|
+ this.sysFsSopWatchStatus = response.data;
|
|
|
+ });
|
|
|
+ this.getDicts("app_sop_msg_type").then(response => {
|
|
|
+ // 改状态(dictValue=5)已停用,页面过滤掉该选项
|
|
|
+ this.msgTypeOptions = (response.data || []).filter(d => Number(d.dictValue) !== 5);
|
|
|
+ });
|
|
|
+ this.getDicts("app_normal_disabled_status").then(response => {
|
|
|
+ this.statusOptions = response.data;
|
|
|
+ });
|
|
|
+ try {
|
|
|
+ const [
|
|
|
+ courseInfo,
|
|
|
+ defaultPkg,
|
|
|
+ defaultLiveGroup,
|
|
|
+ defaultArticle,
|
|
|
+ defaultOpenClassVideo,
|
|
|
+ ] = await Promise.all([
|
|
|
+ this.getCourseList(null, null),
|
|
|
+ this.getPkgList(null, null),
|
|
|
+ this.fetchLiveGroupTypeList(),
|
|
|
+ this.getArticleList(null, null),
|
|
|
+ this.getOpenClassVideoList(null, null),
|
|
|
+ ]);
|
|
|
+ this.courseList = (courseInfo && courseInfo.list) || [];
|
|
|
+ this.pkgList = (defaultPkg && defaultPkg.data) || [];
|
|
|
+ this.liveGroupTypeList = (defaultLiveGroup && (defaultLiveGroup.rows || defaultLiveGroup.data)) || [];
|
|
|
+ // 民品/药品/短视频接口暂不放开,避免控制台报错
|
|
|
+ // this.productList = ...
|
|
|
+ // this.medicinesList = ...
|
|
|
+ // this.shortVideoList = ...
|
|
|
+ this.articleList = (defaultArticle && defaultArticle.data) || [];
|
|
|
+ this.openClassVideoList = (defaultOpenClassVideo && defaultOpenClassVideo.data) || [];
|
|
|
+ } catch (e) {
|
|
|
+ console.error('SOP模板下拉数据加载失败', e);
|
|
|
+ this.courseList = this.courseList || [];
|
|
|
+ this.pkgList = this.pkgList || [];
|
|
|
+ this.liveGroupTypeList = this.liveGroupTypeList || [];
|
|
|
+ this.articleList = this.articleList || [];
|
|
|
+ this.openClassVideoList = this.openClassVideoList || [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 获取科普信息
|
|
|
+ */
|
|
|
+ async getCourseList(keyword, selectedId) {
|
|
|
+ let data = {
|
|
|
+ keyword: keyword,
|
|
|
+ selectedId: selectedId,
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 50,
|
|
|
+ };
|
|
|
+ return await courseList(data);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 获取疗法信息
|
|
|
+ */
|
|
|
+ async getPkgList(keyword, selectedId) {
|
|
|
+ let data = {
|
|
|
+ keyword: keyword,
|
|
|
+ metaId: selectedId,
|
|
|
+ limit: 50
|
|
|
+ };
|
|
|
+ return await getPackageOptions(data);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 获取直播分组下拉
|
|
|
+ */
|
|
|
+ async fetchLiveGroupTypeList() {
|
|
|
+ return await fetchLiveGroupTypeListApi({ pageNum: 1, pageSize: 999 });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 获取直播间下拉
|
|
|
+ * @param liveGroupType 直播分组id
|
|
|
+ */
|
|
|
+ async fetchLiveOptionsByGroup(liveGroupType) {
|
|
|
+ if (!liveGroupType) {
|
|
|
+ return { data: [] };
|
|
|
+ }
|
|
|
+ return await fetchLiveOptionsApi({ liveGroupType });
|
|
|
+ },
|
|
|
+ // /**
|
|
|
+ // * 获取民品列表
|
|
|
+ // * @param keyword
|
|
|
+ // * @param selectedId
|
|
|
+ // */
|
|
|
+ // async getProductList(keyword, selectedId) {
|
|
|
+ // let data = {
|
|
|
+ // keyword: keyword,
|
|
|
+ // metaId: selectedId,
|
|
|
+ // limit: 50
|
|
|
+ // };
|
|
|
+ // return await getProductOptions(data);
|
|
|
+ // },
|
|
|
+ // /**
|
|
|
+ // * 获取药品列表
|
|
|
+ // * @param keyword
|
|
|
+ // * @param selectedId
|
|
|
+ // */
|
|
|
+ // async getMedicinesList(keyword, selectedId) {
|
|
|
+ // let data = {
|
|
|
+ // keyword: keyword,
|
|
|
+ // metaId: selectedId,
|
|
|
+ // limit: 50
|
|
|
+ // };
|
|
|
+ // return await getMedicinesOptions(data);
|
|
|
+ // },
|
|
|
+ // /**
|
|
|
+ // * 获取短视频列表
|
|
|
+ // * @param keyword
|
|
|
+ // * @param selectedId
|
|
|
+ // */
|
|
|
+ // async getShortVideoList(keyword, selectedId) {
|
|
|
+ // let data = {
|
|
|
+ // keyword: keyword,
|
|
|
+ // metaId: selectedId,
|
|
|
+ // limit: 50
|
|
|
+ // };
|
|
|
+ // return await getShortVideoOptions(data);
|
|
|
+ // },
|
|
|
+ /**
|
|
|
+ * 获取文章列表
|
|
|
+ * @param keyword
|
|
|
+ * @param selectedId
|
|
|
+ */
|
|
|
+ async getArticleList(keyword, selectedId) {
|
|
|
+ let data = {
|
|
|
+ keyword: keyword,
|
|
|
+ metaId: selectedId,
|
|
|
+ limit: 50
|
|
|
+ };
|
|
|
+ return await getArticleOptions(data);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 获取公开课列表
|
|
|
+ * @param keyword
|
|
|
+ * @param selectedId
|
|
|
+ */
|
|
|
+ async getOpenClassVideoList(keyword, selectedId) {
|
|
|
+ let data = {
|
|
|
+ keyword: keyword,
|
|
|
+ metaId: selectedId,
|
|
|
+ limit: 50
|
|
|
+ };
|
|
|
+ return await getOpenClassVideoOptions(data);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 处理输入值不为5的倍数
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ handleIntervalTimeInput(content) {
|
|
|
+ // 确保输入值为5的倍数
|
|
|
+ if (content.intervalTime % 5 !== 0) {
|
|
|
+ // 四舍五入到最近的5的倍数
|
|
|
+ content.intervalTime = Math.round(content.intervalTime / 5) * 5;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 检查字节长度
|
|
|
+ * @param content
|
|
|
+ * @param key
|
|
|
+ */
|
|
|
+ checkByteLength(content, key) {
|
|
|
+ let cont = content[key];
|
|
|
+ if (cont) {
|
|
|
+ const byteLength = this.getByteLength(cont); // 获取当前字节数
|
|
|
+ // 如果字节数超过64,截断输入内容
|
|
|
+ if (byteLength > 64) {
|
|
|
+ this.$set(content, key, this.truncateTextByByteLength(cont, 60));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 计算字符串的字节数
|
|
|
+ getByteLength(text) {
|
|
|
+ return new Blob([text]).size; // 使用 Blob 计算字节数
|
|
|
+ },
|
|
|
+ // 根据字节数截断字符串
|
|
|
+ truncateTextByByteLength(text, maxByteLength) {
|
|
|
+ let byteLength = 0;
|
|
|
+ let result = "";
|
|
|
+
|
|
|
+ for (let i = 0; i < text.length; i++) {
|
|
|
+ const char = text[i];
|
|
|
+ const charByteLength = this.getByteLength(char); // 获取当前字符的字节数
|
|
|
+
|
|
|
+ // 如果加上当前字符的字节数后不超过限制,则添加到结果中
|
|
|
+ if (byteLength + charByteLength <= maxByteLength) {
|
|
|
+ result += char;
|
|
|
+ byteLength += charByteLength;
|
|
|
+ } else {
|
|
|
+ break; // 超过限制时停止
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 保存排序
|
|
|
+ */
|
|
|
+ saveSorts() {
|
|
|
+ let list = this.dayList.filter(e => e.dayNum != e.newDay).map(e => {
|
|
|
+ return { dayNum: e.newDay, id: e.id }
|
|
|
+ })
|
|
|
+ this.loading3 = true;
|
|
|
+ if (!list || list.length == 0) {
|
|
|
+ this.$message.closeAll();
|
|
|
+ return this.msgError('请修改排序!');
|
|
|
+ }
|
|
|
+ sortDay(list).then(e => {
|
|
|
+ window.location.reload();
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ */
|
|
|
+ saveSortsRules() {
|
|
|
+ this.$set(this.days[this.tabIndex], 'rules', this.ruleList);
|
|
|
+ this.openSort2 = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 自动排序
|
|
|
+ */
|
|
|
+ autoSortsRules() {
|
|
|
+ this.ruleList = this.ruleList.sort((a, b) => {
|
|
|
+ // 将 time 字段转换为 Date 对象进行比较
|
|
|
+ const timeA = new Date(`1970-01-01T${a.time}Z`);
|
|
|
+ const timeB = new Date(`1970-01-01T${b.time}Z`);
|
|
|
+
|
|
|
+ // 比较时间顺序
|
|
|
+ return timeA - timeB; // 升序排序
|
|
|
+ });
|
|
|
+ },
|
|
|
+ openUpdateDaySorts() {
|
|
|
+ dayListFun(this.id).then(response => {
|
|
|
+ response.data.forEach((item) => item.newDay = item.dayNum);
|
|
|
+ this.dayList = response.data;
|
|
|
+ if (this.dayList == null || this.dayList.length == 0) {
|
|
|
+ this.$message.error("暂无天数")
|
|
|
+ } else {
|
|
|
+ this.openSort = true;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ openUpdateSorts() {
|
|
|
+ this.ruleList = JSON.parse(JSON.stringify(this.days[this.tabIndex].rules));
|
|
|
+ if (this.ruleList == null || this.ruleList.length == 0) {
|
|
|
+ this.$message.error("暂无规则")
|
|
|
+ } else {
|
|
|
+ this.openSort2 = true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onDragEndDay() {
|
|
|
+ this.dayList.forEach((item, dayIndex) => {
|
|
|
+ item.newDay = (this.form.gap * dayIndex) + 1;
|
|
|
+ })
|
|
|
+ this.$forceUpdate()
|
|
|
+ },
|
|
|
+ onDragEnd() {
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 切换标签保存数据,默认打开会触发一次
|
|
|
+ * @param tabIndex
|
|
|
+ * @param oldIndex
|
|
|
+ */
|
|
|
+ async leave(tabIndex, oldIndex) {
|
|
|
+ const newData = this.days[tabIndex];
|
|
|
+ if (newData.dayNum && newData.id) {
|
|
|
+ this.loading = true;
|
|
|
+ let rd = await selectRulesInfo(newData.id);
|
|
|
+ this.$nextTick(async () => {
|
|
|
+ let defaultRule = {
|
|
|
+ type: 2,//默认消息类别为科普
|
|
|
+ contentType: 1,
|
|
|
+ courseId: null,
|
|
|
+ videoId: null,
|
|
|
+ meta: {
|
|
|
+ courseList: this.courseList,
|
|
|
+ courseLoading: false,
|
|
|
+ videoList: [],
|
|
|
+ },
|
|
|
+ addTag: [],
|
|
|
+ delTag: [],
|
|
|
+ addCustomer: [],
|
|
|
+ delCustomer: [],
|
|
|
+ setting: [{ contentType: '9', value: "", }]//默认是文本
|
|
|
+ }
|
|
|
+ this.$set(this.days, tabIndex, {
|
|
|
+ ...newData,
|
|
|
+ voice: rd.data.voice,
|
|
|
+ rules: rd.data.list || [defaultRule] //为空默认普通消息,内容为文本
|
|
|
+ });
|
|
|
+
|
|
|
+ //遍历当天所有规则
|
|
|
+ for (let j = 0; j < this.days[tabIndex].rules.length; j++) {
|
|
|
+ let ruleItem = this.days[tabIndex].rules[j];
|
|
|
+ //消息类别为科普,动态加载科普下拉
|
|
|
+ if (ruleItem.type == 2) {
|
|
|
+ if (ruleItem.courseId) {
|
|
|
+ //获取科普下拉
|
|
|
+ let cl = await this.getCourseList(null, ruleItem.courseId);
|
|
|
+ //根据科普获取视频小节下拉
|
|
|
+ let vl = await this.getVideoList(ruleItem.courseId);
|
|
|
+ this.$set(ruleItem, 'meta', {
|
|
|
+ courseList: cl.list,
|
|
|
+ courseLoading: false,
|
|
|
+ videoList: vl.list,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ //初始遍历当前规则的所有内容
|
|
|
+ for (let i = 0; i < ruleItem.setting.length; i++) {
|
|
|
+ let setting = ruleItem.setting[i];
|
|
|
+ let contentType = Number(setting.contentType);
|
|
|
+ //疗法
|
|
|
+ if (contentType === 20) {
|
|
|
+ if (setting.packageId) {
|
|
|
+ let pkgList = await this.getPkgList(null, setting.packageId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ pkgLoading: false,
|
|
|
+ pkgList: pkgList.data,
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ pkgLoading: false,
|
|
|
+ pkgList: this.pkgList,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //直播
|
|
|
+ else if (contentType === 21) {
|
|
|
+ if (setting.liveGroupTypeId) {
|
|
|
+ let liveRes = await this.fetchLiveOptionsByGroup(setting.liveGroupTypeId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ liveLoading: false,
|
|
|
+ liveList: liveRes.data || liveRes.rows || [],
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ liveLoading: false,
|
|
|
+ liveList: [],
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //民品
|
|
|
+ else if(contentType === 22) {
|
|
|
+ if (!setting.productId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ productLoading: false,
|
|
|
+ productList: this.productList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let productList = await this.getProductList(null, setting.productId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ productLoading: false,
|
|
|
+ productList: productList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //药品
|
|
|
+ else if(contentType === 23) {
|
|
|
+ if (!setting.medicinesId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ medicinesLoading: false,
|
|
|
+ medicinesList: this.medicinesList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let medicinesList = await this.getMedicinesList(null, setting.medicinesId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ medicinesLoading: false,
|
|
|
+ medicinesList: medicinesList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //短视频
|
|
|
+ else if(contentType === 24) {
|
|
|
+ if (!setting.shortVideoId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ shortVideoLoading: false,
|
|
|
+ shortVideoList: this.shortVideoList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let shortVideoList = await this.getShortVideoList(null, setting.shortVideoId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ shortVideoLoading: false,
|
|
|
+ shortVideoList: shortVideoList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //文章
|
|
|
+ else if(contentType === 25) {
|
|
|
+ if (!setting.articleId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ articleLoading: false,
|
|
|
+ articleList: this.articleList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let articleList = await this.getArticleList(null, setting.articleId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ articleLoading: false,
|
|
|
+ articleList: articleList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //公开课
|
|
|
+ else if(contentType === 26) {
|
|
|
+ if (!setting.openClassVideoId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ openClassVideoLoading: false,
|
|
|
+ openClassVideoList: this.openClassVideoList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let openClassVideoList = await this.getOpenClassVideoList(null, setting.openClassVideoId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ openClassVideoLoading: false,
|
|
|
+ openClassVideoList: openClassVideoList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //动态加载绑定/解绑 标签和客服
|
|
|
+ if (ruleItem.addTag) {
|
|
|
+ getTagByIds(ruleItem.addTag.split(',')).then(tagsRes => {
|
|
|
+ ruleItem.addTag = tagsRes.data;
|
|
|
+ this.tagConfigForBind.selected = tagsRes.data;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ ruleItem.addTag = [];
|
|
|
+ this.tagConfigForBind.selected = [];
|
|
|
+ }
|
|
|
+ if (ruleItem.delTag) {
|
|
|
+ getTagByIds(ruleItem.delTag.split(',')).then(tagsRes => {
|
|
|
+ ruleItem.delTag = tagsRes.data;
|
|
|
+ this.tagConfigForUnbind.selected = tagsRes.data;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ ruleItem.delTag = [];
|
|
|
+ this.tagConfigForUnbind.selected = [];
|
|
|
+ }
|
|
|
+ if (ruleItem.addCustomer) {
|
|
|
+ listRole({ids: ruleItem.addCustomer.split(',')}).then(customerRes => {
|
|
|
+ ruleItem.addCustomer = customerRes.rows;
|
|
|
+ this.customerConfigForBind.selected = customerRes.rows;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ ruleItem.addCustomer = [];
|
|
|
+ this.customerConfigForBind.selected = [];
|
|
|
+ }
|
|
|
+ if (ruleItem.delCustomer) {
|
|
|
+ listRole({ids: ruleItem.delCustomer.split(',')}).then(customerRes => {
|
|
|
+ ruleItem.delCustomer = customerRes.rows;
|
|
|
+ this.customerConfigForUnbind.selected = customerRes.rows;
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ ruleItem.delCustomer = [];
|
|
|
+ this.customerConfigForUnbind.selected = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.loading = false;
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 保存天
|
|
|
+ */
|
|
|
+ saveDay() {
|
|
|
+ let data = JSON.parse(JSON.stringify(this.days[this.tabIndex]));
|
|
|
+ let check = this.checkData(data);
|
|
|
+ if (!check) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let j = 0; j < data.rules.length; j++) {
|
|
|
+ let e = data.rules[j];
|
|
|
+ //如果不是每天第一条,全刷为非官方
|
|
|
+ if (j !== 0) {
|
|
|
+ e.isOfficial = 0;
|
|
|
+ }
|
|
|
+ e.name = data.name;
|
|
|
+ e.tempId = this.id;
|
|
|
+ e.sorts = Number(this.tabIndex);
|
|
|
+ e.dayNum = (this.form.gap * e.sorts) + 1;
|
|
|
+ e.sorts = j;
|
|
|
+ data.dayNum = e.dayNum;
|
|
|
+ e.contentType = e.type;
|
|
|
+ delete e.meta;
|
|
|
+ e.setting.forEach(item => delete item.meta);
|
|
|
+ e.settingList = e.setting;
|
|
|
+ e.settingList.forEach(e => e.content = JSON.stringify(e));
|
|
|
+ e.addTag = e?.addTag?.map(tag => tag.id).join(',') || null;
|
|
|
+ e.delTag = e?.delTag?.map(tag => tag.id).join(',') || null;
|
|
|
+ e.addCustomer = e?.addCustomer?.map(cus => cus.id).join(',') || null;
|
|
|
+ e.delCustomer = e?.delCustomer?.map(cus => cus.id).join(',') || null;
|
|
|
+ }
|
|
|
+ data.tempId = this.id;
|
|
|
+ data.list = data.rules;
|
|
|
+ this.loading = true;
|
|
|
+ addOrUpdateSetting(data).then(e => {
|
|
|
+ this.loading = false;
|
|
|
+ // 使用Vue.set确保响应式更新
|
|
|
+ this.$set(this.days, this.tabIndex, {
|
|
|
+ ...this.days[this.tabIndex],
|
|
|
+ id: e.data.id,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ isEmpty(obj) {
|
|
|
+ if (null === obj || undefined === obj || 0 === obj.length) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 校验数据
|
|
|
+ * @param data
|
|
|
+ */
|
|
|
+ checkData(data) {
|
|
|
+ this.$message.closeAll();
|
|
|
+ if (this.isEmpty(data.name)) {
|
|
|
+ this.$message.error("内容名称不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ for (let j = 0; j < data.rules.length; j++) {
|
|
|
+ let dc = data.rules[j];
|
|
|
+ if (this.isEmpty(dc.time)) {
|
|
|
+ this.$message.error("时间不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ //规则消息类别-科普
|
|
|
+ if (dc.type == 2) {
|
|
|
+ if (this.isEmpty(dc.courseId)) {
|
|
|
+ this.$message.error("请选择科普")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (this.isEmpty(dc.videoId)) {
|
|
|
+ this.$message.error("请选择课节")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (this.isEmpty(dc.courseType)) {
|
|
|
+ this.$message.error("请选择消息类型")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let k = 0; k < dc.setting.length; k++) {
|
|
|
+ let dcs = data.rules[j].setting[k];
|
|
|
+ if (dcs.contentType == 11 && this.isEmpty(dcs.value)) {
|
|
|
+ this.$message.error("内容不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (dcs.contentType == 12 && this.isEmpty(dcs.value)) {
|
|
|
+ this.$message.error("语音文本不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (dcs.contentType == 2 && this.isEmpty(dcs.imgUrl)) {
|
|
|
+ this.$message.error("图片不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ([9].includes(Number(dcs.contentType)) && this.isEmpty(dcs.linkTitle)) {
|
|
|
+ this.$message.error("链接标题不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ([9].includes(Number(dcs.contentType)) && this.isEmpty(dcs.linkDescribe)) {
|
|
|
+ this.$message.error("链接描述不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ([9].includes(Number(dcs.contentType)) && this.isEmpty(dcs.linkImageUrl)) {
|
|
|
+ this.$message.error("链接图片不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ([20].includes(Number(dcs.contentType)) && this.isEmpty(dcs.packageId)) {
|
|
|
+ this.$message.error("疗法不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ([21].includes(Number(dcs.contentType)) && this.isEmpty(dcs.liveGroupTypeId)) {
|
|
|
+ this.$message.error("直播分组不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ([21].includes(Number(dcs.contentType)) && this.isEmpty(dcs.liveId)) {
|
|
|
+ this.$message.error("直播间不能为空")
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //规则消息类别-改状态(绑定/解绑-标签/客服)(已停用,暂注释)
|
|
|
+ // else if (dc.type == 5) {
|
|
|
+ // if (this.isEmpty(dc.addTag) && this.isEmpty(dc.delTag)
|
|
|
+ // && this.isEmpty(dc?.addCustomer) && this.isEmpty(dc?.delCustomer)) {
|
|
|
+ // this.$message.error(`第${j + 1}条规则配置错误,未改动任何状态`);
|
|
|
+ // return false;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 天数选项卡点击
|
|
|
+ * @param obj
|
|
|
+ */
|
|
|
+ tabClick(obj) {
|
|
|
+
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 新增内容节点
|
|
|
+ * @param ruleItem
|
|
|
+ */
|
|
|
+ addContentNode(ruleItem) {
|
|
|
+ const newSetting = {
|
|
|
+ contentType: '9',//默认内容类型为科普
|
|
|
+ value: '',
|
|
|
+ };
|
|
|
+ // 将新设置项添加到 rules.setting 数组中
|
|
|
+ ruleItem.setting.push(newSetting);
|
|
|
+ this.handleContentTypeChange(ruleItem);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 删除内容节点
|
|
|
+ * @param dayIndex
|
|
|
+ * @param ruleIndex
|
|
|
+ * @param contentIndex
|
|
|
+ */
|
|
|
+ delContentNode(dayIndex, ruleIndex, contentIndex) {
|
|
|
+ this.days[dayIndex].rules[ruleIndex].setting.splice(contentIndex, 1)
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 添加规则节点
|
|
|
+ * @param dayIndex
|
|
|
+ */
|
|
|
+ addRuleNode(dayIndex) {
|
|
|
+ this.days[dayIndex].rules.push(
|
|
|
+ {
|
|
|
+ type: 2,//默认消息类别为科普
|
|
|
+ contentType: 2,
|
|
|
+ courseId: null,
|
|
|
+ videoId: null,
|
|
|
+ meta: {
|
|
|
+ courseList: this.courseList,
|
|
|
+ courseLoading: false,
|
|
|
+ videoList: [],
|
|
|
+ },
|
|
|
+ setting: [{ contentType: '9', value: "", }]//默认内容类型为科普
|
|
|
+ }
|
|
|
+ )
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 删除规则节点
|
|
|
+ * @param dayIndex
|
|
|
+ * @param rulesIndex
|
|
|
+ */
|
|
|
+ delRuleNode(dayIndex, rulesIndex) {
|
|
|
+ this.days[dayIndex].rules.splice(rulesIndex, 1);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 添加天数
|
|
|
+ */
|
|
|
+ addDay() {
|
|
|
+ let rules = [
|
|
|
+ {
|
|
|
+ contentType: '1',
|
|
|
+ setting: [{ contentType: '9', value: "", }],//默认内容类型为科普
|
|
|
+ meta: {
|
|
|
+ courseList: this.courseList,
|
|
|
+ courseLoading: false,
|
|
|
+ videoList: [],
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ rules[0]['type'] = 2;//默认消息类别为科普
|
|
|
+ this.days.push({
|
|
|
+ name: null,
|
|
|
+ dayNum: (this.form.gap * this.days.length) + 1,
|
|
|
+ rules
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 删除天数
|
|
|
+ * @param dayIndex
|
|
|
+ */
|
|
|
+ delDay(dayIndex) {
|
|
|
+ const newData = this.days[dayIndex];
|
|
|
+ if (newData.id && newData.dayNum) {
|
|
|
+ this.$confirm('此操作将永久删除, 是否继续?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ delRules(newData.id, newData.name, newData.dayNum).then(res => {
|
|
|
+ this.del(dayIndex);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.del(dayIndex);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ del(dayIndex) {
|
|
|
+ if (dayIndex == 0) {
|
|
|
+ this.tabIndex = "0";
|
|
|
+ } else {
|
|
|
+ this.tabIndex = (dayIndex - 1) + "";
|
|
|
+ }
|
|
|
+ this.days.splice(dayIndex, 1);
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 选择视频号
|
|
|
+ * @param content
|
|
|
+ * @param dayIndex
|
|
|
+ * @param rulesIndex
|
|
|
+ * @param contentIndex
|
|
|
+ */
|
|
|
+ hanldeSelectVideoNum(content, dayIndex, rulesIndex, contentIndex) {
|
|
|
+ this.videoNumOptions.content = content;
|
|
|
+ this.videoNumOptions.rulesIndex = rulesIndex;
|
|
|
+ this.videoNumOptions.contentIndex = contentIndex;
|
|
|
+ this.videoNumOptions.open = true;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 科普下拉搜索
|
|
|
+ */
|
|
|
+ async handleCourseRemoteSearch(keyword, ruleItem) {
|
|
|
+ ruleItem.meta.courseLoading = true;
|
|
|
+ // 模拟远程接口请求(替换为你的真实接口)
|
|
|
+ let cl = await this.getCourseList(this.isEmpty(keyword) ? null : keyword, null);
|
|
|
+ ruleItem.meta.courseLoading = false;
|
|
|
+ ruleItem.meta.courseList = cl.list;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 疗法下拉搜索
|
|
|
+ * @param keyword
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async handlePkgRemoteSearch(keyword, content) {
|
|
|
+ content.meta.pkgLoading = true;
|
|
|
+ // 模拟远程接口请求(替换为你的真实接口)
|
|
|
+ let cl = await this.getPkgList(this.isEmpty(keyword) ? null : keyword, null);
|
|
|
+ content.meta.pkgLoading = false;
|
|
|
+ content.meta.pkgList = cl.data;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 民品下拉搜索
|
|
|
+ * @param keyword
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async handleProductRemoteSearch(keyword, content) {
|
|
|
+ content.meta.productLoading = true;
|
|
|
+ let cl = await this.getProductList(this.isEmpty(keyword) ? null : keyword, null);
|
|
|
+ content.meta.productLoading = false;
|
|
|
+ content.meta.productList = cl.data;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 民品变动处理
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async productChangeUpdate(content) {
|
|
|
+ this.$set(content, 'productName', null);
|
|
|
+ this.$set(content, 'productImgUrl', null);
|
|
|
+ if (content.productId) {
|
|
|
+ // 查找选中民品的信息
|
|
|
+ const selected = content.meta.productList.find(pro => parseInt(pro.productId) === content.productId);
|
|
|
+ this.$set(content, 'productName', selected.productName);
|
|
|
+ this.$set(content, 'productImgUrl', selected.image);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 药品下拉搜索
|
|
|
+ * @param keyword
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async handleMedicinesRemoteSearch(keyword, content) {
|
|
|
+ content.meta.medicinesLoading = true;
|
|
|
+ let cl = await this.getMedicinesList(this.isEmpty(keyword) ? null : keyword, null);
|
|
|
+ content.meta.medicinesLoading = false;
|
|
|
+ content.meta.medicinesList = cl.data;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 药品变动处理
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async medicinesChangeUpdate(content) {
|
|
|
+ this.$set(content, 'medicinesName', null);
|
|
|
+ this.$set(content, 'medicinesImgUrl', null);
|
|
|
+ if (content.medicinesId) {
|
|
|
+ // 查找选中药品的信息
|
|
|
+ const selected = content.meta.medicinesList.find(pro => parseInt(pro.productId) === content.medicinesId);
|
|
|
+ this.$set(content, 'medicinesName', selected.productName);
|
|
|
+ this.$set(content, 'medicinesImgUrl', selected.image);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 短视频下拉搜索
|
|
|
+ * @param keyword
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async handleShortVideoRemoteSearch(keyword, content) {
|
|
|
+ content.meta.shortVideoLoading = true;
|
|
|
+ let cl = await this.getShortVideoList(this.isEmpty(keyword) ? null : keyword, null);
|
|
|
+ content.meta.shortVideoLoading = false;
|
|
|
+ content.meta.shortVideoList = cl.data;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 短视频变动处理
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async shortVideoChangeUpdate(content) {
|
|
|
+ this.$set(content, 'shortVideoName', null);
|
|
|
+ this.$set(content, 'shortVideoImgUrl', null);
|
|
|
+ if (content.shortVideoId) {
|
|
|
+ // 查找选中短视频的信息
|
|
|
+ const selected = content.meta.shortVideoList.find(pro => parseInt(pro.videoId) === content.shortVideoId);
|
|
|
+ this.$set(content, 'shortVideoName', selected.title);
|
|
|
+ this.$set(content, 'shortVideoImgUrl', selected.thumbnail);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 文章下拉搜索
|
|
|
+ * @param keyword
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async handleArticleRemoteSearch(keyword, content) {
|
|
|
+ content.meta.articleLoading = true;
|
|
|
+ let cl = await this.getArticleList(this.isEmpty(keyword) ? null : keyword, null);
|
|
|
+ content.meta.articleLoading = false;
|
|
|
+ content.meta.articleList = cl.data;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 文章变动处理
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async articleChangeUpdate(content) {
|
|
|
+ this.$set(content, 'articleName', null);
|
|
|
+ this.$set(content, 'articleImgUrl', null);
|
|
|
+ if (content.articleId) {
|
|
|
+ // 查找选中文章的信息
|
|
|
+ const selected = content.meta.articleList.find(pro => parseInt(pro.articleId) === content.articleId);
|
|
|
+ this.$set(content, 'articleName', selected.title);
|
|
|
+ this.$set(content, 'articleImgUrl', selected.imageUrl);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 公开课下拉搜索
|
|
|
+ * @param keyword
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async handleOpenClassVideoRemoteSearch(keyword, content) {
|
|
|
+ content.meta.openClassVideoLoading = true;
|
|
|
+ let cl = await this.getOpenClassVideoList(this.isEmpty(keyword) ? null : keyword, null);
|
|
|
+ content.meta.openClassVideoLoading = false;
|
|
|
+ content.meta.openClassVideoList = cl.data;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 公开课变动处理
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async openClassVideoChangeUpdate(content) {
|
|
|
+ this.$set(content, 'openClassVideoName', null);
|
|
|
+ this.$set(content, 'openClassVideoImgUrl', null);
|
|
|
+ if (content.openClassVideoId) {
|
|
|
+ // 查找选中文章的信息
|
|
|
+ const selected = content.meta.openClassVideoList.find(pro => parseInt(pro.videoId) === content.openClassVideoId);
|
|
|
+ this.$set(content, 'openClassVideoName', selected.title);
|
|
|
+ this.$set(content, 'openClassVideoImgUrl', selected.thumbnail);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 科普变动处理
|
|
|
+ * @param ruleItem
|
|
|
+ * @param dayIndex
|
|
|
+ * @param ruleIndex
|
|
|
+ */
|
|
|
+ async courseChangeUpdate(ruleItem, dayIndex, ruleIndex) {
|
|
|
+ //将当前规则已选中的视频小节清空
|
|
|
+ this.$set(ruleItem, 'videoId', null);
|
|
|
+ this.$set(ruleItem.meta, 'videoList', []);
|
|
|
+ // 查找选中的科普的信息
|
|
|
+ const selectedCourse = ruleItem.meta.courseList.find(course => parseInt(course.dictValue) === ruleItem.courseId);
|
|
|
+ for (let i = 0; i < ruleItem.setting.length; i++) {
|
|
|
+ this.$set(ruleItem.setting[i], 'linkTitle', null);
|
|
|
+ this.$set(ruleItem.setting[i], 'linkDescribe', null);
|
|
|
+ this.$set(ruleItem.setting[i], 'linkImageUrl', null);
|
|
|
+
|
|
|
+ //如果是科普才上
|
|
|
+ if (selectedCourse && ruleItem.type == 2 && !this.isEmpty(ruleItem.courseId)) {
|
|
|
+ //响应式直接给链接的标题/封面上值
|
|
|
+
|
|
|
+ if ([9].includes(Number(ruleItem.setting[i].contentType))) {
|
|
|
+ this.$set(ruleItem.setting[i], 'linkTitle', selectedCourse.dictLabel);
|
|
|
+ this.$set(ruleItem.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!this.isEmpty(ruleItem.courseId)) {
|
|
|
+ let vl = await this.getVideoList(ruleItem.courseId, null);
|
|
|
+ ruleItem.meta.videoList = vl.list;
|
|
|
+ } else {
|
|
|
+ let cl = await this.getCourseList(null, null);
|
|
|
+ ruleItem.meta.courseList = cl.list;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 疗法变动处理
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async pkgChangeUpdate(content) {
|
|
|
+ //将当前规则已选中的视频小节清空
|
|
|
+ this.$set(content, 'packageName', null);
|
|
|
+ this.$set(content, 'packageImgUrl', null);
|
|
|
+ if (content.packageId) {
|
|
|
+ // 查找选中疗法的信息
|
|
|
+ const selectedPkg = content.meta.pkgList.find(pkg => parseInt(pkg.packageId) === content.packageId);
|
|
|
+ this.$set(content, 'packageName', selectedPkg.packageName);
|
|
|
+ this.$set(content, 'packageImgUrl', selectedPkg.imgUrl);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 直播分组切换
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ async liveGroupTypeChange(content) {
|
|
|
+ this.$set(content, 'liveId', null);
|
|
|
+ this.$set(content, 'liveTitle', null);
|
|
|
+ this.$set(content, 'liveImgUrl', null);
|
|
|
+ if (!content.liveGroupTypeId) {
|
|
|
+ this.$set(content, 'meta', {
|
|
|
+ ...(content.meta || {}),
|
|
|
+ liveLoading: false,
|
|
|
+ liveList: [],
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.$set(content, 'meta', {
|
|
|
+ ...(content.meta || {}),
|
|
|
+ liveLoading: true,
|
|
|
+ liveList: [],
|
|
|
+ });
|
|
|
+ const liveRes = await this.fetchLiveOptionsByGroup(content.liveGroupTypeId);
|
|
|
+ this.$set(content, 'meta', {
|
|
|
+ ...(content.meta || {}),
|
|
|
+ liveLoading: false,
|
|
|
+ liveList: liveRes.data || liveRes.rows || [],
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 直播间切换
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ liveChange(content) {
|
|
|
+ content.liveTitle = null;
|
|
|
+ content.liveImgUrl = null;
|
|
|
+ const list = (content.meta && content.meta.liveList) ? content.meta.liveList : [];
|
|
|
+ const selectedLive = list.find(live => parseInt(live.liveId) === parseInt(content.liveId));
|
|
|
+ if (selectedLive) {
|
|
|
+ content.liveTitle = selectedLive.liveName; // 自动填充标题
|
|
|
+ content.liveImgUrl = selectedLive.liveImgUrl; // 自动填充封面
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 处理输入内容
|
|
|
+ * @param value
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ handleInputVideoText(value, content) {
|
|
|
+ // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
|
|
|
+ const regex = /^[\u4e00-\u9fa5,。!?,!?]+$/;
|
|
|
+ // 删除不符合条件的字符
|
|
|
+ const filteredValue = value.split('').filter(char => regex.test(char)).join('');
|
|
|
+ this.$set(content, 'value', filteredValue);
|
|
|
+ },
|
|
|
+ courseUpdate(ruleItem, dayIndex, ruleIndex) {
|
|
|
+ videoList(ruleItem.courseId).then(response => {
|
|
|
+ ruleItem.meta.videoList = response.list;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 根据科普获取视频小节
|
|
|
+ * @param courseId
|
|
|
+ * @param title
|
|
|
+ */
|
|
|
+ async getVideoList(courseId, title) {
|
|
|
+ return await videoList({
|
|
|
+ courseId: courseId,
|
|
|
+ title: title
|
|
|
+ });
|
|
|
+ },
|
|
|
+ toggleSalesCall(dayIndex, rulesIndex, contentIndex) {
|
|
|
+ // 获取目标对象
|
|
|
+ const setItem = this.days[dayIndex].rules[rulesIndex].setting[contentIndex];
|
|
|
+ const salesCall = '#客服称呼#';
|
|
|
+ const refKey = `textarea-${dayIndex}-${rulesIndex}-${contentIndex}`;
|
|
|
+ const textarea = this.$refs[refKey][0]?.$refs?.textarea;
|
|
|
+
|
|
|
+ if (!textarea) return;
|
|
|
+
|
|
|
+ // 获取光标位置
|
|
|
+ const cursorPosition = textarea.selectionStart;
|
|
|
+
|
|
|
+ if (setItem.isSalesCallAdded) {
|
|
|
+ // 移除所有标签
|
|
|
+ setItem.value = setItem.value.replace(new RegExp(salesCall, 'g'), '');
|
|
|
+ } else {
|
|
|
+ // 插入到光标位置
|
|
|
+ setItem.value =
|
|
|
+ setItem.value.slice(0, cursorPosition) +
|
|
|
+ salesCall +
|
|
|
+ setItem.value.slice(cursorPosition);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 切换状态
|
|
|
+ setItem.isSalesCallAdded = !setItem.isSalesCallAdded;
|
|
|
+
|
|
|
+ // 保持光标位置
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const newCursorPos = cursorPosition + (setItem.isSalesCallAdded ? salesCall.length : 0);
|
|
|
+ textarea.setSelectionRange(newCursorPos, newCursorPos);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleKeydown(event, dayIndex, rulesIndex, contentIndex) {
|
|
|
+
|
|
|
+ const setItem = this.days[dayIndex].rules[rulesIndex].setting[contentIndex];
|
|
|
+ const refKey = `textarea-${dayIndex}-${rulesIndex}-${contentIndex}`;
|
|
|
+ const textarea = this.$refs[refKey][0]?.$refs?.textarea;
|
|
|
+
|
|
|
+ if (!textarea) return;
|
|
|
+
|
|
|
+ const tags = ['#客服称呼#', '#客户称呼#'];
|
|
|
+ const key = event.key;
|
|
|
+ const value = setItem.value;
|
|
|
+ const cursorPosition = textarea.selectionStart;
|
|
|
+
|
|
|
+ if (key === 'Backspace' || key === 'Delete') {
|
|
|
+ tags.forEach(tag => {
|
|
|
+ let start, end;
|
|
|
+
|
|
|
+ // Backspace 处理
|
|
|
+ if (key === 'Backspace' && cursorPosition >= tag.length) {
|
|
|
+ start = cursorPosition - tag.length;
|
|
|
+ if (value.slice(start, cursorPosition) === tag) {
|
|
|
+ event.preventDefault();
|
|
|
+ setItem.value = value.slice(0, start) + value.slice(cursorPosition);
|
|
|
+ if (tag === '#客服称呼#') setItem.isSalesCallAdded = false;
|
|
|
+ this.$nextTick(() => textarea.setSelectionRange(start, start));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Delete 处理
|
|
|
+ if (key === 'Delete') {
|
|
|
+ end = cursorPosition + tag.length;
|
|
|
+ if (value.slice(cursorPosition, end) === tag) {
|
|
|
+ event.preventDefault();
|
|
|
+ setItem.value = value.slice(0, cursorPosition) + value.slice(end);
|
|
|
+ if (tag === '#客服称呼#') setItem.isSalesCallAdded = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 内容类型切换
|
|
|
+ * @param ruleItem
|
|
|
+ */
|
|
|
+ handleContentTypeChange(ruleItem) {
|
|
|
+ if (ruleItem.type === 2) {
|
|
|
+ const selectedCourse = ruleItem.courseId != null
|
|
|
+ ? this.courseList.find(course => parseInt(course.dictValue) === ruleItem.courseId)
|
|
|
+ : null;
|
|
|
+ const selectedVideo = ruleItem.videoId != null
|
|
|
+ ? ruleItem.meta.videoList.find(course => parseInt(course.dictValue) === ruleItem.videoId)
|
|
|
+ : null;
|
|
|
+ ruleItem.setting.forEach(async setting => {
|
|
|
+ const contentType = Number(setting.contentType);
|
|
|
+ // 科普相关赋值(contentType=9)
|
|
|
+ if (selectedCourse && contentType === 9) {
|
|
|
+ this.$set(setting, 'linkTitle', selectedCourse.dictLabel);
|
|
|
+ this.$set(setting, 'linkImageUrl', selectedCourse.dictImgUrl);
|
|
|
+ }
|
|
|
+ // 视频相关赋值(contentType=9)
|
|
|
+ if (selectedVideo && contentType === 9) {
|
|
|
+ this.$set(setting, 'linkDescribe', selectedVideo.dictLabel);
|
|
|
+ }
|
|
|
+ //疗法相关赋值(contentType=20)
|
|
|
+ if (contentType === 20) {
|
|
|
+ if (!setting.packageId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ pkgLoading: false,
|
|
|
+ pkgList: this.pkgList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let pkgList = await this.getPkgList(null, setting.packageId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ pkgLoading: false,
|
|
|
+ pkgList: pkgList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //直播
|
|
|
+ else if (contentType === 21) {
|
|
|
+ if (setting.liveGroupTypeId) {
|
|
|
+ let liveRes = await this.fetchLiveOptionsByGroup(setting.liveGroupTypeId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ liveLoading: false,
|
|
|
+ liveList: liveRes.data || liveRes.rows || [],
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ liveLoading: false,
|
|
|
+ liveList: [],
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //民品
|
|
|
+ else if(contentType === 22) {
|
|
|
+ if (!setting.productId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ productLoading: false,
|
|
|
+ productList: this.productList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let productList = await this.getProductList(null, setting.productId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ productLoading: false,
|
|
|
+ productList: productList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //药品
|
|
|
+ else if(contentType === 23) {
|
|
|
+ if (!setting.medicinesId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ medicinesLoading: false,
|
|
|
+ medicinesList: this.medicinesList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let medicinesList = await this.getMedicinesList(null, setting.medicinesId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ medicinesLoading: false,
|
|
|
+ medicinesList: medicinesList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //短视频
|
|
|
+ else if(contentType === 24) {
|
|
|
+ if (!setting.shortVideoId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ shortVideoLoading: false,
|
|
|
+ shortVideoList: this.shortVideoList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let shortVideoList = await this.getShortVideoList(null, setting.shortVideoId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ shortVideoLoading: false,
|
|
|
+ shortVideoList: shortVideoList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //文章
|
|
|
+ else if(contentType === 25) {
|
|
|
+ if (!setting.articleId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ articleLoading: false,
|
|
|
+ articleList: this.articleList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let articleList = await this.getArticleList(null, setting.articleId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ articleLoading: false,
|
|
|
+ articleList: articleList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //公开课
|
|
|
+ else if(contentType === 26) {
|
|
|
+ if (!setting.openClassVideoId) {
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ openClassVideoLoading: false,
|
|
|
+ openClassVideoList: this.openClassVideoList,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let openClassVideoList = await this.getOpenClassVideoList(null, setting.openClassVideoId);
|
|
|
+ this.$set(setting, 'meta', {
|
|
|
+ openClassVideoLoading: false,
|
|
|
+ openClassVideoList: openClassVideoList.data,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 科普小节变化
|
|
|
+ * @param ruleItem
|
|
|
+ * @param dayIndex
|
|
|
+ * @param ruleIndex
|
|
|
+ */
|
|
|
+ videoIdChange(ruleItem, dayIndex, ruleIndex) {
|
|
|
+ //选择了科普小节则 默认绑上
|
|
|
+ let selectedVideo;
|
|
|
+ // 查找选中的科普对应的 label
|
|
|
+ if (ruleItem.videoId != null) {
|
|
|
+ selectedVideo = ruleItem.meta.videoList.find(course => parseInt(course.dictValue) === ruleItem.videoId);
|
|
|
+ }
|
|
|
+ for (let i = 0; i < ruleItem.setting.length; i++) {
|
|
|
+ //科普消息-文本内容
|
|
|
+ if (ruleItem.setting[i].contentType == 11 && ruleItem.type == 2) {
|
|
|
+ this.$set(ruleItem.setting[i], 'isBindUrl', '2');
|
|
|
+ }
|
|
|
+ //如果是科普的才上
|
|
|
+ if (selectedVideo && ruleItem.type == 2 && ruleItem.videoId != null) {
|
|
|
+
|
|
|
+ if (ruleItem.setting[i].contentType == 9) {
|
|
|
+ this.$set(ruleItem.setting[i], 'linkDescribe', selectedVideo.dictLabel);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 打开选择标签的页面
|
|
|
+ * @param ruleItem
|
|
|
+ * @param type 0-绑定 1-解绑
|
|
|
+ */
|
|
|
+ openTagPage(ruleItem, type) {
|
|
|
+ if (type === 0) {
|
|
|
+ this.tagConfigForBind.visible = true;
|
|
|
+ this.tagConfigForBind.currentRuleItem = ruleItem;
|
|
|
+ this.tagConfigForBind.selected = ruleItem.addTag || [];
|
|
|
+ }
|
|
|
+ //解绑
|
|
|
+ else {
|
|
|
+ this.tagConfigForUnbind.visible = true;
|
|
|
+ this.tagConfigForUnbind.currentRuleItem = ruleItem;
|
|
|
+ this.tagConfigForUnbind.selected = ruleItem.delTag || [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 绑定标签取消
|
|
|
+ */
|
|
|
+ tagCancelForBind() {
|
|
|
+ this.tagConfigForBind.visible = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 绑定标签确认
|
|
|
+ */
|
|
|
+ tagSubmitForBind() {
|
|
|
+ this.tagConfigForBind.visible = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 解绑标签取消
|
|
|
+ */
|
|
|
+ tagCancelForUnbind() {
|
|
|
+ this.tagConfigForUnbind.visible = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 解绑标签确认
|
|
|
+ */
|
|
|
+ tagSubmitForUnbind() {
|
|
|
+ this.tagConfigForUnbind.visible = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 删除标签操作
|
|
|
+ * @param ruleItem
|
|
|
+ * @param type 0-绑定 1-解绑
|
|
|
+ * @param tag 标签
|
|
|
+ */
|
|
|
+ handleCloseTag(ruleItem, type, tag) {
|
|
|
+ //绑定
|
|
|
+ if (type === 0) {
|
|
|
+ const index = this.tagConfigForBind.selected.findIndex(t => t === tag);
|
|
|
+ if (index !== -1) {
|
|
|
+ this.tagConfigForBind.selected.splice(index, 1);
|
|
|
+ ruleItem.addTag = this.tagConfigForBind.selected;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //解绑
|
|
|
+ else {
|
|
|
+ const index = this.tagConfigForUnbind.selected.findIndex(t => t === tag);
|
|
|
+ if (index !== -1) {
|
|
|
+ this.tagConfigForUnbind.selected.splice(index, 1);
|
|
|
+ ruleItem.delTag = this.tagConfigForUnbind.selected;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 选中的绑定标签列表
|
|
|
+ * @param group 标签所属组
|
|
|
+ * @param tag 具体操作的标签
|
|
|
+ */
|
|
|
+ tagSelectionChangeCallForBind(group, tag) {
|
|
|
+ if (!tag.isSelected) {
|
|
|
+ this.tagConfigForBind.selected = this.tagConfigForBind.selected.filter(item => tag.id != item.id);
|
|
|
+ } else {
|
|
|
+ if (!this.tagConfigForBind.selected.some(st => st.id == tag.id)) {
|
|
|
+ this.tagConfigForBind.selected.push(tag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.$set(this.tagConfigForBind.currentRuleItem, 'addTag', this.tagConfigForBind.selected);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 选中的解绑标签列表
|
|
|
+ * @param group 标签所属组
|
|
|
+ * @param tag 具体操作的标签
|
|
|
+ */
|
|
|
+ tagSelectionChangeCallForUnbind(group, tag) {
|
|
|
+ if (!tag.isSelected) {
|
|
|
+ this.tagConfigForUnbind.selected = this.tagConfigForUnbind.selected.filter(item => tag.id != item.id);
|
|
|
+ } else {
|
|
|
+ if (!this.tagConfigForUnbind.selected.some(st => st.id == tag.id)) {
|
|
|
+ this.tagConfigForUnbind.selected.push(tag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.$set(this.tagConfigForUnbind.currentRuleItem, 'delTag', this.tagConfigForUnbind.selected);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 打开选择客服的页面
|
|
|
+ * @param ruleItem
|
|
|
+ * @param type 0-绑定 1-解绑
|
|
|
+ */
|
|
|
+ openCustomerPage(ruleItem, type) {
|
|
|
+ if (type === 0) {
|
|
|
+ this.customerConfigForBind.visible = true;
|
|
|
+ this.customerConfigForBind.currentRuleItem = ruleItem;
|
|
|
+ this.customerConfigForBind.selected = ruleItem.addCustomer || [];
|
|
|
+ }
|
|
|
+ //解绑
|
|
|
+ else {
|
|
|
+ this.customerConfigForUnbind.visible = true;
|
|
|
+ this.customerConfigForUnbind.currentRuleItem = ruleItem;
|
|
|
+ this.customerConfigForUnbind.selected = ruleItem.delCustomer || [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 确定绑定客服
|
|
|
+ */
|
|
|
+ customerConfirmCallForBind() {
|
|
|
+ this.customerConfigForBind.visible = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 确定解绑客服
|
|
|
+ */
|
|
|
+ customerConfirmCallForUnbind() {
|
|
|
+ this.customerConfigForUnbind.visible = false;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 删除客服操作
|
|
|
+ * @param ruleItem
|
|
|
+ * @param type 0-绑定 1-解绑
|
|
|
+ * @param customer 客服
|
|
|
+ */
|
|
|
+ handleCloseCustomer(ruleItem, type, customer) {
|
|
|
+ //绑定
|
|
|
+ if (type === 0) {
|
|
|
+ const index = this.customerConfigForBind.selected.findIndex(t => t === customer);
|
|
|
+ if (index !== -1) {
|
|
|
+ this.customerConfigForBind.selected.splice(index, 1);
|
|
|
+ ruleItem.addCustomer = this.customerConfigForBind.selected;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //解绑
|
|
|
+ else {
|
|
|
+ const index = this.customerConfigForUnbind.selected.findIndex(t => t === customer);
|
|
|
+ if (index !== -1) {
|
|
|
+ this.customerConfigForUnbind.selected.splice(index, 1);
|
|
|
+ ruleItem.delCustomer = this.customerConfigForUnbind.selected;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 选中的绑定客服列表
|
|
|
+ * @param list
|
|
|
+ */
|
|
|
+ customerSelectionChangeCallForBind(config) {
|
|
|
+ let selected = config.selected;
|
|
|
+ //单行操作
|
|
|
+ if (config.mode === 0) {
|
|
|
+ let row = config.row;
|
|
|
+ if (selected) {
|
|
|
+ if (!this.customerConfigForBind.selected.some(s => s.id == row.id)) {
|
|
|
+ this.customerConfigForBind.selected.push(row)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.customerConfigForBind.selected = this.customerConfigForBind.selected.filter(m => m.id != row.id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //操作当前页所有行
|
|
|
+ else {
|
|
|
+ let list = config.rows;
|
|
|
+ if (selected) {
|
|
|
+ list.map(l => {
|
|
|
+ if (!this.customerConfigForBind.selected.some(s => s.id == l.id)) {
|
|
|
+ this.customerConfigForBind.selected.push(l);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ list.map(l => {
|
|
|
+ for (let i = 0; i < this.customerConfigForBind.selected.length; i++) {
|
|
|
+ if (l.id == this.customerConfigForBind.selected[i].id) {
|
|
|
+ this.customerConfigForBind.selected.splice(i, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.$set(this.customerConfigForBind.currentRuleItem, 'addCustomer', this.customerConfigForBind.selected);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 选中的解绑客服列表
|
|
|
+ * @param list
|
|
|
+ */
|
|
|
+ customerSelectionChangeCallForUnbind(config) {
|
|
|
+ let selected = config.selected;
|
|
|
+ //单行操作
|
|
|
+ if (config.mode === 0) {
|
|
|
+ let row = config.row;
|
|
|
+ if (selected) {
|
|
|
+ if (!this.customerConfigForUnbind.selected.some(s => s.id == row.id)) {
|
|
|
+ this.customerConfigForUnbind.selected.push(row)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.customerConfigForUnbind.selected = this.customerConfigForUnbind.selected.filter(m => m.id != row.id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //操作当前页所有行
|
|
|
+ else {
|
|
|
+ let list = config.rows;
|
|
|
+ if (selected) {
|
|
|
+ list.map(l => {
|
|
|
+ if (!this.customerConfigForUnbind.selected.some(s => s.id == l.id)) {
|
|
|
+ this.customerConfigForUnbind.selected.push(l)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ list.map(l => {
|
|
|
+ for (let i = 0; i < this.customerConfigForUnbind.selected.length; i++) {
|
|
|
+ if (l.id == this.customerConfigForUnbind.selected[i].id) {
|
|
|
+ this.customerConfigForUnbind.selected.splice(i, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.$set(this.customerConfigForUnbind.currentRuleItem, 'delCustomer', this.customerConfigForUnbind.selected);
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 上传文件前置处理
|
|
|
+ * @param file
|
|
|
+ */
|
|
|
+ beforeAvatarUploadFile(file) {
|
|
|
+ const isLt1M = file.size / 1024 / 1024 < 10;
|
|
|
+ if (!isLt1M) {
|
|
|
+ this.$message.error('上传大小不能超过 10MB!');
|
|
|
+ }
|
|
|
+ return isLt1M;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 上传文件成功回调
|
|
|
+ * @param res
|
|
|
+ * @param file
|
|
|
+ * @param content
|
|
|
+ */
|
|
|
+ handleAvatarSuccessFile(res, file, content) {
|
|
|
+ if (res.code === 200) {
|
|
|
+ // 使用 $set 确保响应式更新
|
|
|
+ this.$set(content, 'fileUrl', res.url);
|
|
|
+ } else {
|
|
|
+ this.msgError(res.msg);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ //下载文件
|
|
|
+ downloadUrl(materialUrl) {
|
|
|
+ // 直接返回文件 URL
|
|
|
+ return materialUrl;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 上传视频
|
|
|
+ * @param file
|
|
|
+ */
|
|
|
+ beforeAvatarUploadVideo(file) {
|
|
|
+ const isLt30M = file.size / 1024 / 1024 < 10;
|
|
|
+ const isMP4 = file.type === 'video/mp4';
|
|
|
+
|
|
|
+ if (!isMP4) {
|
|
|
+ this.$message.error('仅支持上传 MP4 格式的视频文件!');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isLt30M) {
|
|
|
+ this.$message.error('上传大小不能超过 10MB!');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 上传视频成功回调
|
|
|
+ * @param res
|
|
|
+ * @param file
|
|
|
+ * @param rules
|
|
|
+ */
|
|
|
+ handleAvatarSuccessVideo(res, file, rules) {
|
|
|
+ if (res.code == 200) {
|
|
|
+ // 使用 $set 确保响应式更新
|
|
|
+ this.$set(rules, 'videoUrl', res.url);
|
|
|
+ } else {
|
|
|
+ this.msgError(res.msg);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 查询sop模板列表
|
|
|
+ */
|
|
|
+ getList() {
|
|
|
+ this.loading = true;
|
|
|
+ listSopTemp(this.queryParams).then(response => {
|
|
|
+ this.sopTempList = response.rows;
|
|
|
+ this.total = response.total;
|
|
|
+ this.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 表单重置
|
|
|
+ */
|
|
|
+ reset() {
|
|
|
+ this.form = {
|
|
|
+ id: null,
|
|
|
+ name: null,
|
|
|
+ setting: null,
|
|
|
+ status: "0",
|
|
|
+ sort: null,
|
|
|
+ createTime: null,
|
|
|
+ createBy: null,
|
|
|
+ companyId: null
|
|
|
+ };
|
|
|
+ this.resetForm("form");
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 初始化操作
|
|
|
+ * @param id
|
|
|
+ */
|
|
|
+ async initTempInfo(id) {
|
|
|
+ getSopTemp(id).then(response => {
|
|
|
+ this.form = response.data || {};
|
|
|
+ //获取当前模板已维护天数
|
|
|
+ this.days = this.form.days || [];
|
|
|
+ //解释
|
|
|
+ //days:一共多少天
|
|
|
+ //days[dayIndex].rules[ruleIndex]:消息(包含时间:time,消息类别:contentType,具体内容:setting【可能存在多个】)
|
|
|
+ //days[dayIndex].rules[ruleIndex].isOfficial,0-非官方,1-官方
|
|
|
+ if (Array.isArray(this.days)) {
|
|
|
+ //遍历所有天
|
|
|
+ this.days.forEach(day => {
|
|
|
+ if (day && Array.isArray(day.rules)) {
|
|
|
+ //遍历当天的所有规则
|
|
|
+ day.rules.forEach(ruleItem => {
|
|
|
+ this.$set(ruleItem, 'meta', {courseList: [], videoList: []});
|
|
|
+ if (ruleItem && Array.isArray(ruleItem.setting)) {
|
|
|
+ ruleItem.addTag = [];
|
|
|
+ ruleItem.delTag = [];
|
|
|
+ ruleItem.addCustomer = [];
|
|
|
+ ruleItem.delCustomer = [];
|
|
|
+ //遍历当前规则的所有内容
|
|
|
+ ruleItem.setting.forEach(content => {
|
|
|
+ this.$set(content, 'meta', {
|
|
|
+ pkgLoading: false,
|
|
|
+ pkgList: this.pkgList,
|
|
|
+ });
|
|
|
+ if (content && !Object.prototype.hasOwnProperty.call(content, 'isSalesCallAdded')) {
|
|
|
+ this.$set(content, 'isSalesCallAdded', false);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (Array.isArray(this.form.days)) {
|
|
|
+ this.form.days.forEach(e => e.newDay = e.dayNum);
|
|
|
+ this.dayList = JSON.parse(JSON.stringify(this.form.days));
|
|
|
+ } else {
|
|
|
+ this.form.days = [];
|
|
|
+ this.dayList = [];
|
|
|
+ }
|
|
|
+ }).catch(e => {
|
|
|
+ console.error('加载SOP模板详情失败', e);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ isOfficialChange(rules) {
|
|
|
+ this.$set(rules, 'time', '00:30');
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 确认分割后的内容
|
|
|
+ */
|
|
|
+ comfirmContent() {
|
|
|
+ this.openShowContent = false;
|
|
|
+ },
|
|
|
+ showOpenContent(dayIndex, rulesIndex, contentIndex) {
|
|
|
+ let setItem = this.days[dayIndex].rules[rulesIndex].setting[contentIndex];
|
|
|
+ let refKey = `textarea-${dayIndex}-${rulesIndex}-${contentIndex}`;
|
|
|
+ let textarea = this.$refs[refKey][0]?.$refs?.textarea;
|
|
|
+ if (!textarea) return;
|
|
|
+ this.openShowContent = true;
|
|
|
+ this.contentList = [];
|
|
|
+ this.contentListData = [];
|
|
|
+ let str = setItem.value;
|
|
|
+ this.contentList = str.split("|&|");
|
|
|
+ let idx = 1;
|
|
|
+ this.contentList.forEach(a => {
|
|
|
+ this.contentListData.push({ index: idx++, content: a });
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 复制分隔符
|
|
|
+ */
|
|
|
+ cppySpliter() {
|
|
|
+ navigator.clipboard.writeText("|&|").then(() => {
|
|
|
+ this.$message({
|
|
|
+ message: '复制成功',
|
|
|
+ type: 'success'
|
|
|
+ });
|
|
|
+ }).catch(err => {
|
|
|
+ this.$message({
|
|
|
+ message: '复制失败',
|
|
|
+ type: 'warning'
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style scoped>
|
|
|
+.el-button {
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.red:hover {
|
|
|
+ color: #dbdbdb !important;
|
|
|
+}
|
|
|
+
|
|
|
+.red {
|
|
|
+ background-color: #F56C6C !important;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .el-dialog__footer {
|
|
|
+ height: 55px;
|
|
|
+}
|
|
|
+
|
|
|
+.custom-input ::v-deep .el-input__inner {
|
|
|
+ height: 20px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.custom-input ::v-deep .el-input__icon {
|
|
|
+ line-height: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.el-icon-delete {
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .el-badge__content.is-fixed {
|
|
|
+ top: 10px !important;
|
|
|
+ right: 0 !important;
|
|
|
+ width: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.tip {
|
|
|
+ color: #909399;
|
|
|
+ font-size: 12px;
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.sortable-ghost {
|
|
|
+ background: rgb(26, 164, 255) !important;
|
|
|
+ color: #FFF !important;
|
|
|
+}
|
|
|
+</style>
|