<template>
|
<div class="template-selector">
|
<!-- 模板选择按钮和预览 -->
|
<div class="template-selector__header">
|
<el-form>
|
<el-form-item label="当前使用模板">
|
<el-input
|
style="width: 300px"
|
v-model="selectedTemplateName"
|
placeholder="请点击右侧选择"
|
/>
|
<el-button
|
v-if="(selectedTemplateId && isEditable) || !selectedTemplateId"
|
style="margin-left: 10px"
|
type="primary"
|
icon="el-icon-edit"
|
@click="drawerVisible = true"
|
circle
|
></el-button>
|
<!-- <el-button
|
v-if="selectedTemplateId"
|
type="success"
|
icon="el-icon-search"
|
@click="handlePreview"
|
circle
|
></el-button> -->
|
</el-form-item>
|
</el-form>
|
</div>
|
|
|
|
<!-- 模板选择抽屉 -->
|
<el-drawer
|
title="问卷内容列表"
|
:visible.sync="drawerVisible"
|
direction="rtl"
|
size="50%"
|
:before-close="handleDrawerClose"
|
>
|
<div class="drawer-content">
|
<el-form
|
:model="queryParams"
|
ref="queryForm"
|
size="small"
|
:inline="true"
|
label-width="98px"
|
>
|
<el-form-item label="问卷名称">
|
<el-input
|
v-model="queryParams.svyname"
|
@keyup.enter.native="handleSearch"
|
></el-input>
|
</el-form-item>
|
<el-form-item>
|
<el-button
|
type="primary"
|
icon="el-icon-search"
|
size="medium"
|
@click="handleSearch"
|
>搜索</el-button
|
>
|
<el-button
|
icon="el-icon-refresh"
|
size="medium"
|
@click="handleReset"
|
>重置</el-button
|
>
|
</el-form-item>
|
</el-form>
|
<el-divider></el-divider>
|
|
<!-- 模板列表 -->
|
<el-table
|
:data="templateList"
|
style="width: 100%"
|
@row-click="handleSelectTemplate"
|
>
|
<el-table-column prop="svyname" label="问卷标题" />
|
<el-table-column prop="description" label="问卷描述" />
|
<el-table-column prop="updateTime" label="修改日期" />
|
<el-table-column prop="createBy" label="创建人" />
|
<el-table-column label="操作" width="120">
|
<template slot-scope="scope">
|
<el-button
|
type="primary"
|
size="mini"
|
@click.stop="handlePreviewTemplate(scope.row)"
|
>预览</el-button
|
>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<!-- 分页 -->
|
<pagination
|
v-show="total > 0"
|
:total="total"
|
:page.sync="queryParams.pageNum"
|
:limit.sync="queryParams.pageSize"
|
@pagination="handleSearch"
|
/>
|
</div>
|
</el-drawer>
|
|
<!-- 模板预览对话框 -->
|
<el-dialog
|
title="模板预览"
|
:visible.sync="previewVisible"
|
width="70%"
|
:before-close="handlePreviewClose"
|
>
|
<el-tabs v-model="activeTab" type="border-card">
|
<el-tab-pane label="模板基础数据" name="basic">
|
<div class="preview-content">
|
<el-form :model="previewData" label-width="100px">
|
<el-row :gutter="10">
|
<el-col :span="14">
|
<el-form-item label="问卷分类">
|
<el-select
|
v-model="previewData.categoryid"
|
size="medium"
|
filterable
|
placeholder="请选择分类"
|
disabled
|
>
|
<el-option-group
|
v-for="group in categoryOptions"
|
:key="group.id"
|
:label="group.name"
|
>
|
<el-option
|
v-for="item in group.svyLibTemplateCategoryList"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-option-group>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="10">
|
<el-form-item label="评价类型">
|
<el-select
|
v-model="previewData.scoreType"
|
placeholder="请选择分类"
|
disabled
|
>
|
<el-option
|
v-for="group in appraisalOptions"
|
:key="group.value"
|
:label="group.label"
|
:value="group.value"
|
/>
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="14">
|
<el-form-item label="可用状态">
|
<el-radio-group v-model="previewData.isenable" disabled>
|
<el-radio
|
v-for="(item, index) in usableOptions"
|
:key="index"
|
:label="item.value"
|
>
|
{{ item.label }}
|
</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-col>
|
<el-col :span="8">
|
<el-form-item label="版本号">
|
<el-input
|
v-model="previewData.version"
|
placeholder="默认1.0"
|
disabled
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-form-item label="问卷标题">
|
<el-input v-model="previewData.svyname" disabled />
|
</el-form-item>
|
|
<el-form-item label="问卷描述">
|
<el-input
|
type="textarea"
|
:rows="2"
|
v-model="previewData.description"
|
disabled
|
/>
|
</el-form-item>
|
|
<el-form-item label="问卷结束语">
|
<el-input
|
type="textarea"
|
:rows="2"
|
v-model="previewData.conclusion"
|
disabled
|
/>
|
</el-form-item>
|
</el-form>
|
</div>
|
</el-tab-pane>
|
|
<el-tab-pane label="问题展示" name="questions">
|
<div class="preview-content">
|
<div v-for="item in questionList" :key="item.sort">
|
<!-- 单选 -->
|
<div
|
class="scriptTopic-dev"
|
v-if="item.scriptType == 1"
|
>
|
<div class="dev-text">
|
{{ item.sort }}、[单选]<span>{{ item.scriptContent }}</span>
|
</div>
|
<div class="dev-xx">
|
<el-radio-group v-model="item.remark" disabled>
|
<el-radio
|
v-for="(items, index) in item.svyLibTemplateTargetoptions"
|
:key="index"
|
:label="index"
|
>
|
{{ items.optioncontent }}
|
</el-radio>
|
</el-radio-group>
|
</div>
|
</div>
|
|
<!-- 多选 -->
|
<div
|
class="scriptTopic-dev"
|
v-if="item.scriptType == 2"
|
>
|
<div class="dev-text">
|
{{ item.sort }}、[多选]<span>{{ item.scriptContent }}</span>
|
</div>
|
<div class="dev-xx">
|
<el-checkbox-group v-model="item.qremark" disabled>
|
<el-checkbox
|
v-for="(items, index) in item.svyLibTemplateTargetoptions"
|
:key="index"
|
:label="index"
|
>
|
{{ items.optioncontent }}
|
</el-checkbox>
|
</el-checkbox-group>
|
</div>
|
</div>
|
|
<!-- 填空 -->
|
<div
|
class="scriptTopic-dev"
|
v-if="item.scriptType == 4"
|
>
|
<div class="dev-text">
|
{{ item.sort }}、[问答]<span>{{ item.scriptContent }}</span>
|
</div>
|
<div class="dev-xx">
|
<el-input
|
placeholder="请输入答案"
|
v-model="item.radioas"
|
disabled
|
/>
|
</div>
|
</div>
|
</div>
|
</div>
|
</el-tab-pane>
|
</el-tabs>
|
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="handleCancelPreview">取消</el-button>
|
<el-button
|
v-if="!selectedTemplateId"
|
type="primary"
|
@click="handleConfirmSelect"
|
>
|
选择使用
|
</el-button>
|
<el-button
|
v-else
|
type="primary"
|
@click="handleConfirmReplace"
|
>
|
替换使用
|
</el-button>
|
</span>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
import { getQtemplatelist, getQtemplateobj, getQtemplateclassify } from "@/api/AiCentre/index";
|
import store from "@/store";
|
import pagination from "@/components/Pagination";
|
|
export default {
|
name: "TemplateSelector",
|
components: {
|
pagination
|
},
|
props: {
|
// 当前选中的模板ID
|
value: {
|
type: [String, Number],
|
default: null
|
},
|
// 当前选中的模板名称
|
templateName: {
|
type: String,
|
default: ''
|
},
|
// 是否可编辑
|
isEditable: {
|
type: Boolean,
|
default: true
|
},
|
// 是否显示变量配置
|
showVariableConfig: {
|
type: Boolean,
|
default: true
|
},
|
// 服务类型,用于过滤模板
|
serviceType: {
|
type: [String, Number],
|
default: null
|
}
|
},
|
data() {
|
return {
|
// 组件状态
|
drawerVisible: false,
|
previewVisible: false,
|
activeTab: 'basic',
|
loading: false,
|
|
// 模板数据
|
selectedTemplateId: null,
|
selectedTemplateName: '',
|
selectedTemplateData: null,
|
|
// 列表数据
|
templateList: [],
|
questionList: [],
|
variableList: [],
|
previewData: {},
|
|
// 查询参数
|
queryParams: {
|
pageNum: 1,
|
pageSize: 10,
|
svyname: '',
|
isenable: ''
|
},
|
total: 0,
|
|
// 选项数据
|
categoryOptions: [],
|
appraisalOptions: store.getters.appraiselist || [],
|
usableOptions: [
|
{ value: "0", label: "可用" },
|
{ value: "1", label: "停用" }
|
],
|
|
// 默认变量
|
transitionList: [
|
{
|
name: "姓名",
|
value: "${name}",
|
fill: "派发时自动匹配",
|
default: true
|
},
|
{
|
name: "地址",
|
value: "${dzz}",
|
fill: "派发时自动匹配",
|
default: true
|
},
|
{
|
name: "智能语音",
|
value: "${dhh}",
|
fill: "派发时自动匹配",
|
default: true
|
}
|
]
|
};
|
},
|
watch: {
|
value: {
|
immediate: true,
|
handler(newVal) {
|
this.selectedTemplateId = newVal;
|
}
|
},
|
templateName: {
|
immediate: true,
|
handler(newVal) {
|
|
this.selectedTemplateName = newVal;
|
}
|
},
|
selectedTemplateId(newVal) {
|
this.$emit('input', newVal);
|
},
|
selectedTemplateName(newVal) {
|
this.$emit('update:templateName', newVal);
|
}
|
},
|
created() {
|
this.loadCategories();
|
this.handleSearch();
|
|
},
|
methods: {
|
// 加载模板分类
|
async loadCategories() {
|
try {
|
const response = await getQtemplateclassify({});
|
if (response.code === 200) {
|
this.categoryOptions = response.rows;
|
}
|
} catch (error) {
|
console.error('加载分类失败:', error);
|
}
|
},
|
|
// 搜索模板
|
async handleSearch() {
|
try {
|
this.loading = true;
|
const response = await getQtemplatelist(this.queryParams);
|
if (response.code === 200) {
|
this.templateList = response.rows;
|
this.total = response.total;
|
}
|
} catch (error) {
|
console.error('搜索模板失败:', error);
|
this.$modal.msgError('搜索模板失败');
|
} finally {
|
this.loading = false;
|
}
|
},
|
|
// 重置搜索
|
handleReset() {
|
this.queryParams = {
|
pageNum: 1,
|
pageSize: 10,
|
svyname: '',
|
isenable: ''
|
};
|
this.handleSearch();
|
},
|
|
// 选择模板
|
handleSelectTemplate(row) {
|
this.selectedTemplateData = row;
|
this.loadTemplateDetail(row.svyid);
|
},
|
|
// 预览模板
|
handlePreviewTemplate(row) {
|
this.selectedTemplateData = row;
|
this.loadTemplateDetail(row.svyid);
|
},
|
|
// 加载模板详情
|
async loadTemplateDetail(templateId) {
|
try {
|
this.loading = true;
|
const response = await getQtemplateobj({ svyid: templateId });
|
if (response.code === 200) {
|
const templateData = response.rows[0];
|
this.previewData = templateData;
|
this.questionList = templateData.svyTemplateLibScripts || [];
|
|
// 初始化问题状态
|
this.questionList.forEach(item => {
|
item.qremark = [];
|
});
|
|
// 处理变量
|
this.extractVariables(templateData.svyTemplateLibScripts || []);
|
|
this.previewVisible = true;
|
this.drawerVisible = false;
|
}
|
} catch (error) {
|
console.error('加载模板详情失败:', error);
|
this.$modal.msgError('加载模板详情失败');
|
} finally {
|
this.loading = false;
|
}
|
},
|
|
// 提取变量
|
extractVariables(scripts) {
|
let variableList = [];
|
|
scripts.forEach(script => {
|
try {
|
const otherData = JSON.parse(script.otherdata || '[]');
|
otherData.forEach(item => {
|
if (item.default != 1) {
|
variableList.push({
|
value: item.variate,
|
fill: "",
|
name: item.variatename
|
});
|
}
|
});
|
} catch (e) {
|
console.warn('解析otherdata失败:', e);
|
}
|
});
|
|
// 去重
|
const uniqueVariables = variableList.filter(
|
(obj, index, self) =>
|
index ===
|
self.findIndex(
|
t => t.name === obj.name && t.value === obj.value
|
)
|
);
|
|
this.variableList = [...this.transitionList, ...uniqueVariables];
|
},
|
|
// 预览已选模板
|
handlePreview() {
|
if (!this.selectedTemplateId) {
|
this.$modal.msgWarning('请先选择模板');
|
return;
|
}
|
|
this.loadTemplateDetail(this.selectedTemplateId);
|
},
|
|
// 确认选择模板
|
handleConfirmSelect() {
|
if (!this.selectedTemplateData) {
|
this.$modal.msgWarning('请先选择模板');
|
return;
|
}
|
|
this.selectedTemplateId = this.selectedTemplateData.svyid;
|
this.selectedTemplateName = this.selectedTemplateData.svyname;
|
|
// 转换变量格式
|
const filteredVariables = this.variableList.filter(
|
item => item.name !== "姓名" && item.name !== "电话" && item.name !== "地址"
|
);
|
|
const textParam = this.convertFormat2ToFormat1(filteredVariables);
|
|
// 触发选择事件
|
this.$emit('select', {
|
templateId: this.selectedTemplateId,
|
templateName: this.selectedTemplateName,
|
templateData: this.previewData,
|
variableList: this.variableList,
|
textParam: textParam
|
});
|
|
this.previewVisible = false;
|
this.$modal.msgSuccess('选择模板成功');
|
},
|
|
// 确认替换模板
|
handleConfirmReplace() {
|
this.$modal.confirm('确定要替换当前模板吗?')
|
.then(() => {
|
this.handleConfirmSelect();
|
})
|
.catch(() => {});
|
},
|
|
// 取消预览
|
handleCancelPreview() {
|
this.previewVisible = false;
|
this.$emit('cancel');
|
},
|
|
// 关闭抽屉
|
handleDrawerClose(done) {
|
done();
|
this.$emit('drawer-close');
|
},
|
|
// 关闭预览
|
handlePreviewClose(done) {
|
done();
|
this.$emit('preview-close');
|
},
|
|
// 删除变量
|
handleVariableDelete(index, row) {
|
this.variableList.splice(index, 1);
|
this.$emit('variable-delete', row);
|
},
|
|
// 变量格式转换:数组转对象
|
convertFormat2ToFormat1(data) {
|
let result = {};
|
data.forEach(item => {
|
let innerObj = {};
|
innerObj[item.value] = item.fill;
|
result[item.name] = innerObj;
|
});
|
return result;
|
},
|
|
// 变量格式转换:对象转数组
|
convertFormat1ToFormat2(data) {
|
let result = [];
|
for (let key in data) {
|
let innerKey = Object.keys(data[key])[0];
|
result.push({
|
name: key,
|
value: innerKey,
|
fill: data[key][innerKey]
|
});
|
}
|
return result;
|
},
|
|
// 设置变量
|
setVariables(variables) {
|
if (variables) {
|
const converted = this.convertFormat1ToFormat2(variables);
|
this.variableList = [...this.transitionList, ...converted];
|
}
|
},
|
|
// 清除选择
|
clear() {
|
this.selectedTemplateId = null;
|
this.selectedTemplateName = '';
|
this.selectedTemplateData = null;
|
this.variableList = [...this.transitionList];
|
this.$emit('clear');
|
},
|
|
// 获取变量数据
|
getVariables() {
|
const filteredVariables = this.variableList.filter(
|
item => item.name !== "姓名" && item.name !== "电话" && item.name !== "地址"
|
);
|
return this.convertFormat2ToFormat1(filteredVariables);
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.template-selector {
|
&__header {
|
margin-bottom: 20px;
|
}
|
|
&__variables {
|
margin-top: 20px;
|
padding: 20px;
|
background: #f5f7fa;
|
border-radius: 4px;
|
|
.el-table {
|
background: transparent;
|
}
|
}
|
}
|
|
.drawer-content {
|
padding: 20px;
|
|
.el-form {
|
margin-bottom: 20px;
|
}
|
}
|
|
.preview-content {
|
max-height: 600px;
|
overflow-y: auto;
|
padding: 20px;
|
|
.scriptTopic-dev {
|
margin-bottom: 25px;
|
font-size: 16px;
|
|
.dev-text {
|
margin-bottom: 10px;
|
font-weight: 500;
|
color: #333;
|
|
span {
|
margin-left: 10px;
|
color: #666;
|
}
|
}
|
|
.dev-xx {
|
padding-left: 20px;
|
}
|
}
|
}
|
|
::v-deep .el-drawer__body {
|
padding: 0;
|
}
|
|
::v-deep .el-table {
|
font-size: 14px;
|
}
|
|
::v-deep .el-table__row {
|
cursor: pointer;
|
|
&:hover {
|
background-color: #f5f7fa;
|
}
|
}
|
</style>
|