1217 lines
34 KiB
Vue
1217 lines
34 KiB
Vue
<template>
|
||
<a-modal
|
||
:visible="modalVisible"
|
||
:maskClosable="false"
|
||
:destroyOnClose="true"
|
||
:footer="null"
|
||
:width="947"
|
||
:zIndex="1001"
|
||
@cancel="closeHandle"
|
||
>
|
||
<!-- 弹窗标题 -->
|
||
<template v-if="curTemp?.type === 101" v-slot:title>
|
||
<div class="custom-head">
|
||
<div class="custom-head-text">调研方案配置</div>
|
||
<a-tooltip
|
||
placement="rightTop"
|
||
:overlayStyle="{
|
||
'max-width': '804px',
|
||
}"
|
||
>
|
||
<template v-slot:title>
|
||
<div class="custom-head-tip">
|
||
<div class="custom-head-tip-fz14" style="margin-bottom: 8px">说明</div>
|
||
<div class="custom-head-tip-fz12" style="margin-bottom: 16px">
|
||
此处主要配置问卷内产品内包装测试、外包装测试、货架可见度认知和堆头可见度认知四个模块的产品包装,一个产品包装由产品名称、一个包装类型和一张图片组成。您至少配置一个产品包装,每个模块配置几个产品包装就会对应生成几组相关题目。
|
||
</div>
|
||
<div class="custom-head-tip-fz14" style="margin-bottom: 8px">示例</div>
|
||
<div class="custom-head-tip-fz12" style="margin-bottom: 8px">
|
||
示例四个模块分别配置了一个产品包装,创建的问卷中对应的部分题目见下图,区别于普通题型,固定题型会展示固定标签以及对应产品包装信息。
|
||
</div>
|
||
<div class="pack_example">
|
||
<img
|
||
class="custom-head-tip-img"
|
||
src="../../../assets/img/design/pack_example1.png"
|
||
/>
|
||
<img
|
||
class="custom-head-tip-img"
|
||
src="../../../assets/img/design/pack_example2.png"
|
||
/>
|
||
<img
|
||
class="custom-head-tip-img"
|
||
src="../../../assets/img/design/pack_example3.png"
|
||
/>
|
||
<img
|
||
class="custom-head-tip-img"
|
||
src="../../../assets/img/design/pack_example4.png"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<i class="iconfont"></i>
|
||
</a-tooltip>
|
||
</div>
|
||
</template>
|
||
<template v-else v-slot:title>
|
||
<div class="custom-head">
|
||
<div>创建问卷</div>
|
||
</div>
|
||
</template>
|
||
<div class="create-survey">
|
||
<div class="create-survey-scroll scrollbar">
|
||
<div class="create-survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">问卷配置</div>
|
||
</div>
|
||
<a-form
|
||
ref="formRef"
|
||
:model="ruleForm"
|
||
:rules="rules"
|
||
:label-col="{ span: 3 }"
|
||
labelAlign="right"
|
||
>
|
||
<a-form-item label="问卷名称" name="project_name">
|
||
<a-input
|
||
class="custom-input"
|
||
v-model:value="ruleForm.project_name"
|
||
style="width: 50%"
|
||
@keydown.enter="onSubmit"
|
||
placeholder="请输入问卷名称"
|
||
:maxlength="30"
|
||
>
|
||
<template #suffix>
|
||
<span class="suffix">
|
||
{{ `${ruleForm.project_name.length}/30` }}
|
||
</span>
|
||
</template>
|
||
</a-input>
|
||
</a-form-item>
|
||
<a-form-item label="问卷标签" name="tags" v-if="isShow">
|
||
<a-select
|
||
class="custom-select"
|
||
v-model:value="ruleForm.tags"
|
||
style="width: 50%"
|
||
mode="multiple"
|
||
placeholder="搜索标签"
|
||
:filterOption="filterOption"
|
||
>
|
||
<a-select-option
|
||
:value="item.id"
|
||
:label="item.title"
|
||
v-for="item in tagsList"
|
||
:key="item.id"
|
||
>
|
||
<div style="display: flex; justify-content: space-between">
|
||
<span :style="countColor(item.color)" :title="item.title">{{ item.title }}</span>
|
||
</div>
|
||
</a-select-option>
|
||
</a-select>
|
||
</a-form-item>
|
||
<a-form-item label="问卷简介" name="remarks" v-if="isShow">
|
||
<div class="form-text">
|
||
<a-textarea
|
||
v-model:value="ruleForm.remarks"
|
||
:maxlength="150"
|
||
:rows="4"
|
||
placeholder="请输入"
|
||
style="width: 100%"
|
||
/>
|
||
<span class="form-text-count">{{ ruleForm.remarks.length }}/150</span>
|
||
</div>
|
||
</a-form-item>
|
||
</a-form>
|
||
<!-- 口味 -->
|
||
<template v-if="curTemp?.type === 100">
|
||
<div class="create-survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">口味配置</div>
|
||
<flavor-tip />
|
||
</div>
|
||
<div class="create-survey-attr">
|
||
<div class="create-survey-attr-right kouwei-peizhi">
|
||
<div
|
||
class="create-survey-attr-right-item"
|
||
:class="{ 'create-survey-attr-right-item-error': item.status }"
|
||
v-for="(item, index) in flavorList"
|
||
:key="index"
|
||
>
|
||
<div class="create-survey-attr-right-item-input">
|
||
<label class="create-survey-attr-label">产品名称</label>
|
||
<a-input
|
||
v-model:value="item.productName"
|
||
class="create-custom-input"
|
||
showCount
|
||
:maxlength="30"
|
||
placeholder="请输入测试产品名称"
|
||
>
|
||
<template #suffix>
|
||
<span class="suffix">
|
||
{{ `${item.productName.length}/30` }}
|
||
</span>
|
||
</template>
|
||
</a-input>
|
||
<label class="create-survey-attr-label kouweimingcheng">口味名称</label>
|
||
<a-input
|
||
v-model:value="item.flavorName"
|
||
class="create-custom-input"
|
||
showCount
|
||
:maxlength="30"
|
||
placeholder="请输入产品口味名称"
|
||
>
|
||
<template #suffix>
|
||
<span class="suffix">
|
||
{{ `${item.flavorName.length}/30` }}
|
||
</span>
|
||
</template>
|
||
</a-input>
|
||
<i
|
||
v-if="flavorList.length < 20"
|
||
class="iconfont addfont"
|
||
@click="addFlavor(index)"
|
||
></i
|
||
>
|
||
<i v-if="flavorList.length > 1" class="iconfont addfont" @click="delFlavor(index)"
|
||
></i
|
||
>
|
||
</div>
|
||
<div class="create-survey-attr-right-item-text">
|
||
{{ item.text }}
|
||
</div>
|
||
</div>
|
||
<div class="desc">
|
||
<i class="iconfont"></i>
|
||
口味名称例如“草莓味”输入“草莓”即可;如有复合口味请用“;”分隔,例如“蜜桃;乌龙”。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="create-survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">示例</div>
|
||
</div>
|
||
<div class="create-survey-attr">
|
||
<img
|
||
class="create-survey-attr-img"
|
||
src="../../../assets/img/design/flavor_example.png"
|
||
/>
|
||
</div>
|
||
</template>
|
||
<!-- 包装 -->
|
||
<template v-else>
|
||
<!-- 产品内包装测试 -->
|
||
<div class="create-survey-title survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">产品内包装测试</div>
|
||
</div>
|
||
<packing-card-list
|
||
title="请配置参与调研的产品内包装"
|
||
addText="新增产品内包装"
|
||
v-model:list="packingData.inner"
|
||
/>
|
||
<!-- 产品外包装测试 -->
|
||
<div class="create-survey-title survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">产品外包装测试</div>
|
||
</div>
|
||
<packing-card-list
|
||
title="请配置参与调研的产品外包装"
|
||
addText="新增产品外包装"
|
||
v-model:list="packingData.outer"
|
||
/>
|
||
<!-- 货架可见度认知 -->
|
||
<div class="create-survey-title survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">货架可见度认知</div>
|
||
</div>
|
||
<packing-img-list title="请上传货架图片" v-model:imgs="packingData.shelvesImgs" />
|
||
<packing-card-list
|
||
title="请配置参与调研的产品包装"
|
||
addText="新增产品包装"
|
||
v-model:list="packingData.shelves"
|
||
/>
|
||
<!-- 堆头可见度认知 -->
|
||
<div class="create-survey-title survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">堆头可见度认知</div>
|
||
</div>
|
||
<packing-img-list title="请上传堆头图片" v-model:imgs="packingData.stackImgs" />
|
||
<packing-card-list
|
||
title="请配置参与调研的产品包装"
|
||
addText="新增产品包装"
|
||
v-model:list="packingData.stack"
|
||
/>
|
||
<!-- 示例 -->
|
||
<div class="create-survey-title">
|
||
<div class="create-survey-title-line"></div>
|
||
<div class="create-survey-title-text">示例</div>
|
||
</div>
|
||
<div class="create-survey-attr">
|
||
<img class="create-survey-attr-img" src="../../../assets/img/design/pack_example.png" />
|
||
</div>
|
||
</template>
|
||
</div>
|
||
<div class="create-survey-footer">
|
||
<a-button
|
||
class="custom-button"
|
||
style="margin-right: 12px"
|
||
type="default"
|
||
@click="closeHandle"
|
||
>取消</a-button
|
||
>
|
||
<a-button class="custom-button" type="primary" :loading="loading" @click="onSubmit"
|
||
>确定</a-button
|
||
>
|
||
</div>
|
||
<a-modal v-model:visible="visibleTags" title="新建标签" :destroyOnClose="true" :footer="null">
|
||
<addTag @cancel="visibleTags = false" @update="addTagUpdata"></addTag>
|
||
</a-modal>
|
||
</div>
|
||
</a-modal>
|
||
</template>
|
||
<script>
|
||
import { defineComponent, reactive, ref, watch, onBeforeMount, createVNode } from "vue";
|
||
import { useRouter } from "vue-router";
|
||
import { message, Modal } from "ant-design-vue";
|
||
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
|
||
import {
|
||
postSurvey,
|
||
renewSurvey,
|
||
getTagsList,
|
||
deleteTags,
|
||
useTempCreateProject,
|
||
} from "@/views/ProjectManage/api.js";
|
||
import addTag from "@/views/ProjectManage/components/addTag.vue";
|
||
import useEmitter from "@/composables/useEmitter";
|
||
import { baseOss } from "../../../config";
|
||
import PackingCardList from "./Packing/PackingCardList.vue";
|
||
import PackingImgList from "./Packing/PackingImgList.vue";
|
||
import FlavorTip from "./Flavor/FlavorTip.vue";
|
||
|
||
// 包装测试初始化数据
|
||
const packingInit = JSON.stringify({
|
||
inner: [
|
||
{
|
||
text: "",
|
||
status: false,
|
||
packImg: "", // 产品图片
|
||
packName: "", // 产品名称
|
||
packType: "", // 包装类型
|
||
},
|
||
],
|
||
outer: [
|
||
{
|
||
text: "",
|
||
status: false,
|
||
packImg: "", // 产品图片
|
||
packName: "", // 产品名称
|
||
packType: "", // 包装类型
|
||
},
|
||
],
|
||
shelvesImgs: {
|
||
text: "",
|
||
status: false,
|
||
urls: [], // 货架图片
|
||
},
|
||
shelves: [
|
||
{
|
||
text: "",
|
||
status: false,
|
||
packImg: "", // 产品图片
|
||
packName: "", // 产品名称
|
||
packType: "", // 包装类型
|
||
},
|
||
],
|
||
stackImgs: {
|
||
text: "",
|
||
status: false,
|
||
urls: [], // 堆头图片
|
||
},
|
||
stack: [
|
||
{
|
||
text: "",
|
||
status: false,
|
||
packImg: "", // 产品图片
|
||
packName: "", // 产品名称
|
||
packType: "", // 包装类型
|
||
},
|
||
],
|
||
});
|
||
|
||
export default defineComponent({
|
||
name: "CreateSurveySell",
|
||
props: {
|
||
groupId: { type: Number, value: 0 },
|
||
info: { type: Object, default: () => {} },
|
||
temp_sn: { type: String, default: "" },
|
||
curTemp: { type: Object, default: () => {} },
|
||
groupList: {
|
||
type: Array,
|
||
required: true,
|
||
},
|
||
extendJson: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
},
|
||
components: {
|
||
// PlusOutlined,
|
||
// EditOutlined,
|
||
// DeleteOutlined,
|
||
addTag,
|
||
PackingCardList,
|
||
PackingImgList,
|
||
FlavorTip,
|
||
// VNodes: (_, { attrs }) => {
|
||
// return attrs.vnodes;
|
||
// }
|
||
},
|
||
setup(props, context) {
|
||
const emitter = useEmitter();
|
||
const modalVisible = ref(false);
|
||
const items = ref([]);
|
||
const router = useRouter();
|
||
const formRef = ref();
|
||
const tagsList = ref([]);
|
||
const loading = ref(false);
|
||
const isShow = ref(props.info.sn ? false : true);
|
||
const ruleForm = reactive({
|
||
project_name: props.info?.project_name || "",
|
||
tags: props.info?.tag || [],
|
||
group_id: props?.groupId || 0,
|
||
remarks: props.remarks || "",
|
||
});
|
||
const rules = {
|
||
project_name: [
|
||
{ required: true, message: "请输入问卷名称", trigger: "blur" },
|
||
{ min: 1, max: 30, message: "字数超过限制", trigger: "blur" },
|
||
],
|
||
};
|
||
const visibleTags = ref(false);
|
||
|
||
watch(
|
||
() => props,
|
||
() => {
|
||
ruleForm.group_id = props?.groupId || 0;
|
||
ruleForm.project_name = props.info?.project_name || "";
|
||
ruleForm.tags = props.info?.tag || [];
|
||
ruleForm.remarks = props.info?.remarks || "";
|
||
isShow.value = props.info.sn ? false : true;
|
||
},
|
||
{ deep: true }
|
||
// () => props.groupId,
|
||
// () => {
|
||
// ruleForm.group_id = props?.groupId || 0;
|
||
// },
|
||
// () => props.info,
|
||
// () => {
|
||
// ruleForm.project_name = props.info?.project_name || '';
|
||
// }
|
||
);
|
||
|
||
const openModal = () => {
|
||
modalVisible.value = true;
|
||
};
|
||
|
||
const closeModal = () => {
|
||
modalVisible.value = false;
|
||
};
|
||
|
||
// 标签颜色
|
||
const countColor = (value) => {
|
||
let style = {};
|
||
switch (value) {
|
||
case 1:
|
||
style = {
|
||
color: "#4DB8FA",
|
||
border: "1px solid #4DB8FA",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
break;
|
||
case 2:
|
||
style = {
|
||
color: "#0CC126",
|
||
// 'border-color' : '#0CC126',
|
||
border: "1px solid #0CC126",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
break;
|
||
case 3:
|
||
style = {
|
||
color: "#FF8800",
|
||
// 'border-color' : '#FF8800',
|
||
border: "1px solid #FF8800",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
break;
|
||
case 4:
|
||
style = {
|
||
color: "#FF374F",
|
||
// 'border-color' : '#FF374F',
|
||
border: "1px solid #FF374F",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
break;
|
||
case 5:
|
||
style = {
|
||
color: "#1C6FFF",
|
||
// 'border-color' : '#1C6FFF',
|
||
border: "1px solid #1C6FFF",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
break;
|
||
case 6:
|
||
style = {
|
||
color: "#11AEA7",
|
||
// 'border-color' : '#11AEA7',
|
||
border: "1px solid #11AEA7",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
break;
|
||
case 7:
|
||
style = {
|
||
color: "#25D8C8",
|
||
// 'border-color' : '#25D8C8',
|
||
border: "1px solid #25D8C8",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
break;
|
||
case 8:
|
||
style = {
|
||
color: "#FECB0D",
|
||
// 'border-color' : '#FECB0D',
|
||
border: "1px solid #FECB0D",
|
||
padding: "0 5px",
|
||
"border-radius": "4px",
|
||
"line-height": "20px",
|
||
};
|
||
// break;
|
||
// case 9:
|
||
// style = {
|
||
// 'color' : '4DB8FA',
|
||
// 'border-color' : '4DB8FA',
|
||
// }
|
||
}
|
||
return style;
|
||
};
|
||
|
||
// 使用模版
|
||
const toSub = async () => {
|
||
loading.value = true;
|
||
let data;
|
||
try {
|
||
if (props.info?.sn) {
|
||
// 修改
|
||
data = await renewSurvey({ ...ruleForm, sn: props.info.sn });
|
||
context.emit("update");
|
||
} else {
|
||
let params = {
|
||
...ruleForm,
|
||
};
|
||
if (props.curTemp.type === 100) {
|
||
// 使用口味模版
|
||
params.taste_test_list = flavorList.value.map((item) => ({
|
||
product_title: item.productName,
|
||
taste_title: item.flavorName,
|
||
}));
|
||
} else {
|
||
// 使用包装模版
|
||
params.internal_package_test_list = packingData.value.inner
|
||
.filter((item) => !item.status)
|
||
.map((item) => ({
|
||
product_picture: item.packImg,
|
||
product_title: item.packName,
|
||
taste_title: item.packType,
|
||
}));
|
||
params.outer_package_test_list = packingData.value.outer
|
||
.filter((item) => !item.status)
|
||
.map((item) => ({
|
||
product_picture: item.packImg,
|
||
product_title: item.packName,
|
||
taste_title: item.packType,
|
||
}));
|
||
params.shelves_cover_picture = packingData.value.stackImgs.urls;
|
||
params.package_shelves_test_list = packingData.value.stack
|
||
.filter((item) => !item.status)
|
||
.map((item) => ({
|
||
product_picture: item.packImg,
|
||
product_title: item.packName,
|
||
taste_title: item.packType,
|
||
}));
|
||
params.package_cover_picture = packingData.value.shelvesImgs.urls;
|
||
params.package_pile_test_list = packingData.value.shelves
|
||
.filter((item) => !item.status)
|
||
.map((item) => ({
|
||
product_picture: item.packImg,
|
||
product_title: item.packName,
|
||
taste_title: item.packType,
|
||
}));
|
||
}
|
||
params.extendJson = props.extendJson;
|
||
useTempCreateProject(props.temp_sn, params).then((res) => {
|
||
context.emit("update");
|
||
context.emit("close");
|
||
setTimeout(() => {
|
||
router.push({
|
||
path: "/survey/planet/design",
|
||
query: { sn: res.data.sn },
|
||
});
|
||
}, 300);
|
||
});
|
||
}
|
||
message.success("保存成功");
|
||
} catch (error) {
|
||
console.log(error);
|
||
// context.message.warning(
|
||
// error.data?.message || error.message || "服务器错误"
|
||
// );
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
/** 获取项目标签列表 */
|
||
const getTagsListRequest = async (val) => {
|
||
try {
|
||
const { data } = await getTagsList();
|
||
tagsList.value = data;
|
||
} catch (error) {
|
||
context.message.error(error.data?.message || error.message || "服务器错误");
|
||
}
|
||
};
|
||
|
||
// 删除
|
||
const delRequest = async (id) => {
|
||
try {
|
||
const { data } = await deleteTags(id);
|
||
getTagsListRequest();
|
||
} catch (error) {
|
||
console.log(error);
|
||
}
|
||
};
|
||
|
||
const del = (id) => {
|
||
Modal.confirm({
|
||
content: "删除后,此标签会从当前团队的所有问卷中移除,且无法恢复!",
|
||
icon: () => createVNode(ExclamationCircleOutlined),
|
||
cancelText: "取消",
|
||
okText: "确认",
|
||
zIndex: 100001,
|
||
onOk: () => {
|
||
delRequest(id);
|
||
},
|
||
});
|
||
};
|
||
|
||
const edit = (item) => {
|
||
context.emit("labelEdit", item);
|
||
};
|
||
|
||
const addItem = () => {
|
||
emitter.emit("addGroup");
|
||
};
|
||
|
||
const addTag = () => {
|
||
visibleTags.value = true;
|
||
};
|
||
|
||
const addTagUpdata = () => {
|
||
visibleTags.value = false;
|
||
getTagsListRequest();
|
||
};
|
||
|
||
// 取消
|
||
const closeHandle = () => {
|
||
const hasTags = ruleForm.tags.length > 0;
|
||
const hasRemarks = ruleForm.remarks.length > 0;
|
||
const hasProjectName = ruleForm.project_name.length > 0;
|
||
if (hasProjectName || hasTags || hasRemarks) {
|
||
Modal.confirm({
|
||
title: "确认关闭?",
|
||
content: "关闭后当前方案配置无法恢复!",
|
||
cancelText: "取消",
|
||
okText: "确认",
|
||
zIndex: 100001,
|
||
class: "custom-modal custom-modal-title-confirm-notice",
|
||
onOk() {
|
||
flavorList.value = [
|
||
{
|
||
text: "",
|
||
status: false,
|
||
flavorName: "", // 口味名称
|
||
productName: "", // 产品名称
|
||
},
|
||
];
|
||
packingData.value = JSON.parse(packingInit);
|
||
ruleForm.tags = [];
|
||
ruleForm.remarks = "";
|
||
ruleForm.project_name = "";
|
||
modalVisible.value = false;
|
||
},
|
||
});
|
||
} else {
|
||
flavorList.value = [
|
||
{
|
||
text: "",
|
||
status: false,
|
||
flavorName: "", // 口味名称
|
||
productName: "", // 产品名称
|
||
},
|
||
];
|
||
packingData.value = JSON.parse(packingInit);
|
||
modalVisible.value = false;
|
||
}
|
||
};
|
||
|
||
// 确定
|
||
const onSubmit = () => {
|
||
let flavorStatus = false;
|
||
let packingStatus = false;
|
||
if (props.curTemp.type === 100) {
|
||
// 校验口味测试
|
||
flavorList.value.forEach((favor, index) => {
|
||
flavorBlur(favor, index);
|
||
});
|
||
flavorStatus = flavorList.value.findIndex((favor) => favor.status) !== -1;
|
||
} else if (props.curTemp.type === 101) {
|
||
// 校验包装测试
|
||
packingStatus = validatePacking();
|
||
// console.log("校验包装测试:", packingStatus);
|
||
}
|
||
formRef.value
|
||
.validate()
|
||
.then(() => {
|
||
if (flavorStatus || packingStatus) return;
|
||
var exec = async () => {
|
||
await toSub();
|
||
await getTagsListRequest();
|
||
};
|
||
Modal.confirm({
|
||
title: "确认保存?",
|
||
content: "保存后方案配置无法编辑,请您再次确认已完成最终配置!",
|
||
cancelText: "取消",
|
||
okText: "确认",
|
||
class: "custom-modal custom-modal-title-confirm-notice",
|
||
zIndex: 100001,
|
||
onOk: exec,
|
||
});
|
||
})
|
||
.catch((error) => {
|
||
console.log("error", error);
|
||
});
|
||
};
|
||
|
||
function filterOption(inputValue, option) {
|
||
const reg = new RegExp(inputValue);
|
||
const result = reg.test(option.label);
|
||
return result;
|
||
}
|
||
|
||
onBeforeMount(() => {
|
||
getTagsListRequest();
|
||
});
|
||
|
||
// 口味配置
|
||
const flavorList = ref([
|
||
{
|
||
text: "",
|
||
status: false,
|
||
flavorName: "", // 口味名称
|
||
productName: "", // 产品名称
|
||
},
|
||
]);
|
||
// 包装测试
|
||
const packingData = ref(JSON.parse(packingInit));
|
||
|
||
// 添加口味配置
|
||
const addFlavor = (index) => {
|
||
if (flavorList.value.length === 20) return;
|
||
flavorList.value.splice(index + 1, 0, {
|
||
text: "",
|
||
status: true,
|
||
flavorName: "",
|
||
productName: "",
|
||
});
|
||
};
|
||
|
||
// 删除口味配置
|
||
const delFlavor = (index) => {
|
||
flavorList.value.splice(index, 1);
|
||
};
|
||
|
||
// 口味配置输入框失去焦点
|
||
const flavorBlur = (item, index) => {
|
||
const hasSameAttr = flavorList.value.find(
|
||
(sm, smIndex) =>
|
||
smIndex !== index &&
|
||
sm.productName === item.productName &&
|
||
sm.flavorName === item.flavorName
|
||
);
|
||
if (item.productName.length === 0) {
|
||
item.status = true;
|
||
item.text = "产品名称不能为空";
|
||
} else if (item.flavorName.length === 0) {
|
||
item.status = true;
|
||
item.text = "口味名称不能为空";
|
||
} else if (hasSameAttr) {
|
||
item.status = true;
|
||
item.text = "口味配置不能重复";
|
||
} else {
|
||
item.status = false;
|
||
item.text = false;
|
||
}
|
||
};
|
||
|
||
// 校验包装测试
|
||
function validatePacking() {
|
||
const innerStatus = validatePackingCardList(packingData.value.inner);
|
||
const outerStatus = validatePackingCardList(packingData.value.outer);
|
||
const stackStatus = validatePackingCardList(packingData.value.stack);
|
||
const shelvesStatus = validatePackingCardList(packingData.value.shelves);
|
||
const stackImgsStatus = validatePackingImgList(packingData.value.stackImgs);
|
||
const shelvesImgsStatus = validatePackingImgList(packingData.value.shelvesImgs);
|
||
// 至少有1个完整产品包装
|
||
if (innerStatus && outerStatus && stackStatus && shelvesStatus) {
|
||
message.warning("暂无完整产品包装信息,请检查后重试!");
|
||
return true;
|
||
}
|
||
// 存在包装信息不完整
|
||
if (
|
||
(innerStatus && (packingData.value.inner.length > 1 || packingData.value.inner[0].text)) ||
|
||
(outerStatus && (packingData.value.outer.length > 1 || packingData.value.outer[0].text)) ||
|
||
(stackStatus && (packingData.value.stack.length > 1 || packingData.value.stack[0].text)) ||
|
||
(shelvesStatus &&
|
||
(packingData.value.shelves.length > 1 || packingData.value.shelves[0].text)) ||
|
||
(!stackStatus && stackImgsStatus) ||
|
||
(!shelvesStatus && shelvesImgsStatus)
|
||
) {
|
||
message.warning("部分包装信息不完整,请检查后重试!");
|
||
return true;
|
||
}
|
||
// 若存在堆头图片却未上传包装图片
|
||
if (stackStatus && !stackImgsStatus) {
|
||
message.warning("请上传参与堆头可见度调研的包装图片!");
|
||
return true;
|
||
}
|
||
// 若存在货架图片却未上传包装图片
|
||
if (shelvesStatus && !shelvesImgsStatus) {
|
||
message.warning("请上传参与货架可见度调研的包装图片!");
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// 校验包装测试卡片列表
|
||
function validatePackingCardList(list) {
|
||
list.forEach((item, index) => {
|
||
if (list.length === 1 && !item.packName && !item.packType && !item.packImg) {
|
||
item.status = true;
|
||
item.text = "";
|
||
} else if (!item.packName) {
|
||
item.status = true;
|
||
item.text = "产品名称不能为空";
|
||
} else if (!item.packType) {
|
||
item.status = true;
|
||
item.text = "包装类型不能为空";
|
||
} else if (!item.packImg) {
|
||
item.status = true;
|
||
item.text = "请上传产品图片";
|
||
} else {
|
||
const hasSameAttr = list.find(
|
||
(sm, smIndex) =>
|
||
smIndex !== index && sm.packName === item.packName && sm.packType === item.packType
|
||
);
|
||
if (hasSameAttr) {
|
||
item.status = true;
|
||
item.text = "产品包装不能重复";
|
||
} else {
|
||
item.status = false;
|
||
item.text = "";
|
||
}
|
||
}
|
||
});
|
||
const index = list.findIndex((item) => item.status);
|
||
return index !== -1;
|
||
}
|
||
|
||
// 校验包装测试图片列表
|
||
function validatePackingImgList(imgs) {
|
||
imgs.status = imgs.urls.length ? false : true;
|
||
return imgs.status;
|
||
}
|
||
|
||
return {
|
||
modalVisible,
|
||
openModal,
|
||
closeModal,
|
||
formRef,
|
||
rules,
|
||
ruleForm,
|
||
closeHandle,
|
||
onSubmit,
|
||
loading,
|
||
options: [],
|
||
del,
|
||
edit,
|
||
items,
|
||
addItem,
|
||
addTag,
|
||
tagsList,
|
||
filterOption,
|
||
getTagsListRequest,
|
||
visibleTags,
|
||
addTagUpdata,
|
||
countColor,
|
||
isShow,
|
||
baseOss,
|
||
flavorList,
|
||
addFlavor,
|
||
delFlavor,
|
||
flavorBlur,
|
||
packingData,
|
||
};
|
||
},
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.icon {
|
||
font-size: 16px;
|
||
|
||
.del {
|
||
margin: 0 10px;
|
||
}
|
||
}
|
||
|
||
.tags {
|
||
margin: 0 5px 5px;
|
||
min-width: 75px;
|
||
width: 48px;
|
||
height: 19px;
|
||
border-radius: 4px;
|
||
// position: relative;
|
||
box-sizing: border-box;
|
||
|
||
.title {
|
||
// position: absolute;
|
||
font-size: 12px;
|
||
font-family: PingFangSC-Regular, PingFang SC;
|
||
font-weight: 400;
|
||
line-height: 17px;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
.tagStyle {
|
||
border-radius: 4px;
|
||
max-width: 120px;
|
||
padding: 0 5px;
|
||
margin: 0 5px;
|
||
display: inline-block;
|
||
border-width: 1px;
|
||
border-style: solid;
|
||
color: #4db8fa;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
}
|
||
}
|
||
|
||
.show-select {
|
||
.icon {
|
||
// display: none !important;
|
||
}
|
||
}
|
||
.create-survey {
|
||
&-title {
|
||
display: flex;
|
||
margin-bottom: 24px;
|
||
|
||
&-line {
|
||
width: 4px;
|
||
height: 16px;
|
||
background: #70b936;
|
||
border-radius: 0px 0px 0px 0px;
|
||
margin-top: 2.5px;
|
||
}
|
||
|
||
&-text {
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: #262626;
|
||
margin-left: 8px;
|
||
}
|
||
}
|
||
|
||
&-attr {
|
||
display: flex;
|
||
margin-bottom: 14px;
|
||
|
||
&-label {
|
||
position: relative;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
height: 32px;
|
||
color: rgba(0, 0, 0, 0.85);
|
||
font-size: 14px;
|
||
margin-right: 12px;
|
||
word-break: keep-all;
|
||
|
||
&::before {
|
||
display: inline-block;
|
||
margin-right: 4px;
|
||
color: #ff4d4f;
|
||
font-size: 14px;
|
||
font-family: SimSun, sans-serif;
|
||
line-height: 1;
|
||
content: "*";
|
||
}
|
||
}
|
||
|
||
&-right {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
|
||
&-item {
|
||
position: relative;
|
||
flex: 1;
|
||
|
||
&-input {
|
||
display: flex;
|
||
align-items: center;
|
||
width: 260px;
|
||
margin-right: 11px;
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
&-text {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 34px;
|
||
color: rgba(0, 0, 0, 0.45);
|
||
height: 0;
|
||
font-size: 14px;
|
||
line-height: 1.5715;
|
||
transition: all 0.3s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||
overflow: hidden;
|
||
}
|
||
|
||
&-error {
|
||
.create-survey-attr-right-item-text {
|
||
height: 24px;
|
||
color: #ff4d4f;
|
||
}
|
||
|
||
&::v-deep {
|
||
.create-custom-input {
|
||
border-color: #ff4d4f;
|
||
&:focus {
|
||
box-shadow: 0 0 0 2px rgb(255 77 79 / 20%);
|
||
}
|
||
&:hover {
|
||
border-color: #ff4d4f;
|
||
}
|
||
}
|
||
.ant-input-affix-wrapper-focused {
|
||
box-shadow: 0 0 0 2px rgb(255 77 79 / 20%);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.addfont {
|
||
margin-left: 10px;
|
||
cursor: pointer;
|
||
color: #bfbfbf;
|
||
|
||
&:hover {
|
||
color: #434343;
|
||
}
|
||
}
|
||
}
|
||
|
||
&-img {
|
||
width: 540px;
|
||
}
|
||
}
|
||
|
||
&-scroll {
|
||
max-height: calc(100vh - 360px);
|
||
padding-right: 6px;
|
||
overflow: auto;
|
||
}
|
||
|
||
&-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
padding-top: 24px;
|
||
}
|
||
}
|
||
|
||
.custom-head {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
&-text {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
color: #262626;
|
||
}
|
||
|
||
.iconfont {
|
||
margin-left: 9px;
|
||
color: $yili-default-color;
|
||
cursor: pointer;
|
||
|
||
&:hover {
|
||
opacity: 0.8;
|
||
}
|
||
}
|
||
|
||
&-tip {
|
||
padding: 14px 25px;
|
||
|
||
&-fz14 {
|
||
line-height: 22px;
|
||
font-size: 14px;
|
||
}
|
||
|
||
&-fz12 {
|
||
line-height: 22px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
&-img {
|
||
width: 208px;
|
||
height: 140px;
|
||
}
|
||
|
||
.pack_example {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: space-between;
|
||
|
||
img {
|
||
width: 360px;
|
||
margin-bottom: 10px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.form-text {
|
||
position: relative;
|
||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||
border: 1px solid #d9d9d9;
|
||
border-radius: 4px;
|
||
|
||
&-count {
|
||
position: absolute;
|
||
right: 12px;
|
||
bottom: 5px;
|
||
background: #ffffff;
|
||
font-size: 14px;
|
||
color: rgba(0, 0, 0, 0.45);
|
||
}
|
||
|
||
&:hover {
|
||
border: 1px solid #8ec75a;
|
||
}
|
||
|
||
&:focus {
|
||
border: 1px solid #8ec75a;
|
||
}
|
||
|
||
&::v-deep .ant-input {
|
||
width: 92%;
|
||
border: none;
|
||
box-shadow: none;
|
||
|
||
&:hover {
|
||
border: none;
|
||
box-shadow: none;
|
||
}
|
||
|
||
&:focus {
|
||
border: none;
|
||
box-shadow: none;
|
||
}
|
||
|
||
&::placeholder {
|
||
line-height: 24px;
|
||
}
|
||
}
|
||
}
|
||
|
||
::v-deep .ant-input-textarea-clear-icon {
|
||
margin: 4px 3px 0 0;
|
||
}
|
||
|
||
::v-deep .ant-input-suffix {
|
||
color: rgba(0, 0, 0, 0.45);
|
||
}
|
||
|
||
::v-deep .ant-form-item .ant-input-textarea-show-count::after {
|
||
position: absolute;
|
||
bottom: 5px;
|
||
right: 2px;
|
||
background: #ffffff;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
::v-deep .ant-input-affix-wrapper {
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.kouwei-peizhi {
|
||
width: 100%;
|
||
display: block;
|
||
|
||
.kouweimingcheng {
|
||
margin-left: 17px;
|
||
}
|
||
|
||
.create-survey-attr-right-item-input {
|
||
width: auto;
|
||
|
||
.create-custom-input {
|
||
width: 328px;
|
||
}
|
||
}
|
||
|
||
.desc {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 12px;
|
||
color: #bfbfbf;
|
||
line-height: 22px;
|
||
|
||
.iconfont {
|
||
font-size: 12px;
|
||
margin-right: 6px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.survey-title {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
:deep(.ant-form-item-label) {
|
||
max-width: 9.5%;
|
||
}
|
||
</style>
|