Merge branch 'master' into feature-creative-center-v2
# src/router/index.js # src/views/Home/components/Avatar.vue
6
.env.dev
@@ -3,11 +3,13 @@ VUE_APP_CURRENTMODE = 'dev'
|
||||
|
||||
VUE_APP_BASEOSS = 'https://diaoyan-files.automark.cc'
|
||||
#VUE_APP_BASEURL = 'http://planetg-java.test.automark.cc/'
|
||||
VUE_APP_BASEURL = 'http://ylst-api-uat.dctest.digitalyili.com/'
|
||||
VUE_APP_BASEURL = 'http://yls-api-uat.dctest.digitalyili.com/'
|
||||
|
||||
VUE_APP_DELiVERY_BASEURL='https://javaxq.test.automark.cc/'
|
||||
VUE_APP_MESSAGE_CENTER ='http://gtech-gateway.dcin-test.digitalyili.com/apigtech/message-send-center/';
|
||||
|
||||
#VUE_APP_SOCKETURL = 'wss://planetg-java.test.automark.cc/survey_sync'
|
||||
VUE_APP_SOCKETURL = 'wss://ylst-api-uat.dctest.digitalyili.com/survey_sync'
|
||||
VUE_APP_SOCKETURL = 'wss://yls-api-uat.dctest.digitalyili.com/survey_sync'
|
||||
VUE_APP_JSONPURL = 'https://iam-uat.dctest.digitalyili.com/idp/restful/getIDPToken'
|
||||
|
||||
VUE_APP_YQRURL = 'https://ocp-uat-ain.digitalyili.com'
|
||||
|
||||
19
.env.prod
@@ -1,12 +1,15 @@
|
||||
NODE_ENV = 'production'
|
||||
VUE_APP_CURRENTMODE = 'sit'
|
||||
VUE_APP_CURRENTMODE = 'prod'
|
||||
|
||||
VUE_APP_BASEOSS = 'https://test-cxp-pubcos.yili.com/uat-yls'
|
||||
VUE_APP_BASEURL = 'http://planetg-java.test.automark.cc/'
|
||||
VUE_APP_BASEOSS = 'https://cxp-pubcos.yili.com/prod-yls'
|
||||
VUE_APP_BASEURL = 'https://yls.xapi.digitalyili.com/'
|
||||
|
||||
VUE_APP_DELiVERY_BASEURL='https://javaxq.test.automark.cc/'
|
||||
VUE_APP_MESSAGE_CENTER ='http://gtech-gateway.dcin-test.digitalyili.com/apigtech/message-send-center/';
|
||||
VUE_APP_DELiVERY_BASEURL='https://ylsdist-net.x.digitalyili.com/'
|
||||
VUE_APP_MESSAGE_CENTER ='http://gtech-gateway.cxpin.digitalyili.com/apigtech/message-send-center/';
|
||||
|
||||
VUE_APP_LOGIN = 'https://yip.digitalyili.com//login'
|
||||
VUE_APP_SOCKETURL = 'wss://yls.xapi.digitalyili.com/survey_sync'
|
||||
VUE_APP_JSONPURL = 'https://iam.digitalyili.com/idp/restful/getIDPToken'
|
||||
|
||||
VUE_APP_YQRURL = 'https://ocp.digitalyili.com'
|
||||
|
||||
VUE_APP_LOGIN = 'https://yip-uat.dctest.digitalyili.com/login'
|
||||
VUE_APP_SOCKETURL = 'wss://planetg-java.test.automark.cc/survey_sync'
|
||||
VUE_APP_JSONPURL = 'https://iam-uat.dctest.digitalyili.com/idp/restful/getIDPToken'
|
||||
|
||||
18
.env.sit
Normal file
@@ -0,0 +1,18 @@
|
||||
NODE_ENV = 'production'
|
||||
VUE_APP_CURRENTMODE = 'sit'
|
||||
|
||||
VUE_APP_BASEOSS = 'https://test-cxp-pubcos.yili.com/uat-yls'
|
||||
VUE_APP_BASEURL = 'https://yls-api-uat.dctest.digitalyili.com'
|
||||
|
||||
VUE_APP_JAVA_DELiVERY_BASEURL='https://ylsdist-net-uat.dctest.digitalyili.com'
|
||||
|
||||
VUE_APP_MESSAGE_CENTER ='http://gtech-gateway.dcin-test.digitalyili.com/apigtech/message-send-center/';
|
||||
|
||||
VUE_APP_LOGIN = 'https://yip-uat.dctest.digitalyili.com/login'
|
||||
|
||||
VUE_APP_SOCKETURL = 'wss://yls-api-uat.dctest.digitalyili.com/survey_sync'
|
||||
|
||||
VUE_APP_JSONPURL = 'https://iam-uat.dctest.digitalyili.com/idp/restful/getIDPToken'
|
||||
|
||||
VUE_APP_YQRURL = 'https://ocp-uat-ain.digitalyili.com'
|
||||
|
||||
6
.env.uat
@@ -2,7 +2,7 @@ NODE_ENV = 'production'
|
||||
VUE_APP_CURRENTMODE = 'uat'
|
||||
|
||||
VUE_APP_BASEOSS = 'https://test-cxp-pubcos.yili.com/uat-yls'
|
||||
VUE_APP_BASEURL = 'https://ylst-api-uat.dctest.digitalyili.com'
|
||||
VUE_APP_BASEURL = 'https://yls-api-uat.dctest.digitalyili.com'
|
||||
|
||||
VUE_APP_JAVA_DELiVERY_BASEURL='https://ylsdist-net-uat.dctest.digitalyili.com'
|
||||
|
||||
@@ -10,6 +10,8 @@ VUE_APP_MESSAGE_CENTER ='http://gtech-gateway.dcin-test.digitalyili.com/apigtech
|
||||
|
||||
VUE_APP_LOGIN = 'https://yip-uat.dctest.digitalyili.com/login'
|
||||
|
||||
VUE_APP_SOCKETURL = 'wss://ylst-api-uat.dctest.digitalyili.com/survey_sync'
|
||||
VUE_APP_SOCKETURL = 'wss://yls-api-uat.dctest.digitalyili.com/survey_sync'
|
||||
|
||||
VUE_APP_JSONPURL = 'https://iam-uat.dctest.digitalyili.com/idp/restful/getIDPToken'
|
||||
|
||||
VUE_APP_YQRURL = 'https://ocp-uat-ain.digitalyili.com'
|
||||
|
||||
18
package-lock.json
generated
@@ -12031,7 +12031,7 @@
|
||||
},
|
||||
"sortablejs": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
|
||||
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
|
||||
},
|
||||
"source-list-map": {
|
||||
@@ -13710,7 +13710,7 @@
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.8.3",
|
||||
"resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
|
||||
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
@@ -13722,7 +13722,7 @@
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
@@ -13732,7 +13732,7 @@
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
@@ -13743,7 +13743,7 @@
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
@@ -13753,21 +13753,21 @@
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.2.tgz",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
|
||||
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
@@ -13779,7 +13779,7 @@
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
"serve": "vue-cli-service serve --mode dev",
|
||||
"dev": "vue-cli-service serve --mode dev",
|
||||
"uat": "vue-cli-service serve --mode uat",
|
||||
"sit": "vue-cli-service serve --mode sit",
|
||||
"build_sit": "vue-cli-service build --mode sit",
|
||||
"build_uat": "vue-cli-service build --mode uat",
|
||||
"build_prod": "vue-cli-service build --mode prod"
|
||||
},
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
type="text/javascript"
|
||||
src="https://mapapi.qq.com/web/mapComponents/geoLocation/v/geolocation.min.js"
|
||||
></script>
|
||||
<script src="https://pv.sohu.com/cityjson?ie=utf-8"></script>
|
||||
<!-- <script src="https://pv.sohu.com/cityjson?ie=utf-8"></script> -->
|
||||
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
@@ -54,4 +54,12 @@
|
||||
|
||||
}
|
||||
</script> -->
|
||||
|
||||
<!-- 获取ip地址 -->
|
||||
<script type="text/javascript">
|
||||
function ipCallback({ ip }) {
|
||||
localStorage.setItem("plantIp", ip || "");
|
||||
}
|
||||
</script>
|
||||
<script src="https://www.taobao.com/help/getip.php"></script>
|
||||
</html>
|
||||
|
||||
11
src/App.vue
@@ -50,16 +50,17 @@ export default {
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "./style/customize/index.scss";
|
||||
@import "./style/utils.scss";
|
||||
|
||||
@font-face {
|
||||
font-display: optional;
|
||||
font-family: "SourceHanSana-Normal";
|
||||
src: url(#{$baseOss}/fonts/SourceHanSans-Normal.ttf);
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
* {
|
||||
font-family: "SourceHanSana-Normal", sans-serif;
|
||||
|
||||
*{
|
||||
font-family: inherit;
|
||||
}
|
||||
* {
|
||||
margin: 0;
|
||||
@@ -114,7 +115,7 @@ div {
|
||||
}
|
||||
}
|
||||
strong {
|
||||
font-family: "Noto Sans CJK SC Medium", "Source Han Sans CN Medium" !important;
|
||||
// font-family: "Noto Sans CJK SC Medium", "Source Han Sans CN Medium" !important;
|
||||
font-weight: bolder !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,18 +3,24 @@
|
||||
<div class="left">
|
||||
<i class="iconfont icon-xiangzuo-moren"
|
||||
@click="backHome"></i>
|
||||
<a-tooltip placement="right">
|
||||
<template #title>
|
||||
{{ project_name }}
|
||||
</template>
|
||||
<div class="question-name">{{ project_name }}</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div class="tab-container">
|
||||
<div class="tab-item"
|
||||
style="font-size:18px"
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:class="[tab.link === currentPath ? 'active' : '']"
|
||||
@click="toPage(tab.link, tab.title)">
|
||||
<span :class="tab.link === currentPath ? 'click' : 'click2'">{{ index+1 }}</span>
|
||||
<span>{{ tab.title }}</span>
|
||||
<span style="font-size:16px">{{ tab.title }}</span>
|
||||
<span v-if="index!=3"
|
||||
style="width:54px;margin:0 10px;border-top: 1px dashed #C4C0C0;"></span>
|
||||
style="width:27px;margin:0 10px;border-top: 1px dashed #C4C0C0;"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right"
|
||||
@@ -24,41 +30,49 @@
|
||||
class="preview-btn"
|
||||
@click="toPreview">
|
||||
<i class="iconfont icon-yulan"></i>
|
||||
<span style="margin-left: 6px">预览</span>
|
||||
<span style="margin-left: 6px;width: 29px;">预览</span>
|
||||
</div>
|
||||
<a-button v-show="!showPublish && isRenderBtn"
|
||||
type="primary"
|
||||
class="publish-btn"
|
||||
@click="openPublishModal">
|
||||
<template #icon>
|
||||
<i class="iconfont icon-Path"
|
||||
style="font-size: 15px; margin-right: 6px"></i>
|
||||
</template>
|
||||
发布
|
||||
</a-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="display: flex; align-items: center">
|
||||
<a-spin size="small" />
|
||||
<span style="margin-left: 10px">正在保存中...</span>
|
||||
</div>
|
||||
</template>
|
||||
<a-button type="primary"
|
||||
<a-button
|
||||
class="publish-btn share-button"
|
||||
style="display: flex;align-items: center;"
|
||||
@click.stop="clickEntrance">
|
||||
<template #icon>
|
||||
<i class="iconfont icon-fenxiang"
|
||||
style="font-size: 15px; margin-right: 6px"></i>
|
||||
<i class="iconfont icon-fenxiang2 mr-6"></i>
|
||||
<!-- <img class="download_img"
|
||||
:src="require('@/assets/img/fenxiang.png')" /> -->
|
||||
</template>
|
||||
分享
|
||||
</a-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<a-spin size="small" style="padding-left: 40px;"/>
|
||||
<span style="margin-left: 10px;width: 90px;">正在保存中...</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<a-button v-show="!showPublish && isRenderBtn"
|
||||
v-if="!showLoading"
|
||||
type="primary"
|
||||
class="publish-btn"
|
||||
style="display: flex;align-items: center;"
|
||||
@click="openPublishModal">
|
||||
<template #icon>
|
||||
<i class="iconfont icon-fabu3 mr-6"></i>
|
||||
<!-- <img class="download_img"
|
||||
:src="require('@/assets/img/fabu.png')" /> -->
|
||||
</template>
|
||||
发布
|
||||
</a-button>
|
||||
<a-button type="primary"
|
||||
class="download-btn share-button"
|
||||
style="display: flex;align-items: center;"
|
||||
@click.stop="toDownload"
|
||||
v-if="showDownload">
|
||||
v-if="showDownload&&showxiazai">
|
||||
<template #icon>
|
||||
<img class="download_img"
|
||||
:src="require('@/assets/img/download_center.png')" />
|
||||
<!-- <img class="download_img"
|
||||
:src="require('@/assets/img/download_center.png')" /> -->
|
||||
<i class="iconfont icon-xiazaiqi mr-6"></i>
|
||||
</template>
|
||||
下载中心
|
||||
</a-button>
|
||||
@@ -66,22 +80,26 @@
|
||||
</div>
|
||||
<div class="right"
|
||||
v-if="!showPreview && !isRenderBtn && !showShare">
|
||||
<a-button type="primary"
|
||||
<a-button
|
||||
class="publish-btn share-button"
|
||||
style="display: flex;align-items: center;"
|
||||
@click.stop="clickEntrance">
|
||||
<template #icon>
|
||||
<i class="iconfont icon-fenxiang"
|
||||
style="font-size: 15px; margin-right: 6px"></i>
|
||||
<i class="iconfont icon-fenxiang2 mr-6"></i>
|
||||
<!-- <img class="download_img"
|
||||
:src="require('@/assets/img/fenxiang.png')" /> -->
|
||||
</template>
|
||||
分享
|
||||
</a-button>
|
||||
<a-button type="primary"
|
||||
class="download-btn share-button"
|
||||
style="display: flex;align-items: center;"
|
||||
@click.stop="toDownload"
|
||||
v-if="showDownload">
|
||||
<template #icon>
|
||||
<img class="download_img"
|
||||
:src="require('@/assets/img/download_center.png')" />
|
||||
<!-- <img class="download_img"
|
||||
:src="require('@/assets/img/download_center.png')" /> -->
|
||||
<i class="iconfont icon-xiazaiqi mr-6"></i>
|
||||
</template>
|
||||
下载中心
|
||||
</a-button>
|
||||
@@ -111,7 +129,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, createVNode } from "vue";
|
||||
import { ref, computed, onMounted, createVNode,nextTick } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import useEmitter from "@/composables/useEmitter";
|
||||
import { publishSurvey, getSurveyInfo } from "@/api/publish";
|
||||
@@ -137,7 +155,7 @@ const publish_type = 0;
|
||||
const sn = route.query.sn;
|
||||
const tabs = ref([
|
||||
{
|
||||
title: "题目设计",
|
||||
title: "问卷设计",
|
||||
link: "/survey/planet",
|
||||
},
|
||||
{
|
||||
@@ -215,6 +233,11 @@ const showLoading = computed(() => {
|
||||
return false;
|
||||
});
|
||||
const toPage = (path, title) => {
|
||||
console.log(path, title)
|
||||
showxiazai.value=null
|
||||
if(path!='/survey/planet'&&path!="/survey/schedule/recycle"){
|
||||
showxiazai.value=true
|
||||
}
|
||||
router.push({
|
||||
path,
|
||||
query: route.query,
|
||||
@@ -222,12 +245,15 @@ const toPage = (path, title) => {
|
||||
document.title = title;
|
||||
};
|
||||
|
||||
const toPreview = () => {
|
||||
const toPreview = async () => {
|
||||
var res = await canPlanetPublish(route.query.sn);
|
||||
if (res) {
|
||||
router.push({
|
||||
path: "/preview",
|
||||
query: route.query,
|
||||
});
|
||||
document.title = name;
|
||||
}
|
||||
};
|
||||
|
||||
const openPublishModal = async () => {
|
||||
@@ -235,7 +261,8 @@ const openPublishModal = async () => {
|
||||
var res = await canPlanetPublish(route.query.sn);
|
||||
|
||||
if(res){
|
||||
visible.value = true;
|
||||
// visible.value = true;
|
||||
handlePublish()
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -336,7 +363,11 @@ const toDownload = () => {
|
||||
// query: { path: route.path, sn },
|
||||
// });
|
||||
};
|
||||
const showxiazai=ref(true)
|
||||
onMounted(() => {
|
||||
if(route.path=='/survey/planet/design'){
|
||||
showxiazai.value=false
|
||||
}
|
||||
fetchInfo();
|
||||
});
|
||||
</script>
|
||||
@@ -360,6 +391,11 @@ onMounted(() => {
|
||||
font-size: 16px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
color: #434343;
|
||||
width: 150px;
|
||||
overflow:hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
.icon-xiangzuo-moren {
|
||||
cursor: pointer;
|
||||
@@ -378,7 +414,7 @@ onMounted(() => {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-size: 18px;
|
||||
color: #434343;
|
||||
white-space: nowrap;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
@@ -392,17 +428,21 @@ onMounted(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 9px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding-top:5px;
|
||||
padding-bottom:5px;
|
||||
line-height: 10px;
|
||||
border-radius: 60%;
|
||||
background-color: #70b936;
|
||||
color: #fff;
|
||||
}
|
||||
.click2 {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 9px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding-top:5px;
|
||||
padding-bottom:5px;
|
||||
line-height: 10px;
|
||||
border-radius: 60%;
|
||||
background-color: #f5f5f5;
|
||||
color: black;
|
||||
@@ -425,20 +465,21 @@ onMounted(() => {
|
||||
color: #70b936;
|
||||
}
|
||||
.publish-btn {
|
||||
margin-left: 20px;
|
||||
height: 36px;
|
||||
margin-left: 10px;
|
||||
height: 32px;
|
||||
line-height: 18px;
|
||||
border-radius: 6px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.download-btn {
|
||||
margin-left: 32px;
|
||||
// width: 88px;
|
||||
height: 36px;
|
||||
height: 32px;
|
||||
line-height: 18px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.share-button {
|
||||
margin-left: 20px;
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.head-portrait {
|
||||
width: 32px;
|
||||
@@ -567,14 +608,16 @@ onMounted(() => {
|
||||
}
|
||||
.download_img {
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
height: 16px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
.click {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding-top:5px;
|
||||
padding-bottom:5px;
|
||||
line-height: 10px;
|
||||
font-size: 12px;
|
||||
line-height: 9px;
|
||||
border-radius: 60%;
|
||||
background-color: #70b936;
|
||||
color: #fff;
|
||||
@@ -585,12 +628,17 @@ onMounted(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
line-height: 9px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding-top:5px;
|
||||
padding-bottom:5px;
|
||||
line-height: 10px;
|
||||
font-size: 12px;
|
||||
border-radius: 60%;
|
||||
background-color: #f5f5f5;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.mr-6 {
|
||||
margin-right: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
73
src/api/qc.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/* 标记答卷 */
|
||||
export function surveys(params) {
|
||||
return request({
|
||||
url: `/console/surveys/${params.sn}`,
|
||||
method: 'GET',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/* 标记答卷 */
|
||||
export function answer_mark(params) {
|
||||
return request({
|
||||
url: `/console/surveys/${params.sn}/answer_mark`,
|
||||
method: 'POST',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 获取题状态
|
||||
*/
|
||||
export function getParticularList(sn, params) {
|
||||
console.log(params)
|
||||
return request({
|
||||
url: `/console/surveys/${sn}/answers?${params}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/* 处理无效答卷 */
|
||||
export function nullDeal(params) {
|
||||
return request({
|
||||
url: `/console/surveys/${params.sn}/nullDeal`,
|
||||
method: 'POST',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/* 批量更新标记数据 */
|
||||
export function answer_mark_batch(params) {
|
||||
return request({
|
||||
url: `/console/surveys/${params.sn}/answer_mark_batch`,
|
||||
method: 'POST',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/* 答卷标记取消 */
|
||||
export function answer_mark_del(params) {
|
||||
return request({
|
||||
url: `/console/surveys/${params.sn}/answer_mark`,
|
||||
method: 'DELETE',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
/* 答卷标记取消 */
|
||||
export function getNullDealConfig(params) {
|
||||
return request({
|
||||
url: `/console/surveys/${params.sn}/getNullDealConfig`,
|
||||
method: 'GET',
|
||||
params
|
||||
})
|
||||
}
|
||||
/* 答卷标记取消 */
|
||||
export function heads(params) {
|
||||
return request({
|
||||
url: `/console/surveys/${params.sn}/answers/heads`,
|
||||
method: 'GET',
|
||||
params
|
||||
})
|
||||
}
|
||||
BIN
src/assets/img/business_wechat.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/img/design/flavor_example.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
src/assets/img/design/flavor_example1.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/assets/img/design/flavor_example2.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
src/assets/img/design/flavor_example3.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
src/assets/img/design/pack_example.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
src/assets/img/design/pack_example1.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
src/assets/img/design/pack_example2.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
src/assets/img/design/pack_example3.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
src/assets/img/design/pack_example4.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
src/assets/img/design/sell_example.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
src/assets/img/design/sell_example1.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
src/assets/img/design/sell_example2.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 623 B |
BIN
src/assets/img/fabu.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/img/fabushuliang.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/assets/img/fenxiang.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/assets/img/guanlianxuanxiang.png
Normal file
|
After Width: | Height: | Size: 488 B |
BIN
src/assets/img/huishouzongliang.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
src/assets/img/jinrihuishou.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
src/assets/img/publish/random-no-data.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
src/assets/img/publish/step-no-data.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
@@ -19,7 +19,7 @@
|
||||
<i class="iconfont" v-html="item.icon"></i>
|
||||
</div>
|
||||
<div class="menu-bar-item-main-text">
|
||||
<div>{{ item[property] }}</div>
|
||||
<div style="font-size: 14px;">{{ item[property] }}</div>
|
||||
<i
|
||||
v-if="item.children.length > 0"
|
||||
class="iconfont"
|
||||
@@ -224,12 +224,12 @@ function menusStatusToFalsefather(menus) {
|
||||
&-item {
|
||||
position: relative;
|
||||
width: 220px;
|
||||
z-index: 99;
|
||||
// z-index: 999;
|
||||
background: rgba(245, 245, 245, 0.6);
|
||||
&-child {
|
||||
background-color: #ffffff;
|
||||
.menu-bar-item-main-text{
|
||||
width: 68px;
|
||||
width: 94px;
|
||||
}
|
||||
}
|
||||
&-img {
|
||||
@@ -246,10 +246,12 @@ function menusStatusToFalsefather(menus) {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// justify-content: center;
|
||||
border-radius: 8px 8px 0px 0px;
|
||||
padding-right: 5px;
|
||||
padding-left: 52px;
|
||||
transition: all 0.3s;
|
||||
color: #434343;
|
||||
&-active {
|
||||
color: $yili-default-color;
|
||||
background: #ffffff;
|
||||
@@ -262,7 +264,7 @@ function menusStatusToFalsefather(menus) {
|
||||
&-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
margin-top: 4px;
|
||||
opacity: 0.8;
|
||||
div {
|
||||
font-size: 12px;
|
||||
@@ -280,23 +282,29 @@ function menusStatusToFalsefather(menus) {
|
||||
}
|
||||
&:hover &-icon {
|
||||
opacity: 1;
|
||||
color: #70b936;
|
||||
}
|
||||
&:hover &-text {
|
||||
opacity: 1;
|
||||
color: #70b936;
|
||||
}
|
||||
&:hover {
|
||||
background-color: #efeeee;
|
||||
// background-color: #efeeee;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-no-child {
|
||||
}
|
||||
&-has-child {
|
||||
margin-top: 3px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s;
|
||||
height: 0;
|
||||
border-radius: 5px 5px 5px 5px;
|
||||
box-shadow: 0px 2px 8px 0px rgb(0 0 0 / 10%);
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
color: #434343;
|
||||
}
|
||||
.menu-bar-item:last-child {
|
||||
border-radius: 0px 8px 0px 0px;
|
||||
@@ -306,7 +314,7 @@ function menusStatusToFalsefather(menus) {
|
||||
}
|
||||
}
|
||||
.menu-bar-item-main-text {
|
||||
font-size: 0.75rem;
|
||||
font-size: 14px;
|
||||
z-index: 99;
|
||||
}
|
||||
.menu-bar-item-main-icon {
|
||||
@@ -336,7 +344,7 @@ function menusStatusToFalsefather(menus) {
|
||||
z-index: 100;
|
||||
height: 50px;
|
||||
&:hover {
|
||||
background-color: #efeeee !important;
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
<div
|
||||
class="logical-title-line"
|
||||
:style="{ left: `${activeIndex * posLeft}px`, width: `${lineWidth}px` }"
|
||||
:style="{ left: `${(activeIndex) * posLeft + 20}px`, width: `${lineWidth}px` }"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- mob端 -->
|
||||
<div
|
||||
v-show="showPrevious && page > min && page < pages"
|
||||
class="btn previous my-btn"
|
||||
class="pfe-button btn previous my-btn"
|
||||
@click="previous"
|
||||
:style="`color: ${buttonTextColor};background-color: ${buttonColor}`"
|
||||
>
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<a-spin v-show="page < pages" :spinning="loading" wrapperClassName="spin">
|
||||
<div
|
||||
class="btn next my-btn"
|
||||
class="pfe-button btn next my-btn"
|
||||
@click="next"
|
||||
:style="`color: ${buttonTextColor};background-color: ${buttonColor}`"
|
||||
>
|
||||
|
||||
263
src/components/Slider.vue
Normal file
@@ -0,0 +1,263 @@
|
||||
<template>
|
||||
<div
|
||||
class="slider"
|
||||
:class="{ 'slider-disabled': disabled }"
|
||||
:style="{
|
||||
width: sliderWidth === 0 ? '90%' : `${sliderWidth}px`,
|
||||
marginLeft: `${sliderMrgLeft}px`,
|
||||
}"
|
||||
>
|
||||
<div class="slider-rail"></div>
|
||||
<div class="slider-track" ref="track"></div>
|
||||
<div
|
||||
class="slider-step"
|
||||
@click="stepClickHandle"
|
||||
@mousemove="stepMoveHandle"
|
||||
@mouseup="stepUpHandle"
|
||||
@mousedown="stepDownHandle"
|
||||
@touchmove.prevent="touchmoveHandle"
|
||||
@touchend="touchendHandle"
|
||||
>
|
||||
<div
|
||||
v-if="copyMark.length === 0"
|
||||
class="slider-dot slider-dot-handler"
|
||||
style="left: 0"
|
||||
></div>
|
||||
<div
|
||||
v-for="(item, index) in copyMark"
|
||||
:key="index"
|
||||
class="slider-dot"
|
||||
:class="{ 'slider-dot-handler': (activeMark?.left || 0) === item.left }"
|
||||
:style="{
|
||||
left: `${item.left}%`,
|
||||
}"
|
||||
></div>
|
||||
<div
|
||||
v-for="(item, index) in copyMark"
|
||||
:key="index"
|
||||
class="slider-step-value"
|
||||
:style="{
|
||||
left: `${item.left}%`,
|
||||
}"
|
||||
>
|
||||
{{ item.value }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from "@vue/reactivity";
|
||||
import { nextTick, watch } from "@vue/runtime-core";
|
||||
export default {
|
||||
name: "Slider",
|
||||
props: {
|
||||
marks: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
stepWidth: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ["update:value", "afterChange"],
|
||||
setup(props, context) {
|
||||
const track = ref(null);
|
||||
const sliderWidth = ref("");
|
||||
const sliderMrgLeft = ref(6);
|
||||
const activeMark = ref({});
|
||||
const copyMark = ref([]);
|
||||
watch(
|
||||
() => props.marks,
|
||||
(val) => {
|
||||
const step = 100 / (val.length - 1);
|
||||
copyMark.value = val.map((m, index) => {
|
||||
const temp = {
|
||||
value: m,
|
||||
left: Number((index * step).toFixed(2)),
|
||||
};
|
||||
if (index === 0) {
|
||||
temp.left = 0;
|
||||
}
|
||||
if (index === val.length - 1) {
|
||||
temp.left = 100;
|
||||
}
|
||||
return temp;
|
||||
});
|
||||
sliderWidth.value = props.stepWidth * val.length;
|
||||
nextTick(() => {
|
||||
sliderMrgLeft.value = (
|
||||
(document.querySelector(".slider-step-value")?.clientWidth || 12) /
|
||||
2
|
||||
).toFixed(0);
|
||||
});
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
watch(
|
||||
() => props.value,
|
||||
(val) => {
|
||||
const activeMarks = copyMark.value.find((m) => m.value === val);
|
||||
activeMark.value = activeMarks;
|
||||
nextTick(() => {
|
||||
track.value.style.width = (activeMark.value?.left || 0) + "%";
|
||||
});
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
const markHandle = (offsetX = 0) => {
|
||||
if (props.disabled || copyMark.value.length === 0) return;
|
||||
const position = Number(((offsetX / sliderWidth.value) * 100).toFixed(0));
|
||||
const closeIndex = copyMark.value
|
||||
.map((item) => Math.abs(position - item.left))
|
||||
.findIndex(
|
||||
(item) =>
|
||||
item ===
|
||||
Math.min(
|
||||
...copyMark.value.map((item) => Math.abs(position - item.left))
|
||||
)
|
||||
);
|
||||
|
||||
activeMark.value = copyMark.value[closeIndex];
|
||||
track.value.style.width = copyMark.value[closeIndex].left + "%";
|
||||
context.emit("update:value", copyMark.value[closeIndex].value);
|
||||
};
|
||||
const stepClickHandle = (event) => {
|
||||
console.log("click", event);
|
||||
let offsetX = event.target.offsetLeft;
|
||||
if (offsetX === 0) {
|
||||
offsetX = event.offsetX;
|
||||
}
|
||||
markHandle(offsetX);
|
||||
};
|
||||
const mouseDown = ref(false);
|
||||
const stepMoveHandle = (event) => {
|
||||
if (mouseDown.value) {
|
||||
stepClickHandle(event);
|
||||
}
|
||||
};
|
||||
const stepDownHandle = () => {
|
||||
mouseDown.value = true;
|
||||
};
|
||||
const stepUpHandle = () => {
|
||||
mouseDown.value = false;
|
||||
setTimeout(() => {
|
||||
context.emit("afterChange", activeMark.value?.value || undefined);
|
||||
}, 100);
|
||||
};
|
||||
const touchmoveHandle = (event) => {
|
||||
const offsetX =
|
||||
event.changedTouches[0].pageX -
|
||||
event.target.parentNode.getBoundingClientRect().left;
|
||||
markHandle(offsetX);
|
||||
};
|
||||
const touchendHandle = () => {
|
||||
context.emit("afterChange", activeMark.value?.value || undefined);
|
||||
};
|
||||
return {
|
||||
copyMark,
|
||||
track,
|
||||
activeMark,
|
||||
sliderWidth,
|
||||
sliderMrgLeft,
|
||||
stepClickHandle,
|
||||
stepMoveHandle,
|
||||
touchmoveHandle,
|
||||
touchendHandle,
|
||||
stepUpHandle,
|
||||
stepDownHandle,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.slider {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 14px;
|
||||
line-height: 1.5715;
|
||||
position: relative;
|
||||
height: 33px;
|
||||
margin: 14px 6px 10px;
|
||||
padding: 4px 0;
|
||||
cursor: pointer;
|
||||
&-rail {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 2px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
&-track {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
height: 4px;
|
||||
width: 0;
|
||||
background-color: #a5d39f;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&-step {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
&-value {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
transform: translateX(-50%);
|
||||
display: inline-block;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
text-align: center;
|
||||
word-break: keep-all;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
&-dot {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-left: -4px;
|
||||
background-color: #fff;
|
||||
border: 2px solid #f0f0f0;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
&-handler {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-color: #70B936;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 5px rgba(55, 204, 32, 0.2);
|
||||
margin-top: -3px;
|
||||
transform: translateX(-20%);
|
||||
}
|
||||
}
|
||||
&-disabled {
|
||||
cursor: not-allowed;
|
||||
.slider-dot {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.slider-step-value {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.slider-rail {
|
||||
background-color: #e1e1e1;
|
||||
}
|
||||
.slider-track {
|
||||
background-color: #17ae29;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -24,7 +24,7 @@
|
||||
>
|
||||
<a-form :label-col="{ span: 6 }">
|
||||
<a-form-item label="地址">
|
||||
<a-input v-model:value="linkAddress" placeholder="请输入地址" />
|
||||
<a-input v-model:value="linkAddress" placeholder="请输入地址" :disabled="fixation" />
|
||||
</a-form-item>
|
||||
<a-form-item label="显示文字">
|
||||
<a-input v-model:value="linkText" placeholder="请输入显示的文字" />
|
||||
@@ -266,6 +266,7 @@ import { useStore } from "vuex";
|
||||
import { useRoute } from "vue-router";
|
||||
import { nodeHandle } from "../views/planetDesign/Design/js/util.js";
|
||||
import { baseOss } from "../config.js";
|
||||
import * as cheerio from 'cheerio';
|
||||
export default {
|
||||
name: "Tinymce",
|
||||
components: { Editor },
|
||||
@@ -322,13 +323,29 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isLinkContent: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 固定插入地址
|
||||
isFixation: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 最大数量
|
||||
maxNum: {
|
||||
type: Number,
|
||||
default: NaN
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
const store = useStore();
|
||||
const route = useRoute();
|
||||
const sn = computed(() => route.query.sn || "");
|
||||
const fixation = ref(props.isFixation)
|
||||
const { linkAddress, linkText, linkDialogVisible, linkDiglogOkHandle } =
|
||||
linkDialog();
|
||||
linkDialog(fixation);
|
||||
|
||||
const {
|
||||
d3Address,
|
||||
d3Width,
|
||||
@@ -371,14 +388,28 @@ export default {
|
||||
quesList,
|
||||
quoteList,
|
||||
quoteDialogVisible,
|
||||
isLinkContent: props.isLinkContent,
|
||||
};
|
||||
const { content, init, editorId, fileInput } = initTinymce(dataJson);
|
||||
const { fileChange } = imageHandle(editorId, props.isImageStyle, sn);
|
||||
const legendFormat = (str)=>{
|
||||
if(str){
|
||||
const $ = cheerio.load(str)
|
||||
const text = $.text().trim()
|
||||
return text
|
||||
}
|
||||
return str
|
||||
}
|
||||
onMounted(() => {
|
||||
tinymce.init(init);
|
||||
});
|
||||
watch(content, (val, oldVal) => {
|
||||
let num = legendFormat(content.value).length
|
||||
context.emit("update:editorData", content.value);
|
||||
if(num>=props.maxNum) {
|
||||
message.warning(`消息内容最大输入字数为${props.maxNum}`)
|
||||
return
|
||||
}
|
||||
});
|
||||
watch(
|
||||
() => props.editorData,
|
||||
@@ -413,6 +444,8 @@ export default {
|
||||
addQuoListHandle,
|
||||
fileChange,
|
||||
delQuoListHandle,
|
||||
store,
|
||||
fixation
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -447,6 +480,7 @@ function initTinymce(data) {
|
||||
quoteDialogVisible,
|
||||
isImageStyle,
|
||||
sn,
|
||||
isLinkContent,
|
||||
} = data;
|
||||
const content = ref("");
|
||||
const fileInput = ref(null);
|
||||
@@ -464,7 +498,7 @@ function initTinymce(data) {
|
||||
plugins: ["autoresize", "paste"],
|
||||
toolbar_mode: "wrap",
|
||||
toolbar_persist: true,
|
||||
toolbar:
|
||||
toolbar: isLinkContent ? false :
|
||||
"bold italic underline fontsizeselect quoteButton imgButton linkButton moreButton",
|
||||
fontsize_formats: "12px 14px 16px 18px 20px 22px 24px 26px 28px",
|
||||
images_upload_handler: (blobInfo, success, failure, progress) => {},
|
||||
@@ -528,6 +562,23 @@ function initTinymce(data) {
|
||||
context.emit("more", content.value);
|
||||
},
|
||||
});
|
||||
editor.ui.registry.addIcon("linkIcon", link);
|
||||
editor.ui.registry.addButton("linkButton", {
|
||||
icon: "linkIcon",
|
||||
onAction: function (e) {
|
||||
const wrapperNode = tinymce.editors[editor.id].selection.getNode();
|
||||
const content = tinymce.editors[editor.id].selection.getContent();
|
||||
const contentNode = document.createElement("div");
|
||||
contentNode.innerHTML = content;
|
||||
linkText.value = contentNode.innerText;
|
||||
if (wrapperNode.tagName.toLowerCase() === "a") {
|
||||
tinymce.editors[editor.id].selection.select(wrapperNode, true);
|
||||
linkText.value = wrapperNode.innerText;
|
||||
linkAddress.value = wrapperNode.href || "";
|
||||
}
|
||||
linkDialogVisible.value = true;
|
||||
},
|
||||
});
|
||||
commonFunc(editor);
|
||||
editor.on("init", (e) => {
|
||||
// 等页面渲染完毕,给工具栏绑定拖拽事件并且全选内容
|
||||
@@ -564,6 +615,7 @@ function initTinymce(data) {
|
||||
toolbar_mode: "sliding",
|
||||
object_resizing: true,
|
||||
fontsize_formats: "10px 12px 14px 16px 18px 20px 22px 24px 26px 28px",
|
||||
font_formats: "默认='sans-serif';微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';楷体='楷体';隶书='隶书';幼圆='幼圆';",
|
||||
content_style: `p { padding:0;margin:0 } body { font-size: ${defaultFontSize}px } img {max-width:100%;}`,
|
||||
paste_auto_cleanup_on_paste: true,
|
||||
paste_remove_styles: true,
|
||||
@@ -670,7 +722,7 @@ function initTinymce(data) {
|
||||
/**
|
||||
* 插入链接弹框crud
|
||||
*/
|
||||
function linkDialog() {
|
||||
function linkDialog(fixation) {
|
||||
const linkAddress = ref("");
|
||||
const linkText = ref(""); // 用于显示
|
||||
const linkDialogVisible = ref(false);
|
||||
@@ -682,11 +734,20 @@ function linkDialog() {
|
||||
if (!linkAddress.value.startsWith("http")) {
|
||||
linkAddress.value = `https://${linkAddress.value}`;
|
||||
}
|
||||
// 插入链接前后加空格
|
||||
if(fixation.value) {
|
||||
tinymce.editors[id].execCommand(
|
||||
"mceInsertContent",
|
||||
false,
|
||||
` <a href="${linkAddress.value}">${linkText.value}</a> `
|
||||
);
|
||||
}else{
|
||||
tinymce.editors[id].execCommand(
|
||||
"mceInsertContent",
|
||||
false,
|
||||
`<a href="${linkAddress.value}">${linkText.value}</a>`
|
||||
);
|
||||
}
|
||||
linkDialogVisible.value = false;
|
||||
linkAddress.value = "";
|
||||
linkText.value = "";
|
||||
@@ -1039,4 +1100,10 @@ function util(store) {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
:deep(.tox-toolbar__group){
|
||||
flex-wrap: nowrap!important;
|
||||
}
|
||||
:deep(.tox-collection__item-label){
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SignaturePad from 'signature_pad';
|
||||
import { onMounted, ref } from '@vue/runtime-core';
|
||||
import common from '@/api/common.js';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { date } from 'is-type-of';
|
||||
import SignaturePad from 'signature_pad'
|
||||
import { onMounted, ref } from '@vue/runtime-core'
|
||||
import common from '@/api/common.js'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { date } from 'is-type-of'
|
||||
export default {
|
||||
props: {
|
||||
url: {
|
||||
@@ -41,38 +41,40 @@ export default {
|
||||
// // 取消绑定所有事件处理程序
|
||||
// signaturePad.off();
|
||||
// // 重新绑定所有事件处理程序
|
||||
const canvas = ref();
|
||||
const signaturePad = ref();
|
||||
const isErase = ref(false);
|
||||
const imgList = ref([]);
|
||||
const isSave = ref(false);
|
||||
const options = ref();
|
||||
const route = useRoute();
|
||||
const canvas = ref()
|
||||
const signaturePad = ref()
|
||||
const isErase = ref(false)
|
||||
const imgList = ref([])
|
||||
const isSave = ref(false)
|
||||
const options = ref()
|
||||
const route = useRoute()
|
||||
//用于画完图后的显示,在抬起时,添加来自于allPoints的所有点的数据
|
||||
// const List<List> allList = new ArrayList<>();
|
||||
onMounted(() => {
|
||||
if (props.url) {
|
||||
let image = new Image();
|
||||
let image = new Image()
|
||||
//解决跨域问题
|
||||
image.crossOrigin = '*';
|
||||
image.src = props.url + '?v=' + Math.random();
|
||||
|
||||
image.crossOrigin = '*'
|
||||
image.src = props.url + '?v=' + Math.random()
|
||||
image.onload = () => {
|
||||
var canvas = document.createElement('canvas');
|
||||
// window.open(image)
|
||||
var canvas = document.createElement('canvas')
|
||||
var context = canvas.getContext('2d')
|
||||
canvas.width = 302
|
||||
canvas.height = 152
|
||||
context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height)
|
||||
|
||||
canvas.width = 316;
|
||||
canvas.height = 191;
|
||||
var context = canvas.getContext('2d');
|
||||
context.drawImage(image, 0, 0, 316, 191, 0, 0, 316, 191);
|
||||
|
||||
var quality = 1;
|
||||
var quality = 1
|
||||
//这里的dataurl就是base64类型
|
||||
var dataURL = canvas.toDataURL('image/jpg', quality); //使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
|
||||
signaturePad.value.fromDataURL(dataURL);
|
||||
var dataURL = canvas.toDataURL('image/jpg', quality) //使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png,因为压缩成png后base64的字符串可能比不转换前的长!
|
||||
signaturePad.value.fromDataURL(dataURL, {
|
||||
width: 302,
|
||||
height: 152
|
||||
})
|
||||
if (props.disabled) {
|
||||
signaturePad.value.off();
|
||||
signaturePad.value.off()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// dotSize default = (minWidth + maxWidth/2)
|
||||
@@ -105,79 +107,77 @@ export default {
|
||||
minWidth: 2,
|
||||
maxWidth: 2,
|
||||
backgroundColor: '#fafafa'
|
||||
});
|
||||
signaturePad.value.width = 318;
|
||||
signaturePad.value.height = 192;
|
||||
})
|
||||
signaturePad.value.width = 318
|
||||
signaturePad.value.height = 192
|
||||
signaturePad.value.addEventListener('beginStroke', (e) => {
|
||||
content.emit('begin', e);
|
||||
});
|
||||
content.emit('begin', e)
|
||||
})
|
||||
signaturePad.value.addEventListener('endStroke', (e) => {
|
||||
content.emit('end', e);
|
||||
console.log('end', e, signaturePad.value.toData());
|
||||
});
|
||||
content.emit('end', e)
|
||||
console.log('end', e, signaturePad.value.toData())
|
||||
})
|
||||
if (props.disabled) {
|
||||
signaturePad.value.off();
|
||||
signaturePad.value.off()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const base64ToFile = (dataUrl, name) => {
|
||||
var arr = dataUrl.split(','),
|
||||
mime = arr[0].match(/:(.*?);/)[1],
|
||||
bstr = atob(arr[1]),
|
||||
n = bstr.length,
|
||||
u8arr = new Uint8Array(n);
|
||||
u8arr = new Uint8Array(n)
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
u8arr[n] = bstr.charCodeAt(n)
|
||||
}
|
||||
return new File([u8arr], name + '.jpg', { type: 'image/jpg' })
|
||||
}
|
||||
return new File([u8arr], name + '.jpg', { type: 'image/jpg' });
|
||||
};
|
||||
|
||||
//保存
|
||||
const save = async () => {
|
||||
if (signaturePad.value.isEmpty()) {
|
||||
message.error('签名不能为空');
|
||||
return;
|
||||
message.error('签名不能为空')
|
||||
return
|
||||
}
|
||||
let base64 = signaturePad.value.toDataURL()
|
||||
let file = base64ToFile(base64, new Date().getTime())
|
||||
const data = await common.cosUpload(file, file.name, '', () => {})
|
||||
console.log(route.query.sn, file, data)
|
||||
return data.url
|
||||
}
|
||||
let base64 = signaturePad.value.toDataURL();
|
||||
let file = base64ToFile(base64, new Date().getTime());
|
||||
const data = await common.cosUpload(file, file.name, '', () => {});
|
||||
console.log(route.query.sn, file, data);
|
||||
return data.url;
|
||||
};
|
||||
//清除
|
||||
const clear = () => {
|
||||
signaturePad.value.clear();
|
||||
signaturePad.value.clear()
|
||||
// setTimeout(() => {
|
||||
// isErase.value = isErase2;
|
||||
// erase();
|
||||
// });
|
||||
setTimeout(() => {
|
||||
var ctx = canvas.value.getContext('2d');
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
var ctx = canvas.value.getContext('2d')
|
||||
ctx.globalCompositeOperation = 'source-over'
|
||||
if (isErase.value) {
|
||||
signaturePad.value.minWidth = 18;
|
||||
signaturePad.value.maxWidth = 212;
|
||||
signaturePad.value.penColor = '#fafafa';
|
||||
signaturePad.value.velocityFilterWeight =
|
||||
signaturePad.value.velocityFilterWeight + 0.1;
|
||||
signaturePad.value.minWidth = 18
|
||||
signaturePad.value.maxWidth = 212
|
||||
signaturePad.value.penColor = '#fafafa'
|
||||
signaturePad.value.velocityFilterWeight = signaturePad.value.velocityFilterWeight + 0.1
|
||||
} else {
|
||||
signaturePad.value.minWidth = 2;
|
||||
signaturePad.value.maxWidth = 2;
|
||||
signaturePad.value.penColor = '#000000';
|
||||
signaturePad.value.velocityFilterWeight =
|
||||
signaturePad.value.velocityFilterWeight + 0.1;
|
||||
signaturePad.value.minWidth = 2
|
||||
signaturePad.value.maxWidth = 2
|
||||
signaturePad.value.penColor = '#000000'
|
||||
signaturePad.value.velocityFilterWeight = signaturePad.value.velocityFilterWeight + 0.1
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
//撤回
|
||||
const revoke = () => {
|
||||
signaturePad.value.minWidth = 18;
|
||||
signaturePad.value.maxWidth = 18;
|
||||
const data = signaturePad.value.toData();
|
||||
const newData = data.slice(0, data.length - 1);
|
||||
signaturePad.value.minWidth = 18
|
||||
signaturePad.value.maxWidth = 18
|
||||
const data = signaturePad.value.toData()
|
||||
const newData = data.slice(0, data.length - 1)
|
||||
signaturePad.value.fromData(newData, {
|
||||
clear: true
|
||||
});
|
||||
})
|
||||
// newData.forEach(async (s) => {
|
||||
// await setTimeout(() => {
|
||||
// signaturePad.value.fromData([s], {
|
||||
@@ -185,7 +185,7 @@ export default {
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
console.log(newData);
|
||||
console.log(newData)
|
||||
// console.log(newData);
|
||||
// data = newData;
|
||||
// signaturePad.value.fromData(newData, {
|
||||
@@ -193,61 +193,67 @@ export default {
|
||||
// });
|
||||
|
||||
setTimeout(() => {
|
||||
var ctx = canvas.value.getContext('2d');
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
var ctx = canvas.value.getContext('2d')
|
||||
ctx.globalCompositeOperation = 'source-over'
|
||||
if (isErase.value) {
|
||||
signaturePad.value.minWidth = 18;
|
||||
signaturePad.value.maxWidth = 18;
|
||||
signaturePad.value.penColor = '#fafafa';
|
||||
signaturePad.value.minWidth = 18
|
||||
signaturePad.value.maxWidth = 18
|
||||
signaturePad.value.penColor = '#fafafa'
|
||||
// ctx.globalCompositeOperation = 'destination-out';
|
||||
} else {
|
||||
signaturePad.value.minWidth = 2;
|
||||
signaturePad.value.maxWidth = 2;
|
||||
signaturePad.value.penColor = '#000000';
|
||||
signaturePad.value.minWidth = 2
|
||||
signaturePad.value.maxWidth = 2
|
||||
signaturePad.value.penColor = '#000000'
|
||||
// ctx.globalCompositeOperation = 'source-over';
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
}, 100)
|
||||
}
|
||||
//擦除
|
||||
const erase = () => {
|
||||
console.log(isErase.value);
|
||||
var ctx = canvas.value.getContext('2d');
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
console.log(isErase.value)
|
||||
var ctx = canvas.value.getContext('2d')
|
||||
ctx.globalCompositeOperation = 'source-over'
|
||||
if (!isErase.value) {
|
||||
signaturePad.value.minWidth = 18;
|
||||
signaturePad.value.maxWidth = 18;
|
||||
signaturePad.value.penColor = '#fafafa';
|
||||
signaturePad.value.minWidth = 18
|
||||
signaturePad.value.maxWidth = 18
|
||||
signaturePad.value.penColor = '#fafafa'
|
||||
//ctx.globalCompositeOperation = 'destination-out';
|
||||
isErase.value = true;
|
||||
isErase.value = true
|
||||
} else {
|
||||
signaturePad.value.minWidth = 2;
|
||||
signaturePad.value.maxWidth = 2;
|
||||
signaturePad.value.penColor = '#000000';
|
||||
signaturePad.value.minWidth = 2
|
||||
signaturePad.value.maxWidth = 2
|
||||
signaturePad.value.penColor = '#000000'
|
||||
|
||||
isErase.value = false;
|
||||
isErase.value = false
|
||||
}
|
||||
return isErase
|
||||
}
|
||||
return isErase;
|
||||
};
|
||||
|
||||
const onMousedown = (e) => {
|
||||
console.log(e);
|
||||
console.log(e)
|
||||
if (!isSave.value) {
|
||||
isSave.value = true;
|
||||
isSave.value = true
|
||||
}
|
||||
}
|
||||
};
|
||||
const onMouseleave = (e) => {
|
||||
if (!isSave.value) {
|
||||
isSave.value = false;
|
||||
imgList.value.push(save());
|
||||
isSave.value = false
|
||||
imgList.value.push(save())
|
||||
}
|
||||
}
|
||||
};
|
||||
const onMouserup = (e) => {
|
||||
if (!isSave.value) {
|
||||
isSave.value = false;
|
||||
imgList.value.push(save());
|
||||
isSave.value = false
|
||||
imgList.value.push(save())
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
// function resizeCanvas() {
|
||||
// const ratio = Math.max(window.devicePixelRatio || 1, 1)
|
||||
// canvas.value.width = canvas.value.offsetWidth * ratio
|
||||
// canvas.value.height = canvas.value.offsetHeight * ratio
|
||||
// canvas.value.getContext('2d').scale(ratio, ratio)
|
||||
// signaturePad.clear() // otherwise isEmpty() might return incorrect value
|
||||
// }
|
||||
return {
|
||||
canvas,
|
||||
signaturePad,
|
||||
@@ -259,9 +265,9 @@ export default {
|
||||
onMouseleave,
|
||||
onMouserup,
|
||||
options
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -6,4 +6,5 @@ module.exports = {
|
||||
loginUrl: process.env.VUE_APP_LOGIN,
|
||||
socketUrl: process.env.VUE_APP_SOCKETURL,
|
||||
jsonpUrl: process.env.VUE_APP_JSONPURL,
|
||||
jqrUrl: process.env.VUE_APP_YQRURL,
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 3121635 */
|
||||
src: url('iconfont.woff2?t=1666232085564') format('woff2'),
|
||||
url('iconfont.woff?t=1666232085564') format('woff'),
|
||||
url('iconfont.ttf?t=1666232085564') format('truetype');
|
||||
src: url('iconfont.woff2?t=1669789588035') format('woff2'),
|
||||
url('iconfont.woff?t=1669789588035') format('woff'),
|
||||
url('iconfont.ttf?t=1669789588035') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -13,6 +13,226 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-a-wenjian1:before {
|
||||
content: "\e60e";
|
||||
}
|
||||
|
||||
.icon-xiangmu:before {
|
||||
content: "\e809";
|
||||
}
|
||||
|
||||
.icon-PSM2:before {
|
||||
content: "\e807";
|
||||
}
|
||||
|
||||
.icon-KANO2:before {
|
||||
content: "\e808";
|
||||
}
|
||||
|
||||
.icon-tihuantupian:before {
|
||||
content: "\e805";
|
||||
}
|
||||
|
||||
.icon-fangdatupian:before {
|
||||
content: "\e806";
|
||||
}
|
||||
|
||||
.icon-lianxiren1:before {
|
||||
content: "\e804";
|
||||
}
|
||||
|
||||
.icon-dakai1:before {
|
||||
content: "\e803";
|
||||
}
|
||||
|
||||
.icon-a-bianzu34:before {
|
||||
content: "\e802";
|
||||
}
|
||||
|
||||
.icon-xuanxiangxianshi1:before {
|
||||
content: "\e801";
|
||||
}
|
||||
|
||||
.icon-a-CombinedShape21:before {
|
||||
content: "\e800";
|
||||
}
|
||||
|
||||
.icon-xiazaiqi:before {
|
||||
content: "\e7fe";
|
||||
}
|
||||
|
||||
.icon-piliang1:before {
|
||||
content: "\e7ff";
|
||||
}
|
||||
|
||||
.icon-fenxiang2:before {
|
||||
content: "\e7fc";
|
||||
}
|
||||
|
||||
.icon-fabu3:before {
|
||||
content: "\e7fd";
|
||||
}
|
||||
|
||||
.icon-a-3Dchangjingfenxi:before {
|
||||
content: "\e7fb";
|
||||
}
|
||||
|
||||
.icon-shoucang2:before {
|
||||
content: "\e7f9";
|
||||
}
|
||||
|
||||
.icon-shoucangkong:before {
|
||||
content: "\e7fa";
|
||||
}
|
||||
|
||||
.icon-shoucang:before {
|
||||
content: "\e7f5";
|
||||
}
|
||||
|
||||
.icon-yulan2:before {
|
||||
content: "\e7f6";
|
||||
}
|
||||
|
||||
.icon-a-bianzu33:before {
|
||||
content: "\e7f7";
|
||||
}
|
||||
|
||||
.icon-lianxiwomen:before {
|
||||
content: "\e7f8";
|
||||
}
|
||||
|
||||
.icon-a-bianzu22:before {
|
||||
content: "\e7f3";
|
||||
}
|
||||
|
||||
.icon-bianzu6:before {
|
||||
content: "\e7f4";
|
||||
}
|
||||
|
||||
.icon-a-zu699:before {
|
||||
content: "\e7f2";
|
||||
}
|
||||
|
||||
.icon-sucaiku:before {
|
||||
content: "\e7f0";
|
||||
}
|
||||
|
||||
.icon-wodezuopin:before {
|
||||
content: "\e7f1";
|
||||
}
|
||||
|
||||
.icon-rongqi6:before {
|
||||
content: "\e7ed";
|
||||
}
|
||||
|
||||
.icon-a-rongqi1:before {
|
||||
content: "\e60c";
|
||||
}
|
||||
|
||||
.icon-rongqi5:before {
|
||||
content: "\e60d";
|
||||
}
|
||||
|
||||
.icon-a-rongqi2:before {
|
||||
content: "\e60b";
|
||||
}
|
||||
|
||||
.icon-Worddaoru:before {
|
||||
content: "\e7ef";
|
||||
}
|
||||
|
||||
.icon-rongqi4:before {
|
||||
content: "\e7ec";
|
||||
}
|
||||
|
||||
.icon-a-zu671:before {
|
||||
content: "\e7ee";
|
||||
}
|
||||
|
||||
.icon-chakanrenqunbao:before {
|
||||
content: "\e7ea";
|
||||
}
|
||||
|
||||
.icon-lianjie:before {
|
||||
content: "\e7eb";
|
||||
}
|
||||
|
||||
.icon-a-zu709:before {
|
||||
content: "\e7e8";
|
||||
}
|
||||
|
||||
.icon-tubiaoshuoming:before {
|
||||
content: "\e7e9";
|
||||
}
|
||||
|
||||
.icon-chudahuishoushuai1:before {
|
||||
content: "\e7e3";
|
||||
}
|
||||
|
||||
.icon-chakanwenjuanrenshu:before {
|
||||
content: "\e7e4";
|
||||
}
|
||||
|
||||
.icon-tiaoyanxiangmuzhuangtai:before {
|
||||
content: "\e7e5";
|
||||
}
|
||||
|
||||
.icon-wanchengdatirenshu:before {
|
||||
content: "\e7e6";
|
||||
}
|
||||
|
||||
.icon-dajuanrenshu:before {
|
||||
content: "\e7e7";
|
||||
}
|
||||
|
||||
.icon-wenjuanku:before {
|
||||
content: "\e7e2";
|
||||
}
|
||||
|
||||
.icon-tiku1:before {
|
||||
content: "\e7e1";
|
||||
}
|
||||
|
||||
.icon-a-jingjiadianjijiage:before {
|
||||
content: "\e7d7";
|
||||
}
|
||||
|
||||
.icon-jingjiajingzhengdu:before {
|
||||
content: "\e7d8";
|
||||
}
|
||||
|
||||
.icon-liuliangzhishu:before {
|
||||
content: "\e7d9";
|
||||
}
|
||||
|
||||
.icon-yidongrijiansuoliang:before {
|
||||
content: "\e7da";
|
||||
}
|
||||
|
||||
.icon-jingjiagongsishuliang:before {
|
||||
content: "\e7db";
|
||||
}
|
||||
|
||||
.icon-yidongzhishu:before {
|
||||
content: "\e7dc";
|
||||
}
|
||||
|
||||
.icon-PCrijiansuoliang:before {
|
||||
content: "\e7dd";
|
||||
}
|
||||
|
||||
.icon-shoululiang:before {
|
||||
content: "\e7de";
|
||||
}
|
||||
|
||||
.icon-changweicigeshu:before {
|
||||
content: "\e7df";
|
||||
}
|
||||
|
||||
.icon-a-360zhishu:before {
|
||||
content: "\e7e0";
|
||||
}
|
||||
|
||||
.icon-guanjiancizhushi:before {
|
||||
content: "\e7d4";
|
||||
}
|
||||
|
||||
@@ -5,6 +5,391 @@
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "调研猩球前台icon",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "33133939",
|
||||
"name": "文件 (1)",
|
||||
"font_class": "a-wenjian1",
|
||||
"unicode": "e60e",
|
||||
"unicode_decimal": 58894
|
||||
},
|
||||
{
|
||||
"icon_id": "33069016",
|
||||
"name": "项目",
|
||||
"font_class": "xiangmu",
|
||||
"unicode": "e809",
|
||||
"unicode_decimal": 59401
|
||||
},
|
||||
{
|
||||
"icon_id": "33002397",
|
||||
"name": "PSM",
|
||||
"font_class": "PSM2",
|
||||
"unicode": "e807",
|
||||
"unicode_decimal": 59399
|
||||
},
|
||||
{
|
||||
"icon_id": "33002398",
|
||||
"name": "KANO",
|
||||
"font_class": "KANO2",
|
||||
"unicode": "e808",
|
||||
"unicode_decimal": 59400
|
||||
},
|
||||
{
|
||||
"icon_id": "32968447",
|
||||
"name": "替换图片",
|
||||
"font_class": "tihuantupian",
|
||||
"unicode": "e805",
|
||||
"unicode_decimal": 59397
|
||||
},
|
||||
{
|
||||
"icon_id": "32967776",
|
||||
"name": "放大图片",
|
||||
"font_class": "fangdatupian",
|
||||
"unicode": "e806",
|
||||
"unicode_decimal": 59398
|
||||
},
|
||||
{
|
||||
"icon_id": "32932788",
|
||||
"name": "联系人",
|
||||
"font_class": "lianxiren1",
|
||||
"unicode": "e804",
|
||||
"unicode_decimal": 59396
|
||||
},
|
||||
{
|
||||
"icon_id": "32896944",
|
||||
"name": "dakai",
|
||||
"font_class": "dakai1",
|
||||
"unicode": "e803",
|
||||
"unicode_decimal": 59395
|
||||
},
|
||||
{
|
||||
"icon_id": "32896940",
|
||||
"name": "a-bianzu3",
|
||||
"font_class": "a-bianzu34",
|
||||
"unicode": "e802",
|
||||
"unicode_decimal": 59394
|
||||
},
|
||||
{
|
||||
"icon_id": "32896935",
|
||||
"name": "xuanxiangxianshi",
|
||||
"font_class": "xuanxiangxianshi1",
|
||||
"unicode": "e801",
|
||||
"unicode_decimal": 59393
|
||||
},
|
||||
{
|
||||
"icon_id": "32896934",
|
||||
"name": "a-CombinedShape2",
|
||||
"font_class": "a-CombinedShape21",
|
||||
"unicode": "e800",
|
||||
"unicode_decimal": 59392
|
||||
},
|
||||
{
|
||||
"icon_id": "32896894",
|
||||
"name": "xiazaiqi",
|
||||
"font_class": "xiazaiqi",
|
||||
"unicode": "e7fe",
|
||||
"unicode_decimal": 59390
|
||||
},
|
||||
{
|
||||
"icon_id": "32896920",
|
||||
"name": "piliang",
|
||||
"font_class": "piliang1",
|
||||
"unicode": "e7ff",
|
||||
"unicode_decimal": 59391
|
||||
},
|
||||
{
|
||||
"icon_id": "32880564",
|
||||
"name": "分享",
|
||||
"font_class": "fenxiang2",
|
||||
"unicode": "e7fc",
|
||||
"unicode_decimal": 59388
|
||||
},
|
||||
{
|
||||
"icon_id": "32880565",
|
||||
"name": "发布",
|
||||
"font_class": "fabu3",
|
||||
"unicode": "e7fd",
|
||||
"unicode_decimal": 59389
|
||||
},
|
||||
{
|
||||
"icon_id": "32874979",
|
||||
"name": "3D场景分析",
|
||||
"font_class": "a-3Dchangjingfenxi",
|
||||
"unicode": "e7fb",
|
||||
"unicode_decimal": 59387
|
||||
},
|
||||
{
|
||||
"icon_id": "32850006",
|
||||
"name": "收藏",
|
||||
"font_class": "shoucang2",
|
||||
"unicode": "e7f9",
|
||||
"unicode_decimal": 59385
|
||||
},
|
||||
{
|
||||
"icon_id": "32850007",
|
||||
"name": "收藏空",
|
||||
"font_class": "shoucangkong",
|
||||
"unicode": "e7fa",
|
||||
"unicode_decimal": 59386
|
||||
},
|
||||
{
|
||||
"icon_id": "32775900",
|
||||
"name": "收藏",
|
||||
"font_class": "shoucang",
|
||||
"unicode": "e7f5",
|
||||
"unicode_decimal": 59381
|
||||
},
|
||||
{
|
||||
"icon_id": "32775901",
|
||||
"name": "预览",
|
||||
"font_class": "yulan2",
|
||||
"unicode": "e7f6",
|
||||
"unicode_decimal": 59382
|
||||
},
|
||||
{
|
||||
"icon_id": "32775957",
|
||||
"name": "编组 3",
|
||||
"font_class": "a-bianzu33",
|
||||
"unicode": "e7f7",
|
||||
"unicode_decimal": 59383
|
||||
},
|
||||
{
|
||||
"icon_id": "32776009",
|
||||
"name": "联系我们",
|
||||
"font_class": "lianxiwomen",
|
||||
"unicode": "e7f8",
|
||||
"unicode_decimal": 59384
|
||||
},
|
||||
{
|
||||
"icon_id": "32775859",
|
||||
"name": "编组 2",
|
||||
"font_class": "a-bianzu22",
|
||||
"unicode": "e7f3",
|
||||
"unicode_decimal": 59379
|
||||
},
|
||||
{
|
||||
"icon_id": "32775860",
|
||||
"name": "编组",
|
||||
"font_class": "bianzu6",
|
||||
"unicode": "e7f4",
|
||||
"unicode_decimal": 59380
|
||||
},
|
||||
{
|
||||
"icon_id": "32771188",
|
||||
"name": "组 699",
|
||||
"font_class": "a-zu699",
|
||||
"unicode": "e7f2",
|
||||
"unicode_decimal": 59378
|
||||
},
|
||||
{
|
||||
"icon_id": "32726360",
|
||||
"name": "素材库",
|
||||
"font_class": "sucaiku",
|
||||
"unicode": "e7f0",
|
||||
"unicode_decimal": 59376
|
||||
},
|
||||
{
|
||||
"icon_id": "32726361",
|
||||
"name": "我的作品",
|
||||
"font_class": "wodezuopin",
|
||||
"unicode": "e7f1",
|
||||
"unicode_decimal": 59377
|
||||
},
|
||||
{
|
||||
"icon_id": "32599974",
|
||||
"name": "容器",
|
||||
"font_class": "rongqi6",
|
||||
"unicode": "e7ed",
|
||||
"unicode_decimal": 59373
|
||||
},
|
||||
{
|
||||
"icon_id": "32599653",
|
||||
"name": "容器 (1)",
|
||||
"font_class": "a-rongqi1",
|
||||
"unicode": "e60c",
|
||||
"unicode_decimal": 58892
|
||||
},
|
||||
{
|
||||
"icon_id": "32599654",
|
||||
"name": "容器",
|
||||
"font_class": "rongqi5",
|
||||
"unicode": "e60d",
|
||||
"unicode_decimal": 58893
|
||||
},
|
||||
{
|
||||
"icon_id": "32599041",
|
||||
"name": "容器 2",
|
||||
"font_class": "a-rongqi2",
|
||||
"unicode": "e60b",
|
||||
"unicode_decimal": 58891
|
||||
},
|
||||
{
|
||||
"icon_id": "32565199",
|
||||
"name": "Word导入",
|
||||
"font_class": "Worddaoru",
|
||||
"unicode": "e7ef",
|
||||
"unicode_decimal": 59375
|
||||
},
|
||||
{
|
||||
"icon_id": "32563282",
|
||||
"name": "容器",
|
||||
"font_class": "rongqi4",
|
||||
"unicode": "e7ec",
|
||||
"unicode_decimal": 59372
|
||||
},
|
||||
{
|
||||
"icon_id": "32563284",
|
||||
"name": "组 671",
|
||||
"font_class": "a-zu671",
|
||||
"unicode": "e7ee",
|
||||
"unicode_decimal": 59374
|
||||
},
|
||||
{
|
||||
"icon_id": "32548960",
|
||||
"name": "查看人群包",
|
||||
"font_class": "chakanrenqunbao",
|
||||
"unicode": "e7ea",
|
||||
"unicode_decimal": 59370
|
||||
},
|
||||
{
|
||||
"icon_id": "32548961",
|
||||
"name": "链接",
|
||||
"font_class": "lianjie",
|
||||
"unicode": "e7eb",
|
||||
"unicode_decimal": 59371
|
||||
},
|
||||
{
|
||||
"icon_id": "32534923",
|
||||
"name": "组 709",
|
||||
"font_class": "a-zu709",
|
||||
"unicode": "e7e8",
|
||||
"unicode_decimal": 59368
|
||||
},
|
||||
{
|
||||
"icon_id": "32534924",
|
||||
"name": "图表说明",
|
||||
"font_class": "tubiaoshuoming",
|
||||
"unicode": "e7e9",
|
||||
"unicode_decimal": 59369
|
||||
},
|
||||
{
|
||||
"icon_id": "32524103",
|
||||
"name": "触达回收率",
|
||||
"font_class": "chudahuishoushuai1",
|
||||
"unicode": "e7e3",
|
||||
"unicode_decimal": 59363
|
||||
},
|
||||
{
|
||||
"icon_id": "32524104",
|
||||
"name": "查看问卷人数",
|
||||
"font_class": "chakanwenjuanrenshu",
|
||||
"unicode": "e7e4",
|
||||
"unicode_decimal": 59364
|
||||
},
|
||||
{
|
||||
"icon_id": "32524105",
|
||||
"name": "调研项目状态",
|
||||
"font_class": "tiaoyanxiangmuzhuangtai",
|
||||
"unicode": "e7e5",
|
||||
"unicode_decimal": 59365
|
||||
},
|
||||
{
|
||||
"icon_id": "32524110",
|
||||
"name": "完成答题人数",
|
||||
"font_class": "wanchengdatirenshu",
|
||||
"unicode": "e7e6",
|
||||
"unicode_decimal": 59366
|
||||
},
|
||||
{
|
||||
"icon_id": "32524182",
|
||||
"name": "答卷人数",
|
||||
"font_class": "dajuanrenshu",
|
||||
"unicode": "e7e7",
|
||||
"unicode_decimal": 59367
|
||||
},
|
||||
{
|
||||
"icon_id": "32425797",
|
||||
"name": "问卷库",
|
||||
"font_class": "wenjuanku",
|
||||
"unicode": "e7e2",
|
||||
"unicode_decimal": 59362
|
||||
},
|
||||
{
|
||||
"icon_id": "32425227",
|
||||
"name": "题库",
|
||||
"font_class": "tiku1",
|
||||
"unicode": "e7e1",
|
||||
"unicode_decimal": 59361
|
||||
},
|
||||
{
|
||||
"icon_id": "32421503",
|
||||
"name": "竞价点击价格(¥)",
|
||||
"font_class": "a-jingjiadianjijiage",
|
||||
"unicode": "e7d7",
|
||||
"unicode_decimal": 59351
|
||||
},
|
||||
{
|
||||
"icon_id": "32421505",
|
||||
"name": "竞价竞争度",
|
||||
"font_class": "jingjiajingzhengdu",
|
||||
"unicode": "e7d8",
|
||||
"unicode_decimal": 59352
|
||||
},
|
||||
{
|
||||
"icon_id": "32421506",
|
||||
"name": "流量指数",
|
||||
"font_class": "liuliangzhishu",
|
||||
"unicode": "e7d9",
|
||||
"unicode_decimal": 59353
|
||||
},
|
||||
{
|
||||
"icon_id": "32421507",
|
||||
"name": "移动日检索量",
|
||||
"font_class": "yidongrijiansuoliang",
|
||||
"unicode": "e7da",
|
||||
"unicode_decimal": 59354
|
||||
},
|
||||
{
|
||||
"icon_id": "32421508",
|
||||
"name": "竞价公司数量",
|
||||
"font_class": "jingjiagongsishuliang",
|
||||
"unicode": "e7db",
|
||||
"unicode_decimal": 59355
|
||||
},
|
||||
{
|
||||
"icon_id": "32421509",
|
||||
"name": "移动指数",
|
||||
"font_class": "yidongzhishu",
|
||||
"unicode": "e7dc",
|
||||
"unicode_decimal": 59356
|
||||
},
|
||||
{
|
||||
"icon_id": "32421510",
|
||||
"name": "PC日检索量",
|
||||
"font_class": "PCrijiansuoliang",
|
||||
"unicode": "e7dd",
|
||||
"unicode_decimal": 59357
|
||||
},
|
||||
{
|
||||
"icon_id": "32421511",
|
||||
"name": "收录量",
|
||||
"font_class": "shoululiang",
|
||||
"unicode": "e7de",
|
||||
"unicode_decimal": 59358
|
||||
},
|
||||
{
|
||||
"icon_id": "32421512",
|
||||
"name": "长尾词个数",
|
||||
"font_class": "changweicigeshu",
|
||||
"unicode": "e7df",
|
||||
"unicode_decimal": 59359
|
||||
},
|
||||
{
|
||||
"icon_id": "32421566",
|
||||
"name": "360指数",
|
||||
"font_class": "a-360zhishu",
|
||||
"unicode": "e7e0",
|
||||
"unicode_decimal": 59360
|
||||
},
|
||||
{
|
||||
"icon_id": "32375799",
|
||||
"name": "关键词注释",
|
||||
|
||||
@@ -23,156 +23,165 @@ const constantRoutes = [
|
||||
// },
|
||||
{
|
||||
path: '/:catchAll(.*)',
|
||||
redirect: "/error/404",
|
||||
meta: { noRedirectLogin: true },
|
||||
redirect: '/error/404',
|
||||
meta: { noRedirectLogin: true }
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
redirect: "/home"
|
||||
path: '/',
|
||||
redirect: '/home'
|
||||
},
|
||||
|
||||
{
|
||||
path: "/heartbeat",
|
||||
component: () => import(/* webpackChunkName: 'heartbeat' */ "@views/Heartbeat/Index.vue"),
|
||||
path: '/heartbeat',
|
||||
component: () => import(/* webpackChunkName: 'heartbeat' */ '@views/Heartbeat/Index.vue')
|
||||
},
|
||||
{
|
||||
path: "/home",
|
||||
name: "home",
|
||||
redirect: "/home/project",
|
||||
component: () => import(/* webpackChunkName: 'home' */ "@views/Home/Index.vue"),
|
||||
children: [...ProjectManage, ...TemplateMarket, ...Contact, ...DocumentLibrary,...DataStatistics, ...Creative]
|
||||
path: '/home',
|
||||
name: 'home',
|
||||
redirect: '/home/project',
|
||||
component: () => import(/* webpackChunkName: 'home' */ '@views/Home/Index.vue'),
|
||||
children: [...ProjectManage, ...TemplateMarket, ...Contact, ...DocumentLibrary, ...DataStatistics, ...Creative]
|
||||
},
|
||||
{
|
||||
path: "/luck",
|
||||
name: "luck",
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/redpacket/luck.vue")
|
||||
}, {
|
||||
path: "/addinfor",
|
||||
name: "addinfor",
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/redpacket/addinfor.vue")
|
||||
path: '/luck',
|
||||
name: 'luck',
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/redpacket/luck.vue')
|
||||
},
|
||||
{
|
||||
path: "/prize",
|
||||
name: "prize",
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/redpacket/prize.vue")
|
||||
path: '/addinfor',
|
||||
name: 'addinfor',
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/redpacket/addinfor.vue')
|
||||
},
|
||||
{
|
||||
path: "/succeed",
|
||||
name: "succeed",
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/redpacket/succeed.vue")
|
||||
path: '/prize',
|
||||
name: 'prize',
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/redpacket/prize.vue')
|
||||
},
|
||||
{
|
||||
path: "/login",
|
||||
name: "login",
|
||||
component: () => import(/* webpackChunkName: 'login' */ "@views/Login/Login.vue")
|
||||
path: '/succeed',
|
||||
name: 'succeed',
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/redpacket/succeed.vue')
|
||||
},
|
||||
{
|
||||
path: "/loginInvite",
|
||||
name: "loginInvite",
|
||||
component: () => import(/* webpackChunkName: 'login' */ "@views/TeamManage/TeamCenter/teamAdmin/login.vue")
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import(/* webpackChunkName: 'login' */ '@views/Login/Login.vue')
|
||||
},
|
||||
{
|
||||
path: "/answer",
|
||||
name: "Answer",
|
||||
path: '/loginInvite',
|
||||
name: 'loginInvite',
|
||||
component: () => import(/* webpackChunkName: 'login' */ '@views/TeamManage/TeamCenter/teamAdmin/login.vue')
|
||||
},
|
||||
{
|
||||
path: '/answer',
|
||||
name: 'Answer',
|
||||
meta: { noRedirectLogin: true },
|
||||
component: () => import(/* webpackChunkName: "answer" */ "../views/Answer/Index.vue")
|
||||
component: () => import(/* webpackChunkName: "answer" */ '../views/Answer/Index.vue')
|
||||
},
|
||||
{
|
||||
path: "/preview",
|
||||
name: "Preview",
|
||||
component: () => import(/* webpackChunkName: "preview" */ "../views/Answer/Preview.vue")
|
||||
path: '/preview',
|
||||
name: 'Preview',
|
||||
component: () => import(/* webpackChunkName: "preview" */ '../views/Answer/Preview.vue')
|
||||
},
|
||||
{
|
||||
path: "/survey",
|
||||
name: "Survey",
|
||||
redirect: "/survey/planet",
|
||||
component: () => import(/* webpackChunkName: "survey" */ "../views/survey/index.vue"),
|
||||
path: '/survey',
|
||||
name: 'Survey',
|
||||
redirect: '/survey/planet',
|
||||
component: () => import(/* webpackChunkName: "survey" */ '../views/survey/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: "planet",
|
||||
name: "planet",
|
||||
redirect: "/survey/planet/design",
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/Index.vue"),
|
||||
path: 'planet',
|
||||
name: 'planet',
|
||||
redirect: '/survey/planet/design',
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/Index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: "design",
|
||||
name: "design",
|
||||
meta: { showPreview: true, showPublish: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/Design/DesignContent.vue")
|
||||
path: 'design',
|
||||
name: 'design',
|
||||
meta: { showPreview: true, showPublish: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/Design/DesignContent.vue')
|
||||
},
|
||||
{
|
||||
path: "logical",
|
||||
name: "logical",
|
||||
meta: { showPublish: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/Logical/Index.vue")
|
||||
path: 'logical',
|
||||
name: 'logical',
|
||||
meta: { showPublish: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/Logical/Index.vue')
|
||||
},
|
||||
{
|
||||
path: "test",
|
||||
meta: { showPublish: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/PlanetTest.vue")
|
||||
path: 'test',
|
||||
meta: { showPublish: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/PlanetTest.vue')
|
||||
},
|
||||
{
|
||||
path: "answer-setting",
|
||||
meta: { showPublish: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/AnswerSetting.vue")
|
||||
path: 'answer-setting',
|
||||
meta: { showPublish: true, showDownload: false },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/AnswerSetting.vue')
|
||||
},
|
||||
{
|
||||
path: "theme",
|
||||
meta: { showPublish: true, showPreview: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/Theme/index.vue")
|
||||
path: 'theme',
|
||||
meta: { showPublish: true, showPreview: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/Theme/index.vue')
|
||||
},
|
||||
{
|
||||
path: "redpacket",
|
||||
meta: { showPublish: true, showPreview: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/redpacket/index.vue")
|
||||
path: 'redpacket',
|
||||
meta: { showPublish: true, showPreview: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/redpacket/index.vue')
|
||||
},
|
||||
{
|
||||
path: "addset",
|
||||
meta: { showPublish: true, showPreview: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/planetDesign/redpacket/addset.vue")
|
||||
path: 'addset',
|
||||
meta: { showPublish: true, showPreview: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/planetDesign/redpacket/addset.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "schedule",
|
||||
name: "schedule",
|
||||
redirect: "/survey/schedule/index",
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/schedule/index.vue"),
|
||||
path: 'schedule',
|
||||
name: 'schedule',
|
||||
redirect: '/survey/schedule/index',
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/schedule/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: "recycle",
|
||||
name: "recycle",
|
||||
meta: { showPreview: true, showPublish: true, showDownload: true, },
|
||||
component: () => import(/* webpackChunkName: "planet" */ "../views/schedule/recycle.vue")
|
||||
},]
|
||||
path: 'recycle',
|
||||
name: 'recycle',
|
||||
meta: { showPreview: true, showPublish: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "planet" */ '../views/schedule/recycle.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "analyse",
|
||||
name: "analyse",
|
||||
path: 'analyse',
|
||||
name: 'analyse',
|
||||
redirect: { name: 'Diagram' },
|
||||
meta: { keepAlive: false },
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/index"),
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/index'),
|
||||
children: [
|
||||
{
|
||||
path: "data-particulars",
|
||||
name: "DataParticulars",
|
||||
path: 'data-particulars',
|
||||
name: 'DataParticulars',
|
||||
meta: { keepAlive: true },
|
||||
meta: { showPublish: false, showPreview: false, showShare: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/particulars/list")
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/particulars/list')
|
||||
},
|
||||
{
|
||||
path: "diagram",
|
||||
name: "Diagram",
|
||||
path: 'test-particulars',
|
||||
name: 'TestParticulars',
|
||||
meta: { keepAlive: true },
|
||||
meta: { showPublish: false, showPreview: false, showShare: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/particulars/test')
|
||||
},
|
||||
{
|
||||
path: 'diagram',
|
||||
name: 'Diagram',
|
||||
meta: { keepAlive: true, showDownload: true },
|
||||
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/diagram/test")
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/diagram/test')
|
||||
},
|
||||
{
|
||||
path: "test",
|
||||
name: "test",
|
||||
path: 'test',
|
||||
name: 'test',
|
||||
meta: { keepAlive: true },
|
||||
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/diagram/test")
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/diagram/test')
|
||||
},
|
||||
{
|
||||
path: "kndiagram",
|
||||
@@ -210,65 +219,70 @@ const constantRoutes = [
|
||||
// path: "index",
|
||||
// component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/kndiagram/index"),
|
||||
// }
|
||||
|
||||
},
|
||||
{
|
||||
path: "bi",
|
||||
name: "bi",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/bi")
|
||||
path: 'bi',
|
||||
name: 'bi',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/bi')
|
||||
},
|
||||
{
|
||||
// BPTO模拟
|
||||
path: "bptoAnalog",
|
||||
name: "bptoAnalog",
|
||||
path: 'bptoAnalog',
|
||||
name: 'bptoAnalog',
|
||||
meta: { keepAlive: true },
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/bptoAnalog/index")
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/bptoAnalog/index')
|
||||
},
|
||||
{
|
||||
path: "crosstabs",
|
||||
name: "crosstabs",
|
||||
path: 'crosstabs',
|
||||
name: 'crosstabs',
|
||||
meta: { keepAlive: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/crosstabs/index.vue")
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/crosstabs/index.vue')
|
||||
},
|
||||
{
|
||||
path: "recycleBin",
|
||||
name: "recycleBin",
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/recycleBin/index"),
|
||||
redirect: "detailData",
|
||||
children: [{
|
||||
name: "数据明细",
|
||||
path: "detailData",
|
||||
path: 'recycleBin',
|
||||
name: 'recycleBin',
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/recycleBin/index'),
|
||||
redirect: 'detailData',
|
||||
children: [
|
||||
{
|
||||
name: '数据明细',
|
||||
path: 'detailData',
|
||||
// meta: {title:"数据明细" },
|
||||
component: () => import(/* webpackChunkName: "analyse" */ "@/views/DataAnalyse/recycleBin/binList/detailData"),
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/recycleBin/binList/detailData')
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "publish",
|
||||
name: "publish",
|
||||
redirect: "/survey/publish/link",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/index"),
|
||||
path: 'publish',
|
||||
name: 'publish',
|
||||
redirect: '/survey/publish/link',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/index'),
|
||||
children: [
|
||||
{
|
||||
path: "link-source",
|
||||
name: "link-source",
|
||||
path: 'link-source',
|
||||
name: 'link-source',
|
||||
meta: { showPreview: false, showPublish: false, keepAlive: true, showShare: true },
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/link")
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/link')
|
||||
},
|
||||
{
|
||||
path: "link",
|
||||
name: "link",
|
||||
path: 'link',
|
||||
name: 'link',
|
||||
meta: { showPreview: false, showPublish: false, keepAlive: true, showShare: true },
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/launch-center/launch-task/index")
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/launch-center/launch-task/index')
|
||||
},
|
||||
{
|
||||
path: "create",
|
||||
name: "create",
|
||||
path: 'create',
|
||||
name: 'create',
|
||||
meta: { showPreview: false, showPublish: false, keepAlive: true, showShare: true },
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/launch-center/launch-task/create")
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/launch-center/launch-task/create')
|
||||
},
|
||||
{
|
||||
path: 'enterprise-weChat',
|
||||
name: 'enterprise-weChat',
|
||||
meta: { showPreview: false, showPublish: false, keepAlive: true, showShare: true, permission:'super_admin_flag' },
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/launch-center/launch-task/enterpriseWeChat')
|
||||
},
|
||||
// {
|
||||
// path: "link",
|
||||
@@ -277,80 +291,86 @@ const constantRoutes = [
|
||||
// component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/link")
|
||||
// },
|
||||
{
|
||||
path: "analyst",
|
||||
name: "analyst",
|
||||
path: 'analyst',
|
||||
name: 'analyst',
|
||||
meta: { showPreview: false, showPublish: false, keepAlive: true, showShare: true },
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/analyse")
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/analyse')
|
||||
},
|
||||
{
|
||||
path: "api",
|
||||
name: "api",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/api")
|
||||
path: 'api',
|
||||
name: 'api',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/api')
|
||||
},
|
||||
{
|
||||
path: "email",
|
||||
name: "email",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/message/record"),
|
||||
path: 'email',
|
||||
name: 'email',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/message/record')
|
||||
},
|
||||
{
|
||||
path: "census",
|
||||
name: "census",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/census/census"),
|
||||
path: 'census',
|
||||
name: 'census',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/census/census')
|
||||
},
|
||||
{
|
||||
path: "emailRecord",
|
||||
name: "emailRecord",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/email/email")
|
||||
path: 'emailRecord',
|
||||
name: 'emailRecord',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/email/email')
|
||||
},
|
||||
{
|
||||
path: "message",
|
||||
name: "message",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/message/record")
|
||||
path: 'message',
|
||||
name: 'message',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/message/record')
|
||||
},
|
||||
{
|
||||
path: "messageRecord",
|
||||
name: "messageRecord",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/message/message")
|
||||
path: 'messageRecord',
|
||||
name: 'messageRecord',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/message/message')
|
||||
},
|
||||
{
|
||||
path: "sample",
|
||||
name: "sample",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/sample/sample")
|
||||
path: 'sample',
|
||||
name: 'sample',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/sample/sample')
|
||||
},
|
||||
{
|
||||
path: "activity",
|
||||
name: "activity",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/activity/activity")
|
||||
path: 'activity',
|
||||
name: 'activity',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/activity/activity')
|
||||
},
|
||||
{
|
||||
path: "group",
|
||||
name: "group",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/temp")
|
||||
path: 'group',
|
||||
name: 'group',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/temp')
|
||||
},
|
||||
|
||||
{
|
||||
path: "flush",
|
||||
name: "flush",
|
||||
component: () => import(/* webpackChunkName: "publish" */ "@/views/Publish/flush")
|
||||
},
|
||||
path: 'flush',
|
||||
name: 'flush',
|
||||
component: () => import(/* webpackChunkName: "publish" */ '@/views/Publish/flush')
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/InviteLogin",
|
||||
name: "InviteLogin",
|
||||
component: () => import(/* webpackChunkName: 'InviteLogin' */ "../views/TeamManage/InviteLogin.vue")
|
||||
path: '/not-data',
|
||||
name: 'notData',
|
||||
// meta: { showPublish: false, showPreview: false, showShare: true, showDownload: true },
|
||||
component: () => import(/* webpackChunkName: "analyse" */ '@/views/DataAnalyse/particulars/notData/notData')
|
||||
},
|
||||
{
|
||||
path: "/team-manage",
|
||||
name: "TeamManage",
|
||||
component: () => import(/* webpackChunkName: 'home' */ "../views/TeamManage/index.vue"),
|
||||
path: '/InviteLogin',
|
||||
name: 'InviteLogin',
|
||||
component: () => import(/* webpackChunkName: 'InviteLogin' */ '../views/TeamManage/InviteLogin.vue')
|
||||
},
|
||||
{
|
||||
path: '/team-manage',
|
||||
name: 'TeamManage',
|
||||
component: () => import(/* webpackChunkName: 'home' */ '../views/TeamManage/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: "user-center",
|
||||
name: "userCenTer",
|
||||
component: () => import(/* webpackChunkName: 'home' */ "../views/TeamManage//UserCenter/index.vue"),
|
||||
path: 'user-center',
|
||||
name: 'userCenTer',
|
||||
component: () => import(/* webpackChunkName: 'home' */ '../views/TeamManage//UserCenter/index.vue')
|
||||
// children: [
|
||||
// {
|
||||
// path: "design",
|
||||
@@ -381,11 +401,11 @@ const constantRoutes = [
|
||||
// ]
|
||||
},
|
||||
{
|
||||
path: "team-center",
|
||||
name: "teamCenter",
|
||||
component: () => import(/* webpackChunkName: 'home' */ "../views/TeamManage//TeamCenter/index.vue")
|
||||
},
|
||||
],
|
||||
path: 'team-center',
|
||||
name: 'teamCenter',
|
||||
component: () => import(/* webpackChunkName: 'home' */ '../views/TeamManage//TeamCenter/index.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/SceneSurveyViewerPage",
|
||||
@@ -400,19 +420,29 @@ const constantRoutes = [
|
||||
// component: () => import(/* webpackChunkName: "preview" */ "../views/DownloadCenter/index.vue")
|
||||
// },
|
||||
...routes
|
||||
];
|
||||
]
|
||||
|
||||
export const asyncRoutes = [];
|
||||
export const asyncRoutes = []
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes: constantRoutes
|
||||
});
|
||||
})
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (!to.meta.noRedirectLogin) {
|
||||
if (window.self === window.top) {
|
||||
// window.parent.location.href = 'https://yip-uat.dctest.digitalyili.com/login';
|
||||
}
|
||||
}
|
||||
if(!to.meta.permission) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
if(!JSON.parse(localStorage.getItem('plantUserInfo'))[to.meta.permission]) {
|
||||
next({
|
||||
path:'/error/404',
|
||||
})
|
||||
return
|
||||
}
|
||||
next()
|
||||
})
|
||||
export default router;
|
||||
export default router
|
||||
|
||||
@@ -7,5 +7,9 @@ const router = [
|
||||
meta: { title: '模板库' },
|
||||
component: MarketManage,
|
||||
},
|
||||
{
|
||||
path: 'product_test/template',
|
||||
redirect: '/home/market',
|
||||
},
|
||||
];
|
||||
export default router;
|
||||
|
||||
@@ -7,6 +7,9 @@ export const A_COMMON_SET_QUESSAVEPARAM = 'A_COMMON_SET_QUESSAVEPARAM';
|
||||
export const A_COMMON_GET_ACTIVEQUESTION = 'A_COMMON_GET_ACTIVEQUESTION';
|
||||
export const A_COMMON_SET_ACTIVEQUESTION = 'A_COMMON_SET_ACTIVEQUESTION';
|
||||
|
||||
export const A_COMMON_SET_BANK_LIST = 'A_COMMON_SET_BANK_LIST';
|
||||
export const A_COMMON_GET_BANK_LIST = 'A_COMMON_GET_BANK_LIST';
|
||||
|
||||
export const A_COMMON_GET_WEBSOCKET = 'A_COMMON_GET_WEBSOCKET';
|
||||
export const A_COMMON_SET_WEBSOCKET = 'A_COMMON_SET_WEBSOCKET';
|
||||
|
||||
|
||||
@@ -18,5 +18,13 @@ export default {
|
||||
params
|
||||
});
|
||||
},
|
||||
// 问卷发布-发布统计-题组配额
|
||||
randomProgress (vuex, params = {}) {
|
||||
return request({
|
||||
url: `/console/survey_publishes/${params.sn}/random_progress`,
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,6 @@
|
||||
// import CommonApi from '../../api/api';
|
||||
import request from "@/utils/request";
|
||||
import {
|
||||
A_COMMON_GET_QUESTIONINFO,
|
||||
A_COMMON_SET_QUESTIONINFO,
|
||||
A_COMMON_GET_QUESSAVEPARAM,
|
||||
A_COMMON_SET_QUESSAVEPARAM,
|
||||
A_COMMON_GET_ACTIVEQUESTION,
|
||||
A_COMMON_SET_ACTIVEQUESTION,
|
||||
A_COMMON_GET_WEBSOCKET,
|
||||
A_COMMON_SET_WEBSOCKET,
|
||||
A_COMMON_GET_TOKEN,
|
||||
A_COMMON_CLEAR_TOKEN,
|
||||
M_COMMON_SET_TOKEN,
|
||||
M_COMMON_SET_USERINFO,
|
||||
M_COMMON_GET_USERINFO,
|
||||
M_COMMON_SET_SURVEY_STATUS,
|
||||
M_COMMON_SET_SURVEY_NAME,
|
||||
M_COMMON_SET_TOKEN_UNAUTHORIZED,
|
||||
GET_FILE_TYPE,
|
||||
M_COMMON_SET_THEME_INFO,
|
||||
HEADER_IMG_INFO,
|
||||
DELETET_HEME_INFO_HEADIMGURL,
|
||||
} from "../constance/constance.common";
|
||||
import request from '@/utils/request'
|
||||
import { A_COMMON_GET_QUESTIONINFO, A_COMMON_SET_QUESTIONINFO, A_COMMON_GET_QUESSAVEPARAM, A_COMMON_SET_QUESSAVEPARAM, A_COMMON_GET_ACTIVEQUESTION, A_COMMON_SET_ACTIVEQUESTION, A_COMMON_GET_WEBSOCKET, A_COMMON_SET_WEBSOCKET, A_COMMON_GET_TOKEN, A_COMMON_CLEAR_TOKEN, M_COMMON_SET_TOKEN, M_COMMON_SET_USERINFO, M_COMMON_GET_USERINFO, M_COMMON_SET_SURVEY_STATUS, M_COMMON_SET_SURVEY_NAME, M_COMMON_SET_TOKEN_UNAUTHORIZED, GET_FILE_TYPE, M_COMMON_SET_THEME_INFO, HEADER_IMG_INFO, DELETET_HEME_INFO_HEADIMGURL, A_COMMON_GET_BANK_LIST, A_COMMON_SET_BANK_LIST } from '../constance/constance.common'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
@@ -30,161 +9,175 @@ export default {
|
||||
quesSaveParam: {}, // 问题保存参数
|
||||
activeQuestion: {}, // 当前处于编辑态的题目
|
||||
file_type: [],
|
||||
token: localStorage.getItem("plantToken") ? localStorage.getItem("plantToken") : "",
|
||||
userInfo: localStorage.getItem("plantUserInfo")
|
||||
? JSON.parse(localStorage.getItem("plantUserInfo"))
|
||||
: {},
|
||||
token: localStorage.getItem('plantToken') ? localStorage.getItem('plantToken') : '',
|
||||
userInfo: localStorage.getItem('plantUserInfo') ? JSON.parse(localStorage.getItem('plantUserInfo')) : {},
|
||||
surveyStatus: undefined,
|
||||
surveyName: "",
|
||||
surveyName: '',
|
||||
tokenUnauthorized: false,
|
||||
websocket: {}, // 长链接websocket实例
|
||||
themeInfo: {}, // 主题配置信息
|
||||
headerImgInfo: {}, //皮肤头图,
|
||||
initHomeData: false, //首页数据更新
|
||||
initHomeData: false //首页数据更新
|
||||
},
|
||||
getters: {},
|
||||
mutations: {
|
||||
/** 获取题型列表 */
|
||||
[A_COMMON_SET_QUESTIONINFO](state, questionInfo) {
|
||||
state.questionInfo = JSON.parse(questionInfo);
|
||||
state.questionInfo = JSON.parse(questionInfo)
|
||||
},
|
||||
/** 获取问题保存参数 */
|
||||
[A_COMMON_SET_QUESSAVEPARAM](state, quesSaveParam) {
|
||||
state.quesSaveParam = JSON.parse(quesSaveParam);
|
||||
state.quesSaveParam = JSON.parse(quesSaveParam)
|
||||
},
|
||||
/** 获取当前选中题型 */
|
||||
[A_COMMON_SET_ACTIVEQUESTION](state, activeQuestion) {
|
||||
state.activeQuestion = JSON.parse(activeQuestion);
|
||||
state.activeQuestion = JSON.parse(activeQuestion)
|
||||
},
|
||||
/**获取题库列表 */
|
||||
[A_COMMON_SET_BANK_LIST](state, bankList) {
|
||||
state.bankList = bankList
|
||||
},
|
||||
/** 获取websocket实例 */
|
||||
[A_COMMON_SET_WEBSOCKET](state, ws) {
|
||||
state.websocket = ws;
|
||||
state.websocket = ws
|
||||
},
|
||||
|
||||
/** 获取token */
|
||||
[M_COMMON_SET_TOKEN](state, token) {
|
||||
state.token = token;
|
||||
state.token = token
|
||||
},
|
||||
/** 获取用户信息 */
|
||||
[M_COMMON_SET_USERINFO](state, userInfo) {
|
||||
state.userInfo = JSON.parse(userInfo);
|
||||
state.userInfo = JSON.parse(userInfo)
|
||||
},
|
||||
[M_COMMON_SET_SURVEY_STATUS](state, status) {
|
||||
state.surveyStatus = status;
|
||||
state.surveyStatus = status
|
||||
localStorage.setItem('surveyStatus', status)
|
||||
},
|
||||
[M_COMMON_SET_SURVEY_NAME](state, name) {
|
||||
state.surveyName = name;
|
||||
state.surveyName = name
|
||||
},
|
||||
[M_COMMON_SET_TOKEN_UNAUTHORIZED](state, status) {
|
||||
state.tokenUnauthorized = !!status;
|
||||
state.tokenUnauthorized = !!status
|
||||
},
|
||||
[GET_FILE_TYPE](state, file_type) {
|
||||
state.file_type = file_type;
|
||||
state.file_type = file_type
|
||||
},
|
||||
[M_COMMON_SET_THEME_INFO](state, status) {
|
||||
status.head_img_url = state.themeInfo.head_img_url || status.head_img_url;
|
||||
// status.head_img_url = state.themeInfo.head_img_url || status.head_img_url;
|
||||
// 不带头图使用
|
||||
if (!state.headerImgInfo.checked) {
|
||||
status.head_img_url = state.themeInfo.head_img_url;
|
||||
}
|
||||
state.themeInfo = status;
|
||||
},
|
||||
[HEADER_IMG_INFO](state, status) {
|
||||
if (state.headerImgInfo.checked === false) {
|
||||
status.checked = false;
|
||||
}
|
||||
state.headerImgInfo = status;
|
||||
},
|
||||
[DELETET_HEME_INFO_HEADIMGURL](state) {
|
||||
state.themeInfo.head_img_url = "";
|
||||
},
|
||||
state.themeInfo.head_img_url = ''
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
// 修改用户信息
|
||||
userInfo({ state }, data) {
|
||||
state.userInfo = data;
|
||||
state.userInfo = data
|
||||
},
|
||||
initHomeData(vuex, data) {
|
||||
vuex.state.initHomeData = data;
|
||||
vuex.state.initHomeData = data
|
||||
},
|
||||
/**题型列表 */
|
||||
[A_COMMON_GET_QUESTIONINFO]({ commit }, questionInfo) {
|
||||
commit(A_COMMON_SET_QUESTIONINFO, questionInfo);
|
||||
commit(A_COMMON_SET_QUESTIONINFO, questionInfo)
|
||||
},
|
||||
/**问题保存参数 */
|
||||
[A_COMMON_GET_QUESSAVEPARAM]({ commit }, quesSaveParam) {
|
||||
commit(A_COMMON_SET_QUESSAVEPARAM, quesSaveParam);
|
||||
commit(A_COMMON_SET_QUESSAVEPARAM, quesSaveParam)
|
||||
},
|
||||
/**选中题型 */
|
||||
[A_COMMON_GET_ACTIVEQUESTION]({ commit }, activeQuestion) {
|
||||
commit(A_COMMON_SET_ACTIVEQUESTION, activeQuestion);
|
||||
commit(A_COMMON_SET_ACTIVEQUESTION, activeQuestion)
|
||||
},
|
||||
/**获取题库列表 */
|
||||
[A_COMMON_GET_BANK_LIST]({ commit }, bankList) {
|
||||
commit(A_COMMON_SET_BANK_LIST, bankList)
|
||||
},
|
||||
/**websocket */
|
||||
[A_COMMON_GET_WEBSOCKET]({ commit }, ws) {
|
||||
commit(A_COMMON_SET_WEBSOCKET, ws);
|
||||
commit(A_COMMON_SET_WEBSOCKET, ws)
|
||||
},
|
||||
/* 获取用户token */
|
||||
[A_COMMON_GET_TOKEN]({ commit, dispatch }, token) {
|
||||
if (token) {
|
||||
console.log(dispatch);
|
||||
commit(M_COMMON_SET_TOKEN, token);
|
||||
console.log(dispatch)
|
||||
commit(M_COMMON_SET_TOKEN, token)
|
||||
}
|
||||
},
|
||||
[A_COMMON_CLEAR_TOKEN]: {
|
||||
root: true,
|
||||
handler({ commit }) {
|
||||
commit(M_COMMON_SET_TOKEN, "");
|
||||
localStorage.removeItem("plantToken");
|
||||
return true;
|
||||
},
|
||||
commit(M_COMMON_SET_TOKEN, '')
|
||||
localStorage.removeItem('plantToken')
|
||||
return true
|
||||
}
|
||||
},
|
||||
/* 获取当前登录用户信心 */
|
||||
[M_COMMON_GET_USERINFO]({ commit, dispatch }, userInfo) {
|
||||
if (userInfo) {
|
||||
console.log(dispatch);
|
||||
commit(M_COMMON_SET_MENUS, userInfo);
|
||||
console.log(dispatch)
|
||||
commit(M_COMMON_SET_MENUS, userInfo)
|
||||
}
|
||||
},
|
||||
[GET_FILE_TYPE]({ commit, dispatch }, file_type) {
|
||||
if (file_type) {
|
||||
console.log(dispatch);
|
||||
commit(GET_FILE_TYPE, file_type);
|
||||
console.log(dispatch)
|
||||
commit(GET_FILE_TYPE, file_type)
|
||||
}
|
||||
},
|
||||
// 登记联系人
|
||||
postCommunitiesContacts(vuex, params = {}) {
|
||||
return request({
|
||||
url: `/console/communities/${params.community_id}/contacts`,
|
||||
method: "POST",
|
||||
params,
|
||||
});
|
||||
method: 'POST',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 前端下载
|
||||
fileDown(vuex, { fileURL, fileName }) {
|
||||
const req = new XMLHttpRequest();
|
||||
req.open("get", fileURL);
|
||||
req.responseType = "blob";
|
||||
const req = new XMLHttpRequest()
|
||||
req.open('get', fileURL)
|
||||
req.responseType = 'blob'
|
||||
req.onreadystatechange = (res) => {
|
||||
if (res.currentTarget.readyState == 4 && res.currentTarget.status == 200) {
|
||||
const url = window.URL.createObjectURL(res.currentTarget.response);
|
||||
let link = document.createElement("a");
|
||||
link.download = fileName || "defaultName";
|
||||
link.style.display = "none";
|
||||
link.href = url;
|
||||
const url = window.URL.createObjectURL(res.currentTarget.response)
|
||||
let link = document.createElement('a')
|
||||
link.download = fileName || 'defaultName'
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
// 触发点击
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
};
|
||||
req.send();
|
||||
}
|
||||
req.send()
|
||||
},
|
||||
getYlToken() {
|
||||
try {
|
||||
return request({
|
||||
url: `/authorizations`,
|
||||
method: "POST",
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: localStorage.getItem("plantToken"),
|
||||
remoteIp: "127.0.0.1",
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Authorization: localStorage.getItem('plantToken'),
|
||||
remoteIp: '127.0.0.1'
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,71 +4,75 @@ import qs from 'qs'
|
||||
const conUrl = '/console'
|
||||
export default {
|
||||
namespaced: true,
|
||||
state:{
|
||||
selectKeys:[],
|
||||
dataFilterInfo:{},
|
||||
exportInfo:{}
|
||||
state: {
|
||||
selectKeys: [],
|
||||
selectIds: [],
|
||||
dataFilterInfo: {},
|
||||
exportInfo: {}
|
||||
},
|
||||
actions:{
|
||||
exportInfo({state},data){
|
||||
actions: {
|
||||
exportInfo({ state }, data) {
|
||||
state.exportInfo = data
|
||||
},
|
||||
// 题目答案数据清洗
|
||||
cleanAnswer({state},{answer,question}){
|
||||
console.log('开始数据清洗',answer);
|
||||
cleanAnswer({ state }, { answer, question }) {
|
||||
console.log('开始数据清洗', answer)
|
||||
let newChild = []
|
||||
// 判断是否有修改过的题型
|
||||
let isFlag = false
|
||||
for (let i = 0; i < answer.child.length; i++) {
|
||||
const el = answer.child[i];
|
||||
const el = answer.child[i]
|
||||
let flag = true
|
||||
let questionList = []
|
||||
question.map(cel=>{
|
||||
question.map((cel) => {
|
||||
questionList.push(cel.question_index)
|
||||
if(cel.question_index ===el.question_index&& cel.question_type !== el.question_type){
|
||||
if (cel.question_index === el.question_index && cel.question_type !== el.question_type) {
|
||||
flag = false
|
||||
isFlag = true
|
||||
}
|
||||
})
|
||||
if(questionList.length>0&&!questionList.includes(el.question_index)){
|
||||
if (questionList.length > 0 && !questionList.includes(el.question_index)) {
|
||||
flag = false
|
||||
isFlag = true
|
||||
}
|
||||
if(flag){
|
||||
if (flag) {
|
||||
newChild.push(el)
|
||||
}
|
||||
}
|
||||
if(newChild.length>0){
|
||||
if (newChild.length > 0) {
|
||||
answer.child = newChild
|
||||
}else{
|
||||
} else {
|
||||
answer.child = [{}]
|
||||
}
|
||||
return {answer,isFlag}
|
||||
return { answer, isFlag }
|
||||
},
|
||||
selectKeys({state},data){
|
||||
selectKeys({ state }, data) {
|
||||
state.selectKeys = data
|
||||
},
|
||||
dataFilterInfo({state},data){
|
||||
selectIds({ state }, data) {
|
||||
state.selectIds = data
|
||||
},
|
||||
dataFilterInfo({ state }, data) {
|
||||
state.dataFilterInfo = data
|
||||
},
|
||||
// 投放列表
|
||||
getSurveysAnswers(vuex, data = {}) {
|
||||
if(data.answer&&typeof data.answer =='object'){
|
||||
if (data.answer && typeof data.answer == 'object') {
|
||||
data.answer = JSON.stringify(data.answer)
|
||||
}
|
||||
console.log('筛选列表数据',data);
|
||||
console.log('筛选列表数据', data)
|
||||
return request({
|
||||
url: `${conUrl}/surveys/${data.sn}/answers`,
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
getSurveysHead(vuex, param = {}) {
|
||||
return request({
|
||||
url: `${conUrl}/surveys/${param.sn}/answers/heads`,
|
||||
method: 'GET',
|
||||
param
|
||||
});
|
||||
})
|
||||
},
|
||||
// 数据明细-导出pdf|zip
|
||||
getSurveysAnswersExport(vuex, data = {}) {
|
||||
@@ -76,7 +80,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answers_export`,
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 数据明细-下载
|
||||
getSurveysAnswersDown(vuex, data = {}) {
|
||||
@@ -84,7 +88,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answers_download`,
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 数据明细-回收站
|
||||
delSurveysAnswers(vuex, data = {}) {
|
||||
@@ -92,7 +96,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answers`,
|
||||
method: 'DELETE',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 筛选方案列表
|
||||
getTemplateExport(vuex, param = {}) {
|
||||
@@ -100,16 +104,16 @@ export default {
|
||||
url: `${conUrl}/surveys/${param.sn}/template_export`,
|
||||
method: 'GET',
|
||||
param
|
||||
});
|
||||
})
|
||||
},
|
||||
// 导入作答信息
|
||||
postAnswersImport(vuex, data = {}) {
|
||||
let sn = data.get("sn")
|
||||
let sn = data.get('sn')
|
||||
return request({
|
||||
url: `${conUrl}/surveys/${sn}/answers_import`,
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 筛选方案列表
|
||||
getSurveysAnswerFilter(vuex, param = {}) {
|
||||
@@ -117,7 +121,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${param.sn}/answer_filter`,
|
||||
method: 'GET',
|
||||
param
|
||||
});
|
||||
})
|
||||
},
|
||||
// 筛选方案新增
|
||||
postSurveysAnswers(vuex, data = {}) {
|
||||
@@ -125,7 +129,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answer_filter`,
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 筛选方案复制
|
||||
postSurveysAnswersClone(vuex, data = {}) {
|
||||
@@ -133,7 +137,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answer_filter/${data.id}`,
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 筛选方案修改
|
||||
putSurveysAnswers(vuex, data = {}) {
|
||||
@@ -141,7 +145,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answer_filter/${data.id}`,
|
||||
method: 'PUT',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 筛选方案置顶
|
||||
putSurveysAnswersTop(vuex, data = {}) {
|
||||
@@ -149,7 +153,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answer_filter/${data.id}/top`,
|
||||
method: 'PUT',
|
||||
data
|
||||
});
|
||||
})
|
||||
},
|
||||
// 筛选方案删除
|
||||
delSurveysAnswersTop(vuex, data = {}) {
|
||||
@@ -157,7 +161,7 @@ export default {
|
||||
url: `${conUrl}/surveys/${data.sn}/answer_filter/${data.id}`,
|
||||
method: 'DELETE',
|
||||
data
|
||||
});
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ export default {
|
||||
getPsmAnalyzeExport(vuex, params = {}) {
|
||||
return request({
|
||||
url: `${console}/surveys/psm/down-data`,
|
||||
method: 'POST',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
},
|
||||
|
||||
15
src/store/modules/throw.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
// 企微投放链接地址
|
||||
hrefUrl: '',
|
||||
},
|
||||
getters: {},
|
||||
mutations: {},
|
||||
actions: {
|
||||
changeHrefUrl ({ state }, url) {
|
||||
state.hrefUrl = url
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
19
src/style/utils.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
|
||||
覆盖全局样式
|
||||
|
||||
*/
|
||||
|
||||
.ant-select-item-option-selected{
|
||||
font-weight: normal!important;
|
||||
}
|
||||
.ant-select-selector{
|
||||
border-radius:4px;
|
||||
}
|
||||
.ant-select-dropdown.ant-select-dropdown-placement-bottomLeft{
|
||||
border-radius:4px;
|
||||
}
|
||||
.ant-table-column-sorter {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
$yili-default-color: #70b936;
|
||||
$yili-disabled-color: rgba(112, 185, 54, 0.3);
|
||||
$yili-btn-check-color: #28883D;
|
||||
$yili-btn-check-color: #8ec75a;
|
||||
$yili-btn-border-color: #74dd1d;
|
||||
$yili-bkg-color: rgba(112, 185, 54, 0.11);
|
||||
@@ -242,18 +242,18 @@ const advancedQuesTypeList = [
|
||||
// // check: false,
|
||||
// // type: 104,
|
||||
// // },
|
||||
// {
|
||||
// name: "PSM",
|
||||
// icon: "",
|
||||
// check: false,
|
||||
// type: 101,
|
||||
// },
|
||||
// {
|
||||
// name: "KANO",
|
||||
// icon: "",
|
||||
// check: false,
|
||||
// type: 102,
|
||||
// },
|
||||
{
|
||||
name: "PSM",
|
||||
icon: "",
|
||||
check: false,
|
||||
type: 101,
|
||||
},
|
||||
{
|
||||
name: "KANO",
|
||||
icon: "",
|
||||
check: false,
|
||||
type: 102,
|
||||
},
|
||||
]
|
||||
const d3QuestypeList = [
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as cheerio from "cheerio";
|
||||
class Common {
|
||||
/**
|
||||
* rgba 转 hex
|
||||
|
||||
@@ -20,7 +20,7 @@ service.interceptors.request.use(
|
||||
(config) => {
|
||||
// do something before request is sent
|
||||
config.headers.Accept = 'application/json';
|
||||
config.headers.ContentType = 'application/json';
|
||||
//config.headers.ContentType = 'application/json';
|
||||
config.headers.Authorization = `${localStorage.getItem('plantToken')}`;
|
||||
config.headers.remoteIp = `${localStorage.getItem('plantIp') || ''}`;
|
||||
// console.log(storage.getToken());
|
||||
|
||||
@@ -33,11 +33,11 @@ export default defineComponent({
|
||||
language: (navigator.browserLanguage || navigator.language).toLowerCase(),
|
||||
};
|
||||
const isMobile = browser.versions.mobile && !browser.versions.iPad;
|
||||
try {
|
||||
localStorage.setItem("plantIp", window.returnCitySN?window.returnCitySN["cip"]:"127.0.0.1");
|
||||
} catch (error) {
|
||||
localStorage.setItem("plantIp", "");
|
||||
}
|
||||
// try {
|
||||
// localStorage.setItem("plantIp", returnCitySN["cip"]);
|
||||
// } catch (error) {
|
||||
// localStorage.setItem("plantIp", "");
|
||||
// }
|
||||
|
||||
return { isMobile };
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-modal v-model:visible="shown" title="导出问卷" :destroyOnClose="true" @ok="handleOk">
|
||||
<a-modal v-model:visible="shown" title="导出问卷" :destroyOnClose="true" @ok="handleOk" :confirmLoading="loading">
|
||||
<div class="survey-download-modal-container">
|
||||
<div class="titie">请选择导出部分</div>
|
||||
<a-checkbox-group v-model:value="checkedList" :options="options" />
|
||||
@@ -8,6 +8,7 @@
|
||||
</a-modal>
|
||||
<!-- 下载中心 -->
|
||||
<DownloadCenter
|
||||
:sn="sn"
|
||||
:isView="true"
|
||||
v-model:visible="downloadVisible"
|
||||
v-if="downloadVisible"
|
||||
@@ -47,6 +48,7 @@ const props = defineProps({
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const shown = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
const showModal = async () => {
|
||||
shown.value = true;
|
||||
@@ -80,6 +82,7 @@ const download = async () => {
|
||||
// path: "/downloadCenter",
|
||||
// query: { path:'planet',sn:props.sn },
|
||||
// });
|
||||
loading.value = false;
|
||||
});
|
||||
// const pendingModal = Modal.info({
|
||||
// title: () => '导出任务进行中',
|
||||
@@ -123,7 +126,10 @@ const download = async () => {
|
||||
// })
|
||||
};
|
||||
const handleOk = () => {
|
||||
if (!loading.value) {
|
||||
loading.value = true;
|
||||
download();
|
||||
}
|
||||
};
|
||||
|
||||
const checkedList = ref(["is_title", "is_in", "is_number", "is_if", "is_logic"]);
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
<!-- 头部导航栏 -->
|
||||
<div class="header">
|
||||
<div @click="quitPreview" class="left">
|
||||
<i class="iconfont" v-show="isLogin"></i>
|
||||
<i class="iconfont" v-show="isLogin" style="font-size: 20px;"></i>
|
||||
<span v-show="isLogin">退出预览</span>
|
||||
</div>
|
||||
<a-spin :spinning="issueLoading">
|
||||
<div class="action-container">
|
||||
<div class="comment" @click="handleComment">
|
||||
<i class="iconfont icon-pinglun"></i>
|
||||
<span>评论</span>
|
||||
评论
|
||||
</div>
|
||||
<div class="download" style="margin-left: 20px" @click="handleDownload" v-show="isLogin">
|
||||
<i class="iconfont icon-daochu1"></i>
|
||||
@@ -35,7 +35,8 @@
|
||||
v-show="isLogin && questionsData.survey?.status === 0"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="iconfont icon-Path" style="font-size: 18px; margin-right: 6px"></i>
|
||||
<!-- <i class="iconfont icon-Path" style="font-size: 18px; margin-right: 6px"></i> -->
|
||||
<i class="iconfont icon-fabu3" style="margin-right: 6px"></i>
|
||||
</template>
|
||||
发布
|
||||
</a-button>
|
||||
@@ -70,13 +71,24 @@
|
||||
</div>
|
||||
<!-- 预览-pc -->
|
||||
<a-spin v-show="current === 'pc'" :spinning="loading">
|
||||
<questions-pc />
|
||||
<div v-if="questionsData.action?.code === 20013" class="action">
|
||||
<img src="@/assets/img/answer/actions/suspend.png" />
|
||||
<div class="msg">感谢您的反馈,期待您下次参与</div>
|
||||
</div>
|
||||
<questions-pc v-else />
|
||||
</a-spin>
|
||||
<!-- 预览-mob -->
|
||||
<!-- 手机模拟器 -->
|
||||
<phone v-show="current === 'mobile'" :title="title">
|
||||
<a-spin :spinning="loading">
|
||||
<questions-mob />
|
||||
<div
|
||||
v-if="questionsData.action?.code === 20013"
|
||||
class="action"
|
||||
>
|
||||
<img src="@/assets/img/answer/actions/suspend.png" />
|
||||
<div class="msg">感谢您的反馈,期待您下次参与</div>
|
||||
</div>
|
||||
<questions-mob v-else />
|
||||
</a-spin>
|
||||
</phone>
|
||||
<!-- 展开 -->
|
||||
@@ -189,6 +201,13 @@ export default defineComponent({
|
||||
);
|
||||
question.version = version;
|
||||
});
|
||||
// CBC配置
|
||||
data.answer.cbc_shelves_version?.forEach((version) => {
|
||||
const question = data.questions.find(
|
||||
(question) => question.question_index === version.question_index
|
||||
);
|
||||
question.version = version;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
@@ -201,9 +220,8 @@ export default defineComponent({
|
||||
}
|
||||
// 发布
|
||||
async function issue() {
|
||||
|
||||
var res = await canPlanetPublish(proxy.$route.query.sn);
|
||||
if(!res) return;
|
||||
if (!res) return;
|
||||
|
||||
issueLoading.value = true;
|
||||
try {
|
||||
@@ -336,6 +354,7 @@ export default defineComponent({
|
||||
cursor: pointer;
|
||||
.iconfont {
|
||||
font-size: 16px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
.link-address {
|
||||
@@ -362,9 +381,11 @@ export default defineComponent({
|
||||
.publish-btn {
|
||||
margin-left: 32px;
|
||||
width: 88px;
|
||||
height: 36px;
|
||||
height: 32px;
|
||||
line-height: 18px;
|
||||
border-radius: 6px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,7 +539,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.open:active {
|
||||
color: #1c6fff;
|
||||
color: #70b936;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,6 +552,27 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.action {
|
||||
padding-top: 99px;
|
||||
text-align: center;
|
||||
background-size: 224px 118px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: calc(100% - 10px) 24px;
|
||||
background-image: url("../../../assets/img/answer/pc-bg.png");
|
||||
|
||||
img {
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.msg {
|
||||
font-size: 16px;
|
||||
color: #70b936;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
:title="question.title + '问题评论'"
|
||||
/>
|
||||
</div>
|
||||
<!-- 试销 -->
|
||||
<div class="attribute" v-html="question.attribute"></div>
|
||||
<!-- 题型 -->
|
||||
<div class="question-options">
|
||||
<!-- 单选题 -->
|
||||
<div v-if="question.question_type === 1">
|
||||
@@ -246,6 +249,10 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.attribute {
|
||||
color: #70b936;
|
||||
}
|
||||
|
||||
.question-options {
|
||||
.flex {
|
||||
display: flex;
|
||||
@@ -265,9 +272,9 @@ export default defineComponent({
|
||||
flex-direction: column;
|
||||
|
||||
img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 10px auto;
|
||||
width: 50%;
|
||||
margin: 10px 0;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,6 +355,10 @@
|
||||
:title="question.stem"
|
||||
:config="question.config"
|
||||
v-model:answer="question.answer"
|
||||
:loading="loading"
|
||||
@previous="previous"
|
||||
@next="next"
|
||||
@toTop="toTop"
|
||||
isMobile
|
||||
:isAnswer="isAnswer"
|
||||
:questionIndex="question.question_index"
|
||||
@@ -429,7 +433,7 @@ export default defineComponent({ ...questions });
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
height: calc(100% - 50px);
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
||||
.progress-bar {
|
||||
@@ -461,7 +465,8 @@ export default defineComponent({ ...questions });
|
||||
}
|
||||
|
||||
.questions {
|
||||
padding: 20px;
|
||||
padding: 20px 20px 70px 20px;
|
||||
background-size: cover;
|
||||
|
||||
.question {
|
||||
margin-bottom: 48px;
|
||||
@@ -501,3 +506,21 @@ export default defineComponent({ ...questions });
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
// /*<=1024的设备*/
|
||||
// @media (max-width: 1024px){
|
||||
// html,
|
||||
// body,
|
||||
// * {font-size: 14px}
|
||||
// }
|
||||
/*<=600的设备*/
|
||||
@media (max-width: 600px) {
|
||||
html,
|
||||
body {
|
||||
& *:not(p, strong, em, p span) {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -351,6 +351,10 @@
|
||||
:title="question.stem"
|
||||
:config="question.config"
|
||||
v-model:answer="question.answer"
|
||||
:loading="loading"
|
||||
@previous="previous"
|
||||
@next="next"
|
||||
@toTop="toTop"
|
||||
:isAnswer="isAnswer"
|
||||
:questionIndex="question.question_index"
|
||||
:label="question.title"
|
||||
|
||||
@@ -196,7 +196,7 @@ export default defineComponent({
|
||||
question.error = isError ? "请输入中文" : "";
|
||||
break;
|
||||
case 5: // 邮箱
|
||||
isError = !/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(
|
||||
isError = !/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||
value
|
||||
);
|
||||
question.error = isError ? "请输入正确的email" : "";
|
||||
@@ -237,7 +237,7 @@ export default defineComponent({
|
||||
question.error = "请输入中文";
|
||||
break;
|
||||
case 5: // 邮箱
|
||||
if (!/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value))
|
||||
if (!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value))
|
||||
question.error = "请输入正确的email";
|
||||
break;
|
||||
case 6: // 手机号
|
||||
|
||||
393
src/views/Answer/components/js/logical.js
Normal file
@@ -0,0 +1,393 @@
|
||||
let answerQues = [];
|
||||
/**
|
||||
* 关联选项处理
|
||||
* @returns
|
||||
*/
|
||||
function optionHandle(questionIndex) {
|
||||
const optAndrelateList = [];
|
||||
const rowOptAndrelateList = [];
|
||||
const colOptAndrelateList = [];
|
||||
const classOptAndrelateList = [];
|
||||
const curQuesInfo = answerQues.find((ques) => ques.question_index === questionIndex);
|
||||
curQuesInfo.list.forEach((l) => {
|
||||
if (l.type === 0) {
|
||||
optAndrelateList.push(...l.options);
|
||||
} else if (l.type === 1) {
|
||||
rowOptAndrelateList.push(...l.options);
|
||||
} else if (l.type === 2) {
|
||||
colOptAndrelateList.push(...l.options);
|
||||
} else if (l.type === 3) {
|
||||
classOptAndrelateList.push(...l.options);
|
||||
}
|
||||
})
|
||||
const optList = optAndrelateList.map((opt, oIndex) => {
|
||||
opt.option_index = oIndex + 1;
|
||||
return opt
|
||||
})
|
||||
const rowOptList = rowOptAndrelateList.map((opt, oIndex) => {
|
||||
opt.option_index = oIndex + 1;
|
||||
return opt
|
||||
})
|
||||
const coloptList = colOptAndrelateList.map((opt, oIndex) => {
|
||||
opt.option_index = oIndex + 1;
|
||||
return opt
|
||||
})
|
||||
const classoptList = classOptAndrelateList.map((opt, oIndex) => {
|
||||
opt.option_index = oIndex + 1;
|
||||
return opt
|
||||
})
|
||||
return {
|
||||
optAndrelateList: optList,
|
||||
rowOptAndrelateList: rowOptList,
|
||||
colOptAndrelateList: coloptList,
|
||||
classOptAndrelateList: classoptList,
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 运算符转换处理
|
||||
* @param {*} operator
|
||||
* @returns
|
||||
*/
|
||||
function operatorHandle(operator) {
|
||||
let operatorStr = '';
|
||||
if (operator === '=' || operator === '是') {
|
||||
operatorStr = '==='
|
||||
} else if (operator === '≠' || operator === '不是') {
|
||||
operatorStr = '!=='
|
||||
} else if (operator === '≥') {
|
||||
operatorStr = '>='
|
||||
} else if (operator === '≤') {
|
||||
operatorStr = '<='
|
||||
} else if (operator === '包含') {
|
||||
operatorStr = 'includes'
|
||||
} else if (operator === '不包含') {
|
||||
operatorStr = '!includes'
|
||||
} else {
|
||||
operatorStr = operator;
|
||||
}
|
||||
return operatorStr
|
||||
}
|
||||
/**
|
||||
* 处理每种题型的不同逻辑
|
||||
* @param {*} answer 每个题里面的答题信息answer字段
|
||||
* @param {*} logChild 逻辑信息
|
||||
* @returns
|
||||
*/
|
||||
function quesHandle(answer, logChild) {
|
||||
// 单选
|
||||
const choiceHandle = () => {
|
||||
// 如果配置的逻辑中option_index为0,则代表没有配置选中项,此时不做校验
|
||||
if (logChild.option_index === 0) {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
Object.keys(answer).forEach((key) => {
|
||||
const { optAndrelateList } = optionHandle(logChild.question_index);
|
||||
// 拿到答题时选中的选项位置
|
||||
const postion = optAndrelateList.find((opt) => opt.option_key === key).option_index;
|
||||
// 拿到配置的逻辑里选项的位置
|
||||
const logPostion = optAndrelateList.find((opt) => opt.option_key === logChild.option_index).option_index;
|
||||
status = eval(`${postion}${operatorHandle(logChild.operator)}${logPostion}`);
|
||||
})
|
||||
return status;
|
||||
}
|
||||
// 多选
|
||||
const choiceCheckBoxHandle = () => {
|
||||
// 如果配置的逻辑中option_index为0,则代表没有配置选中项,此时不做校验
|
||||
if (logChild.option_index === 0 || logChild.is_select === '') {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
if (logChild.is_select) {
|
||||
// 如果配置的是选中, 则判断answer答案里面是否包含配置的选项
|
||||
status = Object.keys(answer).includes(logChild.option_index);
|
||||
} else {
|
||||
// 如果配置的是未选中, 则判断answer答案里面是否不包含配置的选项
|
||||
status = !Object.keys(answer).includes(logChild.option_index);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
// 填空题
|
||||
const inputHandle = () => {
|
||||
// 如果配置的逻辑中value为空,则代表没有配置输入值,此时不做校验
|
||||
if (!logChild.value || !logChild.operator) {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
if (['包含', '不包含'].includes(logChild.operator)) {
|
||||
// eval执行转换成字符串的语句(value.includes('222'))
|
||||
status = eval(`'${answer.value}'.${operatorHandle(logChild.operator)}('${logChild.value}')`);
|
||||
} else {
|
||||
status = eval(`${answer.value}${operatorHandle(logChild.operator)}${logChild.value}`);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
// 打分题
|
||||
const rateHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.option_index === 0 || !logChild.operator || !logChild.value) {
|
||||
return true;
|
||||
}
|
||||
return eval(`${answer[logChild.option_index]}${operatorHandle(logChild.operator)}${logChild.value}`);
|
||||
}
|
||||
// 矩阵单选题
|
||||
const matrixRadioHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.cell_index === 0 || logChild.row_index === 0 || !logChild.operator) {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
const { colOptAndrelateList } = optionHandle(logChild.question_index);
|
||||
// 先找到配置的逻辑中,列选项的位置
|
||||
const cellLogPostion = colOptAndrelateList.find((opt) => opt.option_key === logChild.cell_index).option_index;
|
||||
// 然后在找到答案里面行和配置的逻辑行一样的key
|
||||
const selectAnswer = Object.keys(answer).find((key) => key.split('_')[0] === logChild.row_index);
|
||||
// 再找到逻辑里面配置的行在答案里面选中的位置
|
||||
const cellPostion = colOptAndrelateList.find((opt) => opt.option_key === selectAnswer.split('_')[1]).option_index;
|
||||
// 两者进行对比
|
||||
status = eval(`${cellPostion}${operatorHandle(logChild.operator)}${cellLogPostion}`);
|
||||
return status
|
||||
}
|
||||
// 矩阵多选题
|
||||
const matrixCheckboxHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.cell_index === 0 || logChild.row_index === 0 || logChild.is_select === '') {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
const optionKey = `${logChild.row_index}_${logChild.cell_index}`;
|
||||
if (logChild.is_select) {
|
||||
// 如果配置的是选中, 则判断answer答案里面是否包含配置的选项
|
||||
status = Object.keys(answer).includes(optionKey);
|
||||
} else {
|
||||
// 如果配置的是未选中, 则判断answer答案里面是否不包含配置的选项
|
||||
status = !Object.keys(answer).includes(optionKey);
|
||||
}
|
||||
return status
|
||||
}
|
||||
// 矩阵打分题
|
||||
const matrixRateHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.cell_index === 0 || logChild.row_index === 0 || !logChild.operator || !logChild.value) {
|
||||
return true;
|
||||
}
|
||||
const optionKey = `${logChild.row_index}_${logChild.cell_index}`;
|
||||
return eval(`${answer[optionKey]}${operatorHandle(logChild.operator)}${logChild.value}`);
|
||||
}
|
||||
// 矩阵填空题
|
||||
const matrixInputHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.cell_index === 0 || logChild.row_index === 0 || !logChild.operator || !logChild.value) {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
const optionKey = `${logChild.row_index}_${logChild.cell_index}`;
|
||||
if (['包含', '不包含'].includes(logChild.operator)) {
|
||||
// eval执行转换成字符串的语句(value.includes('222'))
|
||||
status = eval(`'${answer[optionKey]}'.${operatorHandle(logChild.operator)}('${logChild.value}')`);
|
||||
} else {
|
||||
status = eval(`${answer[optionKey]}${operatorHandle(logChild.operator)}${logChild.value}`);
|
||||
}
|
||||
return status
|
||||
}
|
||||
// 图片单选
|
||||
const imgRadioHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.option_index === 0 || !logChild.operator) {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
Object.keys(answer).forEach((key) => {
|
||||
status = eval(`${key}${operatorHandle(logChild.operator)}${logChild.option_index}`);
|
||||
})
|
||||
return status;
|
||||
}
|
||||
// 图片多选
|
||||
const imgCheckBoxHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.option_index === 0 || logChild.is_select === '') {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
if (logChild.is_select) {
|
||||
// 如果配置的是选中, 则判断answer答案里面是否包含配置的选项
|
||||
status = Object.keys(answer).includes(logChild.option_index);
|
||||
} else {
|
||||
// 如果配置的是未选中, 则判断answer答案里面是否不包含配置的选项
|
||||
status = !Object.keys(answer).includes(logChild.option_index);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
// 分类题
|
||||
const classifyHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.row_index === 0 || logChild.cell_index === 0 || !logChild.operator) {
|
||||
return true;
|
||||
}
|
||||
const status = eval(`${answer[logChild.row_index]}${operatorHandle(logChild.operator)}${logChild.cell_index}`);
|
||||
return status
|
||||
}
|
||||
// 排序题
|
||||
const sortHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.option_index === 0 || !logChild.operator || logChild.location === '') {
|
||||
return true;
|
||||
}
|
||||
const status = eval(`${answer[logChild.option_index]}${operatorHandle(logChild.operator)}${logChild.location}`);
|
||||
return status;
|
||||
}
|
||||
// 恒定总和题
|
||||
const constantSumHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (logChild.option_index === 0 || !logChild.operator || !logChild.value) {
|
||||
return true;
|
||||
}
|
||||
return eval(`${answer[logChild.option_index]}${operatorHandle(logChild.operator)}${logChild.value}`);
|
||||
}
|
||||
// 日期时间题
|
||||
const dateTimeHandle = () => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (!logChild.date || !logChild.operator || !logChild.time) {
|
||||
return true;
|
||||
}
|
||||
let status = false;
|
||||
if (answer.date && answer.time) {
|
||||
// 如果同时配置了日期和时间
|
||||
status = answer.date === logChild.date && answer.time === logChild.time;
|
||||
} else if (answer.date) {
|
||||
// 如果只配置了日期
|
||||
status = answer.date === logChild.date;
|
||||
} else if (answer.time) {
|
||||
// 如果只配置了时间
|
||||
status = answer.time === logChild.time;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
// psm
|
||||
const psmHandle = (config) => {
|
||||
// 如果配置的逻辑中参数为空,则代表没有配置逻辑匹配值,此时不做校验
|
||||
if (!logChild.value) {
|
||||
return true;
|
||||
}
|
||||
const answerIndex = answer[5];
|
||||
const status = String(config.price_gradient[answerIndex - 1]) === logChild.value;
|
||||
return status;
|
||||
}
|
||||
return {
|
||||
choiceHandle,
|
||||
choiceCheckBoxHandle,
|
||||
inputHandle,
|
||||
rateHandle,
|
||||
matrixRadioHandle,
|
||||
matrixCheckboxHandle,
|
||||
matrixRateHandle,
|
||||
matrixInputHandle,
|
||||
imgRadioHandle,
|
||||
imgCheckBoxHandle,
|
||||
classifyHandle,
|
||||
sortHandle,
|
||||
constantSumHandle,
|
||||
dateTimeHandle,
|
||||
psmHandle,
|
||||
}
|
||||
}
|
||||
function getConditionStatus(logChild) {
|
||||
let resultStatus = [];
|
||||
//拿到当前题的答案
|
||||
const answer = answerQues.find((ques) => ques.question_index === logChild.question_index).answer;
|
||||
//拿到当前题的config信息
|
||||
const config = answerQues.find((ques) => ques.question_index === logChild.question_index).config;
|
||||
// 如果逻辑是不为空则为作答
|
||||
if (logChild.is_answer) {
|
||||
// 每个题型有不同的判断逻辑
|
||||
const quesHandles = quesHandle(answer, logChild);
|
||||
let quesStatus = false;
|
||||
if (answer) {
|
||||
try {
|
||||
switch (logChild.question_type) {
|
||||
case 1:
|
||||
quesStatus = quesHandles.choiceHandle();
|
||||
break;
|
||||
case 2:
|
||||
quesStatus = quesHandles.choiceCheckBoxHandle();
|
||||
break;
|
||||
case 4:
|
||||
quesStatus = quesHandles.inputHandle();
|
||||
break;
|
||||
case 5:
|
||||
quesStatus = quesHandles.rateHandle();
|
||||
break;
|
||||
case 7:
|
||||
quesStatus = quesHandles.dateTimeHandle();
|
||||
break;
|
||||
case 8:
|
||||
quesStatus = quesHandles.matrixInputHandle();
|
||||
break;
|
||||
case 9:
|
||||
quesStatus = quesHandles.matrixRadioHandle();
|
||||
break;
|
||||
case 10:
|
||||
quesStatus = quesHandles.matrixCheckboxHandle();
|
||||
break;
|
||||
case 11:
|
||||
quesStatus = quesHandles.matrixRateHandle();
|
||||
break;
|
||||
case 13:
|
||||
quesStatus = quesHandles.imgRadioHandle();
|
||||
break;
|
||||
case 14:
|
||||
quesStatus = quesHandles.imgCheckBoxHandle();
|
||||
break;
|
||||
case 15:
|
||||
quesStatus = quesHandles.classifyHandle();
|
||||
break;
|
||||
case 16:
|
||||
quesStatus = quesHandles.sortHandle();
|
||||
break;
|
||||
case 17:
|
||||
quesStatus = quesHandles.constantSumHandle();
|
||||
break;
|
||||
case 101:
|
||||
quesStatus = quesHandles.psmHandle(config);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
quesStatus = false;
|
||||
}
|
||||
}
|
||||
resultStatus.push(...[answer ? true : false, quesStatus])
|
||||
} else {
|
||||
//如果为空则为不作答,判断当前题是否包含answer字段,如果有则已经作答,返回false。
|
||||
resultStatus.push(answer ? false : true)
|
||||
}
|
||||
return eval(resultStatus.join('&&'));
|
||||
}
|
||||
function getlogicStatus(questionData) {
|
||||
answerQues = JSON.parse(JSON.stringify(questionData.questions));
|
||||
const logics = JSON.parse(JSON.stringify(questionData.logics));
|
||||
logics.forEach((logs) => {
|
||||
// 如果选择的是always,则直接返回true;
|
||||
if (logs.logic.length === 1 && logs.logic[0].logic === 'always') {
|
||||
logs.logicStatus = true;
|
||||
} else {
|
||||
// 处理每条逻辑(if或者and或者or)的结果
|
||||
// 将上一步获取到的每条逻辑状态整合起来,统一判断
|
||||
let statusStr = '';
|
||||
logs.logic.forEach((logChild, condIndex) => {
|
||||
const conditionStatus = getConditionStatus(logChild);
|
||||
if (condIndex !== logs.logic.length - 1) {
|
||||
statusStr = statusStr + conditionStatus + (logChild.logic === 'or' ? '||' : '&&');
|
||||
} else {
|
||||
statusStr = statusStr + conditionStatus;
|
||||
}
|
||||
})
|
||||
logs.logicStatus = eval(statusStr);
|
||||
}
|
||||
})
|
||||
console.log('logics', logics);
|
||||
return logics;
|
||||
}
|
||||
export default getlogicStatus
|
||||
115
src/views/Answer/components/js/mock.js
Normal file
@@ -0,0 +1,115 @@
|
||||
import getlogicStatus from "./logical";
|
||||
|
||||
// 更新code
|
||||
function updateCode(action, skipQuestionIndex) {
|
||||
if (skipQuestionIndex === -1) {
|
||||
action.code = 20011;
|
||||
action.msg = "成功结束页";
|
||||
} else if (skipQuestionIndex === -2) {
|
||||
action.code = 20004;
|
||||
action.msg = "甄别结束页";
|
||||
} else if (skipQuestionIndex === -3) {
|
||||
action.code = 20016;
|
||||
action.msg = "配额超限页";
|
||||
}
|
||||
}
|
||||
// 更新分页pages(题后跳转逻辑)
|
||||
function updatePagesAfter(pages, logic, jumpTo, page) {
|
||||
const { question_index, skip_question_index } = logic;
|
||||
const startIndex = pages.findIndex(
|
||||
(page) => page.findIndex((questionIndex) => questionIndex === question_index) !== -1
|
||||
);
|
||||
const endIndex = pages.findIndex(
|
||||
(page) => page.findIndex((questionIndex) => questionIndex === skip_question_index) !== -1
|
||||
);
|
||||
if (endIndex !== -1) {
|
||||
const endQuestionIndex = pages[endIndex].findIndex(
|
||||
(questionIndex) => questionIndex === skip_question_index
|
||||
);
|
||||
pages[endIndex].splice(0, endQuestionIndex);
|
||||
// 跳转到某页
|
||||
if (startIndex > endIndex && startIndex < page) {
|
||||
jumpTo.question_index = question_index;
|
||||
return (jumpTo.question_page = endIndex + 1);
|
||||
}
|
||||
pages.splice(startIndex + 1, endIndex - startIndex - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新分页pages(题前设置逻辑)
|
||||
function updatePagesBefore(pages, hideQuestionIndex) {
|
||||
const pagesIndex = pages.findIndex(
|
||||
(page) => page.findIndex((questionIndex) => questionIndex === hideQuestionIndex) !== -1
|
||||
);
|
||||
if (pages[pagesIndex].length === 1) {
|
||||
pages.splice(pagesIndex, 1);
|
||||
} else {
|
||||
const pageIndex = pages[pagesIndex].findIndex(
|
||||
(questionIndex) => questionIndex === hideQuestionIndex
|
||||
);
|
||||
pages[pagesIndex].splice(pageIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 自动填写
|
||||
function autoFill(answerAutoFill, logic) {
|
||||
answerAutoFill.push({
|
||||
answer: logic.autofill.answer_insert,
|
||||
question_index: logic.question_index,
|
||||
question_type: logic.autofill.question_type,
|
||||
});
|
||||
}
|
||||
|
||||
// 选项隐藏逻辑
|
||||
function updateOptionHidden(hide_options, logic) {
|
||||
const { question_index, hide_option_index } = logic;
|
||||
hide_options.question_index = question_index;
|
||||
hide_options.option_key.push(...hide_option_index.map((opt) => opt.option_key));
|
||||
}
|
||||
|
||||
// 模拟答题接口
|
||||
export default function answerMock(questionsData, page) {
|
||||
const data = {
|
||||
action: { code: 20010, msg: "答案已记录" },
|
||||
jump_to: {},
|
||||
hide_options: {
|
||||
option_key: [],
|
||||
},
|
||||
answer_info_autofill: [],
|
||||
pages: JSON.parse(JSON.stringify(questionsData.answer.pages_init)),
|
||||
};
|
||||
const logics = getlogicStatus(questionsData);
|
||||
logics.forEach((logic) => {
|
||||
if (logic.logicStatus && logic.skip_type === 0) {
|
||||
// 题后跳转逻辑
|
||||
if (logic.skip_question_index < 0) {
|
||||
return updateCode(data.action, logic.skip_question_index);
|
||||
}
|
||||
updatePagesAfter(data.pages, logic, data.jump_to, page);
|
||||
} else if (logic.logicStatus && logic.skip_type === 1) {
|
||||
// 题前设置逻辑
|
||||
updatePagesBefore(data.pages, logic.question_index);
|
||||
} else if (logic.logicStatus && logic.skip_type === 3) {
|
||||
// 自动填写逻辑
|
||||
autoFill(data.answer_info_autofill, logic);
|
||||
} else if (logic.logicStatus && logic.skip_type === 4) {
|
||||
// 选项隐藏逻辑
|
||||
updateOptionHidden(data.hide_options, logic);
|
||||
}
|
||||
});
|
||||
// 更新问卷状态
|
||||
if (page === data.pages.length) {
|
||||
data.action.code = 20011;
|
||||
data.action.msg = "成功结束页";
|
||||
}
|
||||
// 拒绝知情同意书
|
||||
const refuseIndex = questionsData.questions.findIndex(
|
||||
(question) => question.question_type === 23 && question.answer?.value === "2"
|
||||
);
|
||||
if (refuseIndex !== -1) {
|
||||
data.action.code = 20013;
|
||||
data.action.msg = "不同意继续参与,已结束作答";
|
||||
}
|
||||
// 返回数据
|
||||
return data;
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import QPSM from "../../questions/high/QPSM.vue";
|
||||
import QKANO from "../../questions/high/QKANO.vue";
|
||||
import QBPTO from "../../questions/high/QBPTO.vue";
|
||||
import QMXD from "../../questions/high/QMXD.vue";
|
||||
import answerMock from "./mock";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -79,6 +80,7 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 是否模板预览
|
||||
isTemplate: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@@ -113,11 +115,11 @@ export default defineComponent({
|
||||
});
|
||||
// 是否显示分页器
|
||||
const showPage = computed(() => {
|
||||
return [104, 105, 201].includes(questions.value[0]?.question_type) ? false : true;
|
||||
return [102, 104, 105, 201].includes(questions.value[0]?.question_type) ? false : true;
|
||||
});
|
||||
// 答题
|
||||
async function answer(callback, callbackBeforePage) {
|
||||
if ((questions.value.length || !questionsData.value.questions.length) && props.isAnswer) {
|
||||
if ((questions.value.length || !questionsData.value.questions.length) && !props.isTemplate) {
|
||||
// 表单验证(当前页)
|
||||
const errors = questions.value.filter((question) => {
|
||||
const { config, answer, question_type: questionType } = question;
|
||||
@@ -204,7 +206,8 @@ export default defineComponent({
|
||||
question.error = isError ? "请输入中文" : "";
|
||||
break;
|
||||
case 5: // 邮箱
|
||||
isError = !/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(
|
||||
isError =
|
||||
!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||
value
|
||||
);
|
||||
question.error = isError ? "请输入正确的email" : "";
|
||||
@@ -245,7 +248,11 @@ export default defineComponent({
|
||||
question.error = "请输入中文";
|
||||
break;
|
||||
case 5: // 邮箱
|
||||
if (!/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value))
|
||||
if (
|
||||
!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
|
||||
value
|
||||
)
|
||||
)
|
||||
question.error = "请输入正确的email";
|
||||
break;
|
||||
case 6: // 手机号
|
||||
@@ -278,6 +285,27 @@ export default defineComponent({
|
||||
return isError;
|
||||
});
|
||||
if (!errors.length) {
|
||||
// 判断是作答还是预览
|
||||
if (!props.isAnswer) {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 模拟接口
|
||||
const data = answerMock(questionsData.value, page.value);
|
||||
console.log("模拟作答数据", data);
|
||||
// 更新答案
|
||||
updateAnswer(data.answer_info_autofill);
|
||||
// 更新分页数组
|
||||
questionsData.value.answer.pages = data.pages;
|
||||
// 选项隐藏
|
||||
hideOptions(data.hide_options);
|
||||
// 更新action
|
||||
questionsData.value.action = data.action;
|
||||
callback(data.jump_to);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
return (loading.value = false);
|
||||
}
|
||||
// 表单验证通过,开始答题
|
||||
const questionsAnswer = questions.value.map((question) => ({
|
||||
question_index: question.question_index,
|
||||
@@ -325,9 +353,9 @@ export default defineComponent({
|
||||
questionsData.value.action = data.action;
|
||||
callback(data.jump_to);
|
||||
// 写入关联选项缓存
|
||||
if (props.isAnswer) {
|
||||
if (props.isAnswer && questionsData.value.survey.is_breakpoint) {
|
||||
if (data.action.code === 20010) {
|
||||
const questionsCache = JSON.parse(localStorage.getItem(questionsCache)) || {};
|
||||
const questionsCache = JSON.parse(localStorage.getItem("questionsCache")) || {};
|
||||
questionsCache[proxy.$route.query.sn] = questionsData.value.questions;
|
||||
localStorage.setItem("questionsCache", JSON.stringify(questionsCache));
|
||||
} else {
|
||||
@@ -360,7 +388,7 @@ export default defineComponent({
|
||||
// 下一页
|
||||
async function next(callbackBeforePage) {
|
||||
answer((jumpPage) => {
|
||||
if (jumpPage) {
|
||||
if (jumpPage?.question_page) {
|
||||
page.value = jumpPage.question_page;
|
||||
} else {
|
||||
page.value += 1;
|
||||
|
||||
@@ -12,7 +12,12 @@
|
||||
<a-button v-if="!config.is_hide" key="back" :loading="loading" @click="refuse">{{
|
||||
config.disagree_button_text
|
||||
}}</a-button>
|
||||
<a-button key="submit" type="primary" :loading="loading" :disabled="time" @click="agree"
|
||||
<a-button
|
||||
key="submit"
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
:disabled="time ? true : false"
|
||||
@click="agree"
|
||||
>{{ config.agree_button_text }}<span v-if="time" class="time">({{ time }}s)</span></a-button
|
||||
>
|
||||
</template>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/>
|
||||
<Remark :title="label + '标题评论'" :type="1" v-if="!isAnswer" />
|
||||
</div>
|
||||
<div v-if="showDesc" class="desc-part">
|
||||
<div v-if="showDesc" class="desc-part" :class="isMobile ? 'm-desc-part' : ''">
|
||||
<rich-text
|
||||
isPreview
|
||||
:nodes="desc"
|
||||
@@ -100,6 +100,10 @@ export default defineComponent({
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.m-desc-part {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
@@ -116,6 +120,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.m-desc {
|
||||
flex: 1;
|
||||
margin-top: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
<div class="checkbox-group">
|
||||
<div
|
||||
class="checkbox"
|
||||
:class="isMobile || config.each_number === 1 ? '' : 'side'"
|
||||
:style="isMobile ? 'width:100%' : `width: calc(100% / ${config.each_number})`"
|
||||
v-for="option in options"
|
||||
:key="option.option_key"
|
||||
:style="isMobile ? 'width:100%' : `width: calc(100% / ${config.each_number})`"
|
||||
>
|
||||
<a-image width="100%" :src="option.option_config.image_url[0]" />
|
||||
<div class="check-option">
|
||||
@@ -97,8 +98,6 @@ export default defineComponent({
|
||||
padding-right: 32px;
|
||||
|
||||
:deep(img) {
|
||||
max-width: 176px;
|
||||
height: 176px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 24px;
|
||||
object-fit: cover;
|
||||
@@ -114,5 +113,12 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.side {
|
||||
:deep(img) {
|
||||
height: 176px;
|
||||
max-width: 176px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
<div class="radio-group">
|
||||
<div
|
||||
class="radio"
|
||||
:class="isMobile || config.each_number === 1 ? '' : 'side'"
|
||||
:style="isMobile ? 'width:100%' : `width: calc(100% / ${config.each_number})`"
|
||||
v-for="option in options"
|
||||
:key="option.option_key"
|
||||
:style="isMobile ? 'width:100%' : `width: calc(100% / ${config.each_number})`"
|
||||
>
|
||||
<a-image width="100%" :src="option.option_config.image_url[0]" />
|
||||
<div class="radio-option">
|
||||
@@ -85,8 +86,6 @@ export default defineComponent({
|
||||
padding-right: 32px;
|
||||
|
||||
:deep(img) {
|
||||
max-width: 176px;
|
||||
height: 176px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 24px;
|
||||
object-fit: cover;
|
||||
@@ -98,5 +97,12 @@ export default defineComponent({
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.side {
|
||||
:deep(img) {
|
||||
height: 176px;
|
||||
max-width: 176px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,20 +2,15 @@
|
||||
<div class="imgs" :class="isMobile ? 'mob-imgs' : ''">
|
||||
<div
|
||||
class="img-show"
|
||||
:class="isMobile || config.each_number === 1 ? '' : 'side'"
|
||||
:style="isMobile ? 'width:100%' : `width: calc(100% / ${config.each_number})`"
|
||||
v-for="option in options"
|
||||
:key="option.option_key"
|
||||
:style="
|
||||
isMobile ? 'width:100%' : `width: calc(100% / ${config.each_number})`
|
||||
"
|
||||
>
|
||||
<!-- 闪照 -->
|
||||
<div v-if="config.countdown_type && config.countdown_time">
|
||||
<div v-if="config?.countdown_type && config?.countdown_time">
|
||||
<!-- 点击查看图片 -->
|
||||
<div
|
||||
v-if="option.preview"
|
||||
class="thumbnail see"
|
||||
@click="previewImg(option)"
|
||||
>
|
||||
<div v-if="option.preview" class="thumbnail see" @click="previewImg(option)">
|
||||
<img src="@/assets/img/answer/see-img.png" alt="" />
|
||||
<div class="text">点击查看图片</div>
|
||||
<div class="desc">查看超时后自动焚毁</div>
|
||||
@@ -31,9 +26,7 @@
|
||||
<!-- 图片名 -->
|
||||
<div v-html="option.option" />
|
||||
<!-- 倒计时 -->
|
||||
<div v-if="previewTime" class="preview-time">
|
||||
{{ previewTime }} 秒后自动关闭
|
||||
</div>
|
||||
<div v-if="previewTime" class="preview-time">{{ previewTime }} 秒后自动关闭</div>
|
||||
<!-- 预览 -->
|
||||
<a-image
|
||||
v-if="previewTime"
|
||||
@@ -127,9 +120,18 @@ export default defineComponent({
|
||||
:deep(.ant-image-img) {
|
||||
width: 100%;
|
||||
margin: 24px 0;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.side {
|
||||
:deep(.ant-image-img) {
|
||||
height: 176px;
|
||||
max-width: 176px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
|
||||
@@ -130,13 +130,14 @@ export default defineComponent({
|
||||
if (!val) {
|
||||
return message.error(`请输入数字`);
|
||||
}
|
||||
if (val && val < props.config.min) {
|
||||
|
||||
if (!isNaN(val) && Number(val) < Number(props.config.min)) {
|
||||
changeValue({ target: { value: "" } });
|
||||
message.error(`请输入大于等于${props.config.min}的数字`);
|
||||
}
|
||||
if (val && val < props.config.min) {
|
||||
if (!isNaN(val) && Number(val) > Number(props.config.max)) {
|
||||
changeValue({ target: { value: "" } });
|
||||
message.error(`请输入大于等于${props.config.min}的数字`);
|
||||
message.error(`请输入大于等于${props.config.max}的数字`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -206,10 +206,11 @@ export default defineComponent({
|
||||
|
||||
.td {
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
padding: 10px 16px;
|
||||
border-left: 1px dashed #d9d9d9;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.td:first-child {
|
||||
@@ -226,6 +227,7 @@ export default defineComponent({
|
||||
.mob-matrix {
|
||||
.table .tr .td {
|
||||
min-width: 120px;
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -215,10 +215,12 @@ export default defineComponent({
|
||||
.tr {
|
||||
.td {
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
width: 150px;
|
||||
padding: 10px 16px;
|
||||
border-left: 1px dashed #d9d9d9;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.td:first-child {
|
||||
@@ -233,7 +235,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
:deep(.ant-input) {
|
||||
width: 132px;
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dfe0e3;
|
||||
@@ -242,6 +244,7 @@ export default defineComponent({
|
||||
.mob-matrix {
|
||||
.table .tr .td {
|
||||
min-width: 120px;
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -101,7 +101,6 @@ export default {
|
||||
border-color: #fff !important;
|
||||
}
|
||||
:deep(*) {
|
||||
color: #fff !important;
|
||||
}
|
||||
td{
|
||||
padding: 5px;
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
<template>
|
||||
<AnswerViewerMatrix :isMobile="isMobile" :config="config" :stem="stem" :answerSurveySn="answerSurveySn" :answerSn="answerSn" :question="question" :row="row" :col="col">
|
||||
<AnswerViewerMatrix
|
||||
:isMobile="isMobile"
|
||||
:config="config"
|
||||
:stem="stem"
|
||||
:answerSurveySn="answerSurveySn"
|
||||
:answerSn="answerSn"
|
||||
:question="question"
|
||||
:row="row"
|
||||
:col="col"
|
||||
>
|
||||
<div class="matrix scrollbar" :class="isMobile ? 'mob-matrix' : ''">
|
||||
<table class="table">
|
||||
<!-- 表头 -->
|
||||
@@ -47,20 +56,20 @@
|
||||
</table>
|
||||
</div>
|
||||
<template v-slot:page="{ rowIndex }">
|
||||
<MatrixRadioPage :row="row" :col="col" :rowIndex="rowIndex"/>
|
||||
<MatrixRadioPage :row="row" :col="col" :rowIndex="rowIndex" />
|
||||
</template>
|
||||
</AnswerViewerMatrix>
|
||||
</AnswerViewerMatrix>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, watch } from "vue";
|
||||
import AnswerViewerMatrix from "../components/AnswerViewerMatrix";
|
||||
import MatrixRadioPage from "./MatrixRadioPage"
|
||||
import MatrixRadioPage from "./MatrixRadioPage";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
AnswerViewerMatrix,
|
||||
MatrixRadioPage
|
||||
MatrixRadioPage,
|
||||
},
|
||||
props: {
|
||||
// 题干
|
||||
@@ -96,15 +105,15 @@ export default defineComponent({
|
||||
// 样本SN
|
||||
answerSn: {
|
||||
type: String,
|
||||
default: ""
|
||||
default: "",
|
||||
},
|
||||
answerSurveySn: {
|
||||
type: String,
|
||||
default: ""
|
||||
default: "",
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
@@ -219,10 +228,11 @@ export default defineComponent({
|
||||
|
||||
.td {
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
padding: 10px 16px;
|
||||
border-left: 1px dashed #d9d9d9;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.td:first-child {
|
||||
@@ -239,6 +249,7 @@ export default defineComponent({
|
||||
.mob-matrix {
|
||||
.table .tr .td {
|
||||
min-width: 120px;
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
182
src/views/Answer/questions/QMatrix/MatrixRadioKano.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<div class="matrix scrollbar" :class="isMobile ? 'mob-matrix' : ''">
|
||||
<table class="table">
|
||||
<a-radio-group
|
||||
v-model:value="rowItem.value"
|
||||
@change="updateAnswer"
|
||||
:disabled="disabled"
|
||||
v-for="(rowItem, rowIndex) in row"
|
||||
:key="rowItem.option_key"
|
||||
>
|
||||
<!-- 标题 -->
|
||||
<div class="title" :class="'answer-background10'">
|
||||
<div class="answer-color" v-html="rowItem.option" />
|
||||
</div>
|
||||
<!-- 表头 -->
|
||||
<tr class="tr">
|
||||
<td class="td scrollbar" v-for="colItem in col" :key="colItem.option_key">
|
||||
<div class="answer-color" v-html="colItem.option" />
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 选择 -->
|
||||
<tr class="tr">
|
||||
<td class="td" v-for="(colItem, colIndex) in col" :key="colItem.option_key">
|
||||
<a-radio
|
||||
:value="colItem.option_key"
|
||||
:disabled="isDisabled(rowItem.option_key, colItem.option_key, rowIndex, colIndex)"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</a-radio-group>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, watch } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
// 列表
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
// 配置
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
// 答案
|
||||
answer: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
// 是否禁用
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 是否移动端
|
||||
isMobile: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
// 选项
|
||||
const row = ref([]); // 行标签
|
||||
const col = ref([]); // 列标签
|
||||
|
||||
// 初始化
|
||||
function init() {
|
||||
props.list.forEach((list) => {
|
||||
if (list.type === 1) {
|
||||
row.value = [...row.value, ...list.options];
|
||||
} else if (list.type === 2) {
|
||||
col.value = [...col.value, ...list.options];
|
||||
}
|
||||
});
|
||||
if (props.answer) {
|
||||
const obj = {};
|
||||
Object.keys(props.answer).forEach((key) => {
|
||||
obj[key.split("_")[0]] = key.split("_")[1];
|
||||
});
|
||||
row.value.forEach((rowItem) => {
|
||||
rowItem.value = obj[rowItem.option_key];
|
||||
});
|
||||
updateAnswer();
|
||||
}
|
||||
}
|
||||
init();
|
||||
|
||||
// 选择回调
|
||||
function updateAnswer() {
|
||||
const answer = {};
|
||||
const index = row.value.findIndex((rowItem) => {
|
||||
if (rowItem.value) {
|
||||
answer[`${rowItem.option_key}_${rowItem.value}`] = 1;
|
||||
}
|
||||
return !rowItem.value;
|
||||
});
|
||||
// 更新答案
|
||||
if (index === -1 || !props.config?.is_required) {
|
||||
context.emit("update:answer", answer);
|
||||
} else {
|
||||
context.emit("update:answer", null);
|
||||
}
|
||||
}
|
||||
|
||||
// 是否禁用选项
|
||||
function isDisabled(rowKey, colKey, rowIndex, colIndex) {
|
||||
// 快捷评价
|
||||
if (props.config.is_quick === 0) {
|
||||
if ((rowIndex === 0 && colIndex < 2) || (rowIndex === 1 && colIndex > 2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const index = (props.config?.disabled || []).findIndex(
|
||||
(item) => item.row_key === rowKey && item.cell_key === colKey
|
||||
);
|
||||
return index === -1 ? false : true;
|
||||
}
|
||||
|
||||
return { row, col, updateAnswer, isDisabled };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.matrix {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.table {
|
||||
border-radius: 4px 4px 0 0;
|
||||
|
||||
.title {
|
||||
padding: 12px 40px;
|
||||
border-radius: 4px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.tr {
|
||||
display: table-row;
|
||||
|
||||
.td {
|
||||
padding: 10px 48px 0;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mob-matrix {
|
||||
.table {
|
||||
.title {
|
||||
padding: 12px 20px;
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tr {
|
||||
display: flex;
|
||||
.td {
|
||||
flex: 1;
|
||||
padding: 10px 0 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-radio-group {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-radio-disabled) {
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
@@ -54,6 +54,5 @@ export default {
|
||||
border-color: #fff !important;
|
||||
}
|
||||
:deep(*) {
|
||||
color: #fff !important;
|
||||
}
|
||||
</style>
|
||||
@@ -202,6 +202,10 @@ export default defineComponent({
|
||||
border-left: 1px dashed #d9d9d9;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
.answer-color {
|
||||
white-space: normal !important;
|
||||
}
|
||||
}
|
||||
|
||||
.td:first-child {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div @touchstart="handleSign">
|
||||
<signature :url="url" @save="save" :disabled="disabled" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -43,7 +45,14 @@ export default defineComponent({
|
||||
message.success("上传成功");
|
||||
}
|
||||
|
||||
return { url, save };
|
||||
// 签名题开始触摸事件
|
||||
function handleSign() {
|
||||
console.log('签名题开始触摸事件');
|
||||
const activeElement = document.activeElement;
|
||||
activeElement.blur();
|
||||
}
|
||||
|
||||
return { url, save, handleSign };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -57,11 +57,26 @@ export default defineComponent({
|
||||
// 选项
|
||||
const options = ref([]);
|
||||
|
||||
// js加法
|
||||
function addNum(arg1, arg2) {
|
||||
(arg1 = arg1.toString()), (arg2 = arg2.toString());
|
||||
var arg1Arr = arg1.split("."),
|
||||
arg2Arr = arg2.split("."),
|
||||
d1 = arg1Arr.length == 2 ? arg1Arr[1] : "",
|
||||
d2 = arg2Arr.length == 2 ? arg2Arr[1] : "";
|
||||
var maxLen = Math.max(d1.length, d2.length);
|
||||
var m = Math.pow(10, maxLen);
|
||||
var result = Number(((arg1 * m + arg2 * m) / m).toFixed(maxLen));
|
||||
var d = arguments[2];
|
||||
return typeof d === "number" ? Number(result.toFixed(d)) : result;
|
||||
}
|
||||
|
||||
// 计算总和
|
||||
const sum = computed(() => {
|
||||
let a = 0;
|
||||
options.value.forEach((option) => {
|
||||
a += option.value * 1 || 0;
|
||||
// a += option.value * 1 || 0;
|
||||
a = addNum(a, option.value * 1 || 0);
|
||||
});
|
||||
return a;
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
:type="3"
|
||||
:questionIndex="questionIndex"
|
||||
v-if="!isAnswer"
|
||||
style="margin-bottom: 22px;"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="error && questionType <= 100" class="error">{{ error }}</div>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 错误 -->
|
||||
<div v-if="error" class="error">{{ error }}</div>
|
||||
<!-- 题 -->
|
||||
<div class="kano" v-for="item in questions" :key="item">
|
||||
<div class="kano" v-show="index + 1 === page" v-for="(item, index) in questions" :key="index">
|
||||
<div class="question-wrapper">
|
||||
<div class="title answer-color" v-html="item.stem" />
|
||||
<Remark
|
||||
@@ -12,23 +13,52 @@
|
||||
v-if="!isAnswer"
|
||||
/>
|
||||
</div>
|
||||
<matrix-radio
|
||||
<matrix-radio-kano
|
||||
:list="item.list"
|
||||
:config="config"
|
||||
:disabled="disabled"
|
||||
v-model:answer="item.answer"
|
||||
@update:answer="changeValue"
|
||||
:isMobile="isMobile"
|
||||
/>
|
||||
</div>
|
||||
<!-- 分页-mob -->
|
||||
<div v-if="isMobile" class="footer">
|
||||
<pfe-pagination
|
||||
:min="0"
|
||||
:page="page"
|
||||
:pages="questions.length + 1"
|
||||
submitText="下一页"
|
||||
:loading="loading"
|
||||
showPrevious
|
||||
@previous="previous"
|
||||
@next="next"
|
||||
isMobile
|
||||
/>
|
||||
</div>
|
||||
<!-- 分页-pc -->
|
||||
<pfe-pagination
|
||||
v-else
|
||||
:min="0"
|
||||
:page="page"
|
||||
:pages="questions.length + 1"
|
||||
submitText="下一页"
|
||||
:loading="loading"
|
||||
showPrevious
|
||||
@previous="previous"
|
||||
@next="next"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref } from "vue";
|
||||
import MatrixRadio from "../QMatrix/MatrixRadio.vue";
|
||||
import PfePagination from "@/components/PfePagination.vue";
|
||||
import MatrixRadioKano from "../QMatrix/MatrixRadioKano.vue";
|
||||
import Remark from "@/views/Answer/components/Remark";
|
||||
import { message } from "ant-design-vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: { MatrixRadio, Remark },
|
||||
components: { PfePagination, MatrixRadioKano, Remark },
|
||||
props: {
|
||||
// 错误
|
||||
error: {
|
||||
@@ -60,6 +90,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 是否作答模式
|
||||
isAnswer: {
|
||||
type: Boolean,
|
||||
@@ -76,6 +110,7 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
const page = ref(1);
|
||||
const list = ref([]); // 矩阵列表
|
||||
const questions = ref([]); // 问题列表
|
||||
|
||||
@@ -95,7 +130,7 @@ export default defineComponent({
|
||||
init();
|
||||
|
||||
// 选择回调
|
||||
function changeValue() {
|
||||
function updateAnswer() {
|
||||
// 更新答案
|
||||
const answer = questions.value.map((question, task) =>
|
||||
question.answer
|
||||
@@ -109,6 +144,31 @@ export default defineComponent({
|
||||
if (index === -1) {
|
||||
context.emit("update:answer", answer);
|
||||
}
|
||||
context.emit("next");
|
||||
}
|
||||
|
||||
// 上一页
|
||||
function previous() {
|
||||
if (page.value === 1) {
|
||||
return context.emit("previous");
|
||||
}
|
||||
page.value -= 1;
|
||||
context.emit("toTop");
|
||||
}
|
||||
|
||||
// 下一页
|
||||
function next() {
|
||||
// 当前页没有选择
|
||||
if (props.config.is_required && !questions.value[page.value - 1].answer) {
|
||||
return message.error("请选择");
|
||||
}
|
||||
// 最后一页
|
||||
if (page.value === questions.value.length) {
|
||||
return updateAnswer();
|
||||
}
|
||||
// 下一页
|
||||
page.value += 1;
|
||||
context.emit("toTop");
|
||||
}
|
||||
|
||||
// 设置list
|
||||
@@ -155,7 +215,7 @@ export default defineComponent({
|
||||
];
|
||||
}
|
||||
|
||||
return { list, questions, changeValue };
|
||||
return { page, list, questions, updateAnswer, previous, next };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -166,6 +226,7 @@ export default defineComponent({
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 12px;
|
||||
color: #ff374f;
|
||||
@@ -177,7 +238,19 @@ export default defineComponent({
|
||||
margin-bottom: 40px;
|
||||
|
||||
.title {
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 72px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
// left: 0;
|
||||
// bottom: 0;
|
||||
// width: 100%;
|
||||
// position: absolute;
|
||||
// padding: 20px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -320,12 +320,12 @@ export default defineComponent({
|
||||
// 下一页
|
||||
function next() {
|
||||
// 作答模式下不进行选择判断
|
||||
if (!props.isAnswer) {
|
||||
if (page.value === pages.value) {
|
||||
return context.emit("next");
|
||||
}
|
||||
return (page.value += 1);
|
||||
}
|
||||
// if (!props.isAnswer) {
|
||||
// if (page.value === pages.value) {
|
||||
// return context.emit("next");
|
||||
// }
|
||||
// return (page.value += 1);
|
||||
// }
|
||||
// 当前页答案
|
||||
const currentOptions = allOptions.value[page.value - 1];
|
||||
if (currentOptions.findIndex((option) => option.value === "b") === -1) {
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
<i class="iconfont"></i>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<Remark :title="label+'问题评论'" :type="3" :questionIndex="questionIndex" v-if="!isAnswer"/>
|
||||
|
||||
<Remark :title="label + '问题评论'" :type="3" :questionIndex="questionIndex" v-if="!isAnswer" />
|
||||
</div>
|
||||
<!-- 错误 -->
|
||||
<div v-if="error" class="error">{{ error }}</div>
|
||||
@@ -77,11 +76,8 @@
|
||||
<!-- 问题 -->
|
||||
<div class="title answer-color">{{ title }}_{{ index + 1 }}{{ item.title }}</div>
|
||||
<!-- 打分 -->
|
||||
<div :style="`width: ${(Object.keys(marks).length / 15) * 1000}px;padding-left:14px;`">
|
||||
<a-slider
|
||||
:min="config.min"
|
||||
:max="config.max"
|
||||
:step="null"
|
||||
<div>
|
||||
<slider
|
||||
:marks="marks"
|
||||
v-model:value="item.value"
|
||||
@afterChange="changeValue($event, item, index)"
|
||||
@@ -97,6 +93,7 @@
|
||||
import { message } from "ant-design-vue";
|
||||
import { computed, defineComponent, ref } from "vue";
|
||||
import Remark from "@/views/Answer/components/Remark";
|
||||
import Slider from "@/components/Slider";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -142,17 +139,17 @@ export default defineComponent({
|
||||
// 题号
|
||||
questionIndex: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
default: "",
|
||||
},
|
||||
// 题干
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
default: "",
|
||||
},
|
||||
components: { Remark },
|
||||
},
|
||||
components: { Remark, Slider },
|
||||
setup(props, context) {
|
||||
const marks = ref({}); // 刻度标记
|
||||
const marks = ref([]); // 刻度标记
|
||||
const questions = ref([]); // 问题列表
|
||||
|
||||
const valueArr = computed(() =>
|
||||
@@ -162,14 +159,15 @@ export default defineComponent({
|
||||
// 初始化
|
||||
function init() {
|
||||
// 设置刻度标记
|
||||
props.config.price_gradient.forEach((item) => {
|
||||
marks.value[item] = item;
|
||||
});
|
||||
// props.config.price_gradient.forEach((item) => {
|
||||
// marks.value[item] = item;
|
||||
// });
|
||||
marks.value = props.config.price_gradient.map((gradient) => gradient * 1);
|
||||
// 设置问题列表
|
||||
questions.value = props.config.text_map.map((question) => ({ title: question }));
|
||||
if (props.answer) {
|
||||
questions.value.forEach((question, index) => {
|
||||
question.value = props.config.price_gradient[props.answer[index + 1] - 1];
|
||||
question.value = marks.value[props.answer[index + 1] - 1];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -177,6 +175,9 @@ export default defineComponent({
|
||||
|
||||
// 滑动回调
|
||||
function changeValue(value, item, i) {
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
// 判断
|
||||
if (i === 4) {
|
||||
if (value > questions.value[1].value || value < questions.value[2].value) {
|
||||
@@ -209,9 +210,7 @@ export default defineComponent({
|
||||
// 更新答案
|
||||
const answer = {};
|
||||
const index = questions.value.findIndex((question, index) => {
|
||||
const priceIndex = props.config.price_gradient.findIndex(
|
||||
(price) => price === question.value
|
||||
);
|
||||
const priceIndex = marks.value.findIndex((price) => price === question.value);
|
||||
answer[index + 1] = priceIndex + 1;
|
||||
return question.value === undefined;
|
||||
});
|
||||
@@ -241,7 +240,7 @@ export default defineComponent({
|
||||
justify-content: space-between;
|
||||
|
||||
.iconfont {
|
||||
color: #3461ff;
|
||||
color: #70b936;
|
||||
cursor: pointer;
|
||||
margin-left: 12px;
|
||||
}
|
||||
@@ -331,7 +330,7 @@ export default defineComponent({
|
||||
|
||||
.slider-group {
|
||||
.slider-box {
|
||||
overflow: auto;
|
||||
overflow-x: auto;
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
|
||||
@@ -7,17 +7,12 @@
|
||||
* @FilePath: /planet-front-end/src/views/DataAnalyse/bptoAnalog/components/bptoContentMid.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="bptoConInfoTop">
|
||||
<div class="bptoConInfoTop">
|
||||
<div class="bptoConInfoLeft">
|
||||
<a-checkbox
|
||||
:disabled="props.isFull"
|
||||
v-model:checked="itemCheck"
|
||||
:indeterminate="indeterminate"
|
||||
@change="onCheckAllChange"
|
||||
>
|
||||
{{itemData?.title}}
|
||||
<a-checkbox :disabled="props.isFull" v-model:checked="itemCheck" :indeterminate="indeterminate" @change="onCheckAllChange">
|
||||
{{ itemData?.title }}
|
||||
</a-checkbox>
|
||||
<p>({{itemData?.question_Q}}:需求曲线模拟/单目标)</p>
|
||||
<p>({{ itemData?.question_Q }}:需求曲线模拟/单目标)</p>
|
||||
</div>
|
||||
<div class="bptoConInfoRight">
|
||||
<a-radio-group v-model:value="cardType" size="small" button-style="solid" @change="changeRadio">
|
||||
@@ -31,9 +26,9 @@
|
||||
</div>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item :disabled="itemData.status!=2" @click="getDetil">详情</a-menu-item>
|
||||
<a-menu-item :disabled="itemData.status!=2" @click="download">下载</a-menu-item>
|
||||
<a-menu-item v-if="itemData.status!=2" @click="againOper">重新计算</a-menu-item>
|
||||
<a-menu-item :disabled="itemData.status != 2" @click="getDetil">详情</a-menu-item>
|
||||
<a-menu-item :disabled="itemData.status != 2" @click="download">下载</a-menu-item>
|
||||
<a-menu-item v-if="itemData.status != 2" @click="againOper">重新计算</a-menu-item>
|
||||
<a-menu-item @click="resetName">重命名</a-menu-item>
|
||||
<a-menu-item class="delClass" @click="delNow">删除</a-menu-item>
|
||||
</a-menu>
|
||||
@@ -41,74 +36,74 @@
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bptoConInfoMid">
|
||||
</div>
|
||||
<div class="bptoConInfoMid">
|
||||
<!-- 这是一个echart图表 -->
|
||||
<component class="bptoMidChart" v-if="itemData.status==2" ref="bptoMidChart" :is="chart" :chartLine="itemData?.linear_chart_data_json" :chartColumn="itemData?.column_chart_data_json" :lineHeader="itemData.target_gradient_json" :cardType="cardType" :avgLine="itemData?.price_avg_price" />
|
||||
<div class="noChart" v-if="itemData.status!=2">
|
||||
<component class="bptoMidChart" v-if="itemData.status == 2" ref="bptoMidChart" :is="chart" :chartLine="itemData?.linear_chart_data_json" :chartColumn="itemData?.column_chart_data_json" :lineHeader="itemData.target_gradient_json" :cardType="cardType" :avgLine="itemData?.price_avg_price" />
|
||||
<div class="noChart" v-if="itemData.status != 2">
|
||||
<img :src="require('@/assets/img/kano.gif')" />
|
||||
<p class="countDownBoxDesc">正在进行市场模拟中…请您稍后~</p>
|
||||
</div>
|
||||
<!-- 这是table -->
|
||||
<div class="bptoConInfoTable">
|
||||
<a-table :dataSource="itemDataTableData" :columns="itemDataTableColumn" :transformCellText="({ text, column, record, index }) => text||'--.--%'" :pagination="false" :scroll="{ x: (150*itemDataTableColumn.length), y:170 }" >
|
||||
<a-table :dataSource="itemDataTableData" :columns="itemDataTableColumn" :transformCellText="({ text, column, record, index }) => text || '--.--%'" :pagination="false" :scroll="{ x: 150 * itemDataTableColumn.length, y: 170 }">
|
||||
<template #count="{ record }">
|
||||
<div v-if="itemData.status!=2">--.--%</div>
|
||||
<div v-else>{{record.count}}</div>
|
||||
<div v-if="itemData.status != 2">--.--%</div>
|
||||
<div v-else>{{ record.count }}</div>
|
||||
</template>
|
||||
<template #head_fir="{ record }">
|
||||
<div class="headFir" v-html="record.head_fir"></div>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive,defineProps,defineEmits,watch,onMounted,nextTick } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import { EllipsisOutlined,ExpandOutlined } from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import chart from './chart.vue';
|
||||
const router = useRouter();
|
||||
import { ref, reactive, defineProps, defineEmits, watch, onMounted, nextTick } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { EllipsisOutlined, ExpandOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import chart from './chart.vue'
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
// url参数
|
||||
const query = router.currentRoute.value.query
|
||||
// 点击全选按钮
|
||||
const emit = defineEmits(["checkboxClick","delItem"]);
|
||||
const emit = defineEmits(['checkboxClick', 'delItem'])
|
||||
const props = defineProps({
|
||||
// 判断当前是否显示
|
||||
isFull:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
isFull: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
itemData:{
|
||||
type:Object,
|
||||
default:()=>{}
|
||||
itemData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
index:{
|
||||
type:Number,
|
||||
default:-1
|
||||
index: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
pagination:{
|
||||
type:Object,
|
||||
default:()=>{}
|
||||
},
|
||||
allCheckState:{
|
||||
type:Object,
|
||||
default:()=>{}
|
||||
pagination: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
allCheckState: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
})
|
||||
// 修改格式
|
||||
const changePerInfo = (data)=>{
|
||||
const changePerInfo = (data) => {
|
||||
const newData = JSON.parse(JSON.stringify(data))
|
||||
let newArr = []
|
||||
newData.map(el=>{
|
||||
newData.map((el) => {
|
||||
const retData = {}
|
||||
for (const key in el) {
|
||||
if(typeof el[key]=='number'){
|
||||
retData[key] = el[key]+'%'
|
||||
}else{
|
||||
if (typeof el[key] == 'number') {
|
||||
retData[key] = el[key] + '%'
|
||||
} else {
|
||||
retData[key] = el[key]
|
||||
}
|
||||
}
|
||||
@@ -119,166 +114,181 @@ const changePerInfo = (data)=>{
|
||||
// 是否选中
|
||||
const itemCheck = ref(false)
|
||||
// 图表类型
|
||||
const cardType= ref(0)
|
||||
const cardType = ref(0)
|
||||
const bptoMidChart = ref(null)
|
||||
// 接受分页参数
|
||||
watch(()=>cardType.value,nval=>{
|
||||
watch(
|
||||
() => cardType.value,
|
||||
(nval) => {
|
||||
// 单目标
|
||||
if(nval===0){
|
||||
if (nval === 0) {
|
||||
itemDataTableData.value = changePerInfo(props.itemData.one.dataSource)
|
||||
itemDataTableColumn.value = [...props.itemData.one.columns]
|
||||
}
|
||||
// 下降差
|
||||
if(nval===1){
|
||||
if (nval === 1) {
|
||||
itemDataTableData.value = changePerInfo(props.itemData.decline.dataSource)
|
||||
itemDataTableColumn.value = [...props.itemData.decline.columns]
|
||||
}
|
||||
})
|
||||
watch(() => store?.state?.bptoData?.fullScreen, nVal => {
|
||||
if(nVal){
|
||||
console.log('全屏显示');
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => store?.state?.bptoData?.fullScreen,
|
||||
(nVal) => {
|
||||
if (nVal) {
|
||||
console.log('全屏显示')
|
||||
cardType.value = 0
|
||||
nextTick(()=>{
|
||||
nextTick(() => {
|
||||
bptoMidChart.value.initCharts(0)
|
||||
bptoMidChart.value.chartResize()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
// table数据
|
||||
const itemDataTableData = ref([])
|
||||
// table表头
|
||||
const itemDataTableColumn = ref([])
|
||||
// 全屏时候翻页
|
||||
watch(()=>props.itemData,()=>{
|
||||
watch(
|
||||
() => props.itemData,
|
||||
() => {
|
||||
itemDataTableData.value = changePerInfo(props.itemData.one.dataSource)
|
||||
itemDataTableColumn.value = [...props.itemData.one.columns]
|
||||
cardType.value = 0
|
||||
nextTick(()=>{
|
||||
if(bptoMidChart.value){
|
||||
nextTick(() => {
|
||||
if (bptoMidChart.value) {
|
||||
bptoMidChart.value.initCharts(0)
|
||||
bptoMidChart.value.chartResize()
|
||||
}
|
||||
})
|
||||
}, {
|
||||
deep:true,
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
}
|
||||
)
|
||||
// 接受分页参数
|
||||
watch(props.pagination,nval=>{
|
||||
console.log(nval.value);
|
||||
watch(props.pagination, (nval) => {
|
||||
console.log(nval.value)
|
||||
})
|
||||
// 接受全选状态
|
||||
watch(()=>props.allCheckState,nval=>{
|
||||
console.log(nval.value);
|
||||
dataList.value.map(el=>el.checked=nval.value.checked)
|
||||
})
|
||||
watch(
|
||||
() => props.allCheckState,
|
||||
(nval) => {
|
||||
console.log(nval.value)
|
||||
dataList.value.map((el) => (el.checked = nval.value.checked))
|
||||
}
|
||||
)
|
||||
|
||||
// 如果点击一个触发全选的indeterminate
|
||||
const onCheckAllChange=async e=>{
|
||||
const onCheckAllChange = async (e) => {
|
||||
const item = store?.state?.bptoData?.bptoItem
|
||||
const checkInfo = itemCheck.value
|
||||
item[props.index].checked =checkInfo
|
||||
console.log('当前选中',checkInfo,props.index,item);
|
||||
await store.dispatch('bptoData/saveBptoItem',item)
|
||||
item[props.index].checked = checkInfo
|
||||
console.log('当前选中', checkInfo, props.index, item)
|
||||
await store.dispatch('bptoData/saveBptoItem', item)
|
||||
}
|
||||
// 监听全选状态
|
||||
watch(()=>store?.state?.bptoData?.bptoItem,(nval)=>{
|
||||
if(props.index>-1&&nval[props.index])itemCheck.value = nval[props.index].checked
|
||||
}, {
|
||||
deep:true,
|
||||
watch(
|
||||
() => store?.state?.bptoData?.bptoItem,
|
||||
(nval) => {
|
||||
if (props.index > -1 && nval[props.index]) itemCheck.value = nval[props.index].checked
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
}
|
||||
)
|
||||
// 查看详情
|
||||
const getDetil = ()=>{
|
||||
const getDetil = () => {
|
||||
const id = props.itemData.id
|
||||
console.log('查看详情',id);
|
||||
store.dispatch('bptoData/changeSceneId',id)
|
||||
store.dispatch('bptoData/changeLookAll',true)
|
||||
console.log('查看详情', id)
|
||||
store.dispatch('bptoData/changeSceneId', id)
|
||||
store.dispatch('bptoData/changeLookAll', true)
|
||||
}
|
||||
// 下载
|
||||
const download = async()=>{
|
||||
console.log('下载');
|
||||
const download = async () => {
|
||||
console.log('下载')
|
||||
try {
|
||||
const subData = {
|
||||
scene_id:props.itemData.id
|
||||
scene_id: props.itemData.id
|
||||
}
|
||||
const {xlsx}= await store.dispatch('bptoData/getSceneDownload',subData)
|
||||
window.open(xlsx.download_url,"_blank");
|
||||
const { xlsx } = await store.dispatch('bptoData/getSceneDownload', subData)
|
||||
window.open(xlsx.download_url, '_blank')
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
// 重新计算
|
||||
const againOper = async()=>{
|
||||
const againOper = async () => {
|
||||
try {
|
||||
const subData = {
|
||||
scene_id:props.itemData.id
|
||||
scene_id: props.itemData.id
|
||||
}
|
||||
await store.dispatch('bptoData/putRecalculate',subData)
|
||||
await store.dispatch('bptoData/putRecalculate', subData)
|
||||
message.success('计算成功')
|
||||
emit('delItem')
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
// 重命名
|
||||
const resetName = ()=>{
|
||||
console.log('重命名');
|
||||
const resetName = () => {
|
||||
console.log('重命名')
|
||||
const id = props.itemData.id
|
||||
store.dispatch('bptoData/changeSceneId',id)
|
||||
store.dispatch('bptoData/changeFullScreenIndex',props.index)
|
||||
store.dispatch('bptoData/changeResetName',true)
|
||||
store.dispatch('bptoData/changeSceneId', id)
|
||||
store.dispatch('bptoData/changeFullScreenIndex', props.index)
|
||||
store.dispatch('bptoData/changeResetName', true)
|
||||
}
|
||||
// 删除
|
||||
const delNow = ()=>{
|
||||
console.log('删除');
|
||||
const delNow = () => {
|
||||
console.log('删除')
|
||||
delScene()
|
||||
|
||||
}
|
||||
const delScene =async ()=>{
|
||||
const delScene = async () => {
|
||||
try {
|
||||
const subData = {
|
||||
scene_id:props.itemData.id,
|
||||
title:props.itemData.title,
|
||||
scene_id: props.itemData.id,
|
||||
title: props.itemData.title
|
||||
}
|
||||
await store.dispatch('bptoData/delScene',subData)
|
||||
await store.dispatch('bptoData/delScene', subData)
|
||||
emit('delItem')
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
// 翻页监听数据变化
|
||||
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.bptoConInfoTop{
|
||||
<style scoped lang="scss">
|
||||
.bptoConInfoTop {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
.bptoConInfoLeft{
|
||||
.bptoConInfoLeft {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: auto;
|
||||
overflow: hidden;
|
||||
&:deep(.ant-checkbox-wrapper){
|
||||
&:deep(.ant-checkbox-wrapper) {
|
||||
white-space: nowrap;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
}
|
||||
>p{
|
||||
> p {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #8C8C8C;
|
||||
color: #8c8c8c;
|
||||
}
|
||||
}
|
||||
.bptoConInfoRight{
|
||||
.bptoConInfoRight {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
.icon{
|
||||
.icon {
|
||||
cursor: pointer;
|
||||
margin-left: 16px;
|
||||
width: 22px;
|
||||
@@ -291,34 +301,34 @@ const delScene =async ()=>{
|
||||
}
|
||||
}
|
||||
}
|
||||
.bptoConInfoMid{
|
||||
flex:1;
|
||||
.bptoConInfoMid {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 16px;
|
||||
.bptoMidChart{
|
||||
.bptoMidChart {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.bptoConInfoTable{
|
||||
.bptoConInfoTable {
|
||||
flex: 1;
|
||||
// overflow: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.delFont{
|
||||
.delFont {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
.noChart{
|
||||
.noChart {
|
||||
width: 100%;
|
||||
// height: 220px;
|
||||
background: #f5f5f5;
|
||||
margin-bottom: 40px;
|
||||
margin-top: 20px;
|
||||
>img{
|
||||
> img {
|
||||
width: 100%;
|
||||
}
|
||||
.countDownBoxDesc{
|
||||
.countDownBoxDesc {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $yili-default-color;
|
||||
@@ -328,14 +338,14 @@ const delScene =async ()=>{
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
::v-deep .delClass{
|
||||
color: #FF3939 !important;
|
||||
::v-deep .delClass {
|
||||
color: #ff3939 !important;
|
||||
}
|
||||
::v-deep .headFir{
|
||||
*{
|
||||
::v-deep .headFir {
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
img{
|
||||
img {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="custom-head-cell">
|
||||
<div class="image-question custom-table-head-img" v-if="[12, 13, 14].includes(question_type)" v-html="content"></div>
|
||||
<a-popover v-else>
|
||||
<template #content>
|
||||
<a-tooltip placement="topLeft" v-else>
|
||||
<template #title>
|
||||
<div class="custom-head-preview" v-html="content"></div>
|
||||
</template>
|
||||
<div class="custom-head-main">
|
||||
<!-- 下载题型-->
|
||||
<div class="file-question" v-if="question_type === 18">
|
||||
<div class="file-question" v-if="question_type === 18" :style="{width:data.width + 'px'}">
|
||||
<div class="label">{{ content }}</div>
|
||||
<a-button size="mini" @click="download">下载全部附件</a-button>
|
||||
</div>
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<div class="common-text" v-else>{{ content }}</div>
|
||||
</div>
|
||||
</a-popover>
|
||||
</a-tooltip>
|
||||
<!-- 下载中心 -->
|
||||
<DownloadCenter v-model:visible="downloadVisible" v-if="downloadVisible"></DownloadCenter>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
<template>
|
||||
<a-table
|
||||
:row-selection="rowSelection"
|
||||
:rowKey="rowKey"
|
||||
:type="type"
|
||||
:columns="customHeaders"
|
||||
:dataSource="data"
|
||||
:pagination="pagination"
|
||||
:scroll="{ x: 1200 }"
|
||||
@change="handlePageChange"
|
||||
>
|
||||
<template
|
||||
v-for="col in tableHeaders"
|
||||
:key="col.dataIndex"
|
||||
#[col.dataIndex]="{ record, text }"
|
||||
>
|
||||
<template v-if="col.dataIndex !== 'operation'">
|
||||
<a-table :row-selection="rowSelection" :rowKey="rowKey" :type="type" :columns="customHeaders" :dataSource="data" :pagination="pagination" :scroll="{ x: 1200 }" @change="handlePageChange">
|
||||
<template v-for="col in tableHeaders" :key="col.dataIndex" #[col.dataIndex]="{ record, text }">
|
||||
<!-- 作答类型 -->
|
||||
<!-- <template v-if="col.dataIndex === 'type'">
|
||||
<slot name="type" v-bind:record="record">
|
||||
<span class="show-type show-type-da">作答</span>
|
||||
</slot>
|
||||
</template> -->
|
||||
<template v-if="col.dataIndex === 'is_mark'">
|
||||
<slot name="is_mark" v-bind:record="record">
|
||||
<i v-if="record.is_mark == 1" class="icon iconfont show-sign curror" @click="hideSign(record)"></i>
|
||||
<i v-else class="icon iconfont hide-sign curror" @click="showSign(record)"></i>
|
||||
</slot>
|
||||
</template>
|
||||
<template v-else-if="col.dataIndex === 'mark_des'">
|
||||
<slot name="mark_des" v-bind:record="record" v-if="record.is_mark == 1">
|
||||
<render-table-title :title="text">
|
||||
<span class="show-mark_des"> {{ record.mark_des }}</span>
|
||||
</render-table-title>
|
||||
</slot>
|
||||
</template>
|
||||
<template v-else-if="col.dataIndex !== 'operation'">
|
||||
<render-table-title :title="text"></render-table-title>
|
||||
</template>
|
||||
|
||||
<div v-else>
|
||||
<slot name="operation" v-bind:record="record"></slot>
|
||||
</div>
|
||||
@@ -25,15 +32,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineComponent, ref, toRefs, watchEffect, useAttrs,onUnmounted, reactive, useSlots,defineProps } from "vue";
|
||||
import { useStore } from 'vuex';
|
||||
import usePagination from "@views/DataAnalyse/composables/usePagination";
|
||||
import useGeneratorTableColumns from "@views/DataAnalyse/composables/use-generator-table-columns";
|
||||
import useCustomHeaderTitle from "@views/DataAnalyse/composables/useCustomHeaderTitle";
|
||||
import RenderTableTitle from "@views/DataAnalyse/components/RenderTableTitle"
|
||||
import { computed } from "@vue/reactivity";
|
||||
import { watch } from "fs";
|
||||
import * as cheerio from 'cheerio';
|
||||
import { defineComponent, ref, toRefs, watchEffect, useAttrs, onUnmounted, reactive, useSlots, defineProps, createVNode, resolveComponent, h } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import usePagination from '@views/DataAnalyse/composables/usePagination'
|
||||
import useGeneratorTableColumns from '@views/DataAnalyse/composables/use-generator-table-columns'
|
||||
import useCustomHeaderTitle from '@views/DataAnalyse/composables/useCustomHeaderTitle'
|
||||
import RenderTableTitle from '@views/DataAnalyse/components/RenderTableTitle'
|
||||
import { computed } from '@vue/reactivity'
|
||||
import { watch } from 'fs'
|
||||
import * as cheerio from 'cheerio'
|
||||
import { Input, Modal } from 'ant-design-vue'
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: Number
|
||||
@@ -87,21 +96,20 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
}
|
||||
)
|
||||
const emit = defineEmits(['change','select'])
|
||||
})
|
||||
const emit = defineEmits(['change', 'select'])
|
||||
const store = useStore()
|
||||
const data = ref([]);
|
||||
const columns = ref(null);
|
||||
const { perPage: per_page, total,page,rowKey } = toRefs(props);
|
||||
const { pagination } = usePagination(per_page, total,page);
|
||||
const { tableHeaders } = useGeneratorTableColumns(columns);
|
||||
const { customHeaders } = useCustomHeaderTitle(tableHeaders, props.sn, props.params);
|
||||
console.log('tableHeaders',tableHeaders);
|
||||
const data = ref([])
|
||||
const columns = ref(null)
|
||||
const { perPage: per_page, total, page, rowKey } = toRefs(props)
|
||||
const { pagination } = usePagination(per_page, total, page)
|
||||
const { tableHeaders } = useGeneratorTableColumns(columns)
|
||||
const { customHeaders } = useCustomHeaderTitle(tableHeaders, props.sn, props.params)
|
||||
console.log('tableHeaders', tableHeaders)
|
||||
// 页码&分页条数,改变时候触发
|
||||
const handlePageChange =(data)=> {
|
||||
const handlePageChange = (data) => {
|
||||
const { pageSize, current } = data
|
||||
store.dispatch('dataFilter/selectKeys',[])
|
||||
store.dispatch('dataFilter/selectKeys', [])
|
||||
emit('select', [])
|
||||
emit('change', {
|
||||
pageSize,
|
||||
@@ -109,35 +117,80 @@ const handlePageChange =(data)=> {
|
||||
})
|
||||
}
|
||||
//
|
||||
const selectKeys = computed(()=>store.state.dataFilter.selectKeys)
|
||||
const selectList = computed(()=>store.state.dataFilter.selectKeys)
|
||||
const selectKeys = computed(() => store.state.dataFilter.selectKeys)
|
||||
const selectIds = computed(() => store.state.dataFilter.answer_sn)
|
||||
const selectList = computed(() => store.state.dataFilter.selectKeys)
|
||||
const rowSelection = {
|
||||
selectedRowKeys:selectList,
|
||||
selectedRowKeys: selectList,
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
console.log(selectedRowKeys,selectedRows);
|
||||
const keys = selectedRows.map(el=>el.newSn)
|
||||
store.dispatch('dataFilter/selectKeys',keys)
|
||||
},
|
||||
};
|
||||
onUnmounted(()=>{
|
||||
store.dispatch('dataFilter/selectKeys',[])
|
||||
console.log(selectedRowKeys, selectedRows)
|
||||
const keys = selectedRows.map((el) => el.newSn)
|
||||
const ids = selectedRows.map((el) => el.answer_sn)
|
||||
store.dispatch('dataFilter/selectKeys', keys)
|
||||
store.dispatch('dataFilter/selectIds', ids)
|
||||
}
|
||||
}
|
||||
onUnmounted(() => {
|
||||
store.dispatch('dataFilter/selectIds', [])
|
||||
store.dispatch('dataFilter/selectKeys', [])
|
||||
})
|
||||
watchEffect(() => {
|
||||
const tableSource =JSON.parse(JSON.stringify(props.tableSource))
|
||||
const tableSource = JSON.parse(JSON.stringify(props.tableSource))
|
||||
// 去除标签
|
||||
tableSource.map(el=>{
|
||||
tableSource.map((el) => {
|
||||
for (const key in el) {
|
||||
const $ = cheerio.load(el[key]+'')
|
||||
console.log('el[key]',el[key]);
|
||||
if((el[key]+'').indexOf('<img')>-1){
|
||||
const $ = cheerio.load(el[key] + '')
|
||||
if ((el[key] + '').indexOf('<img') > -1) {
|
||||
el[key] = $.html()
|
||||
}else{
|
||||
} else {
|
||||
el[key] = $.text()
|
||||
}
|
||||
}
|
||||
})
|
||||
data.value = tableSource
|
||||
columns.value = props.tableColumns;
|
||||
columns.value = props.tableColumns
|
||||
})
|
||||
|
||||
});
|
||||
const showSign = (item) => {
|
||||
emit('sign', [item], true)
|
||||
}
|
||||
const hideSign = (item) => {
|
||||
emit('sign', [item], false)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.show-type {
|
||||
display: block;
|
||||
width: auto;
|
||||
padding: 0 5px;
|
||||
width: 42px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
opacity: 1;
|
||||
font-size: 12px;
|
||||
font-family: PingFang SC-常规体, PingFang SC;
|
||||
font-weight: normal;
|
||||
}
|
||||
.show-type-da {
|
||||
background: rgba(50, 176, 246, 0.2);
|
||||
color: #32b0f6;
|
||||
}
|
||||
.show-sign {
|
||||
color: #70b936;
|
||||
}
|
||||
.curror {
|
||||
cursor: pointer;
|
||||
}
|
||||
.hide-sign {
|
||||
cursor: pointer;
|
||||
color: #bfbfbf;
|
||||
}
|
||||
.show-mark_des {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<div class="custom-table-head-img-wrapper" v-html="title"></div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<a-popover>
|
||||
<template #content>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
<div class="diagram-preview" v-html="title"></div>
|
||||
</template>
|
||||
<div class="common-text">{{ title }}</div>
|
||||
</a-popover>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -38,7 +38,7 @@ export default defineComponent({
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
top: 42%;
|
||||
top: 48%;
|
||||
display: block;
|
||||
content: '';
|
||||
width: 4px;
|
||||
|
||||
9
src/views/DataAnalyse/components/diagram/api.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/* 同步数据 */
|
||||
export function syncProductTest(sn) {
|
||||
return request({
|
||||
url: `/console/surveys/${sn}/sync_product_test`,
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class='content'>
|
||||
<div class="content">
|
||||
<!-- <a-select
|
||||
:getPopupContainer="triggerNode=>triggerNode.parentNode"
|
||||
class="searchSelect operChd"
|
||||
@@ -11,35 +11,36 @@
|
||||
<img class="suffix-icon" :src="require('@/assets/img/select-arrow-down.png')" alt="">
|
||||
</template>
|
||||
</a-select> -->
|
||||
<a-dropdown class="searchSelect operChd" :getPopupContainer="triggerNode=>triggerNode.parentNode">
|
||||
<a-dropdown class="searchSelect operChd" :getPopupContainer="(triggerNode) => triggerNode.parentNode">
|
||||
<template #overlay>
|
||||
<a-menu @click="opChange">
|
||||
<a-menu-item v-for="(item) in opList" :key="item.value">
|
||||
{{item.label}}
|
||||
<a-menu-item v-for="item in opList" :key="item.value">
|
||||
{{ item.label }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button class="custom-button">
|
||||
批量操作
|
||||
<img class="suffix-icon" :src="require('@/assets/img/select-arrow-down.png')" alt="">
|
||||
<img class="suffix-icon" :src="require('@/assets/img/select-arrow-down.png')" alt="" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
<a-button class="operChd custom-button" @click="emit('cleanAllBtn',true)">清空数据</a-button>
|
||||
<a-button class="operChd custom-button" @click="emit('cleanAllBtn', true)">清空数据</a-button>
|
||||
<!-- <a-button class="operChd" @click="handleDownload">下载全部答卷</a-button> -->
|
||||
<a-dropdown class="searchSelect operChd" :getPopupContainer="triggerNode=>triggerNode.parentNode">
|
||||
<!-- <a-dropdown class="searchSelect operChd" :getPopupContainer="(triggerNode) => triggerNode.parentNode">
|
||||
<template #overlay>
|
||||
<a-menu @click="dataChange">
|
||||
<a-menu-item v-for="(item) in dataList" :key="item.value">
|
||||
{{item.label}}
|
||||
<a-menu-item v-for="item in dataList" :key="item.value">
|
||||
{{ item.label }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button type="primary">
|
||||
<a-button type="primary" class="custom-button">
|
||||
数据管理
|
||||
<!-- <img class="suffix-icon" :src="require('@/assets/img/select-arrow-down.png')" alt=""> -->
|
||||
<img class="suffix-icon" :src="require('@/assets/img/select-arrow-down.png')" alt="">
|
||||
<CaretDownOutlined class="suffix-icon" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
</a-dropdown> -->
|
||||
<a-button type="primary" class="operChd custom-button" @click="dataChange({ key: 2 })">全量数据导出</a-button>
|
||||
<!-- <a-select
|
||||
:getPopupContainer="triggerNode=>triggerNode.parentNode"
|
||||
class="searchSelect operChd"
|
||||
@@ -50,138 +51,163 @@
|
||||
<img class="suffix-icon" :src="require('@/assets/img/select-arrow-down.png')" alt="">
|
||||
</template>
|
||||
</a-select> -->
|
||||
<a-button type="primary" class="operChd" @click="configVisible=true">列表配置</a-button>
|
||||
<a-button type="primary" class="operChd custom-button" @click="noData">无效样本处理</a-button>
|
||||
<a-button type="primary" class="operChd custom-button" @click="configVisible = true">列表配置</a-button>
|
||||
<!-- 同步数据 -->
|
||||
<a-tooltip :overlayStyle="{'max-width': 'none'}">
|
||||
<template v-slot:title>
|
||||
产品测试模块会同步该列表数据并作统计展示
|
||||
</template>
|
||||
<a-button
|
||||
v-if="template_type === 100 || template_type === 101"
|
||||
type="primary"
|
||||
class="operChd custom-button"
|
||||
@click="syncData"
|
||||
:loading="syncDataLoading"
|
||||
>
|
||||
{{ other_send_status ? "更新数据" : "同步数据" }}
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<!-- 配置 -->
|
||||
<ColumnConfig
|
||||
v-model:visible="configVisible"
|
||||
:data="answer_columns"
|
||||
:sn="sn"
|
||||
@ok="handleConfig"
|
||||
/>
|
||||
<ColumnConfig v-model:visible="configVisible" :data="answer_columns" :sn="sn" @ok="handleConfig" />
|
||||
<!-- 导出 -->
|
||||
<DownloadData
|
||||
v-model:visible="downloadVisible"
|
||||
:params="queryState"
|
||||
:sn="sn"
|
||||
:sns="selectedSns"
|
||||
@ok="handleDownload"
|
||||
/>
|
||||
<DownloadData v-model:visible="downloadVisible" :params="queryState" :sn="sn" :sns="selectedSns" @ok="handleDownload" />
|
||||
<!-- 下载中心 -->
|
||||
<DownloadCenter v-model:visible="downloadCenterVisible" v-if="downloadCenterVisible"></DownloadCenter>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, toRefs, reactive,defineProps,watch,onMounted , computed ,nextTick} from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
import { message } from 'ant-design-vue';
|
||||
import ColumnConfig from "./../../particulars/components/ColumnConfig";
|
||||
import DownloadData from "./../../particulars/components/DownloadData";
|
||||
import { addDownloadCenter } from "@/api/download.js";
|
||||
import DownloadCenter from "@/views/DownloadCenter/index.vue"
|
||||
import { CaretDownOutlined } from '@ant-design/icons-vue';
|
||||
import { Modal } from 'ant-design-vue';
|
||||
const props = defineProps({
|
||||
answer_columns:{
|
||||
type:Array,
|
||||
default:()=>[]
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, toRefs, reactive, defineProps, watch, onMounted, computed, nextTick } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { message } from 'ant-design-vue'
|
||||
import ColumnConfig from './../../particulars/components/ColumnConfig'
|
||||
import DownloadData from './../../particulars/components/DownloadData'
|
||||
import { addDownloadCenter } from '@/api/download.js'
|
||||
import { syncProductTest } from './api'
|
||||
import DownloadCenter from '@/views/DownloadCenter/index.vue'
|
||||
import { CaretDownOutlined } from '@ant-design/icons-vue'
|
||||
import { Modal } from 'ant-design-vue'
|
||||
|
||||
const props = defineProps({
|
||||
answer_columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
selectedSns:{}
|
||||
})
|
||||
const store = useStore()
|
||||
const {selectedSns} = toRefs(props)
|
||||
const answer_columns = computed(()=>props.answer_columns)
|
||||
console.log('==========answer_columns',answer_columns.value);
|
||||
const emit = defineEmits()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const sn = computed(() => route.query.sn)
|
||||
const searchData = ref({
|
||||
test1:null,
|
||||
test2:null
|
||||
})
|
||||
const opList = ref([
|
||||
{value:'0',label:'下载答卷'},
|
||||
{value:'1',label:'导出数据'},
|
||||
{value:'2',label:'删除'}
|
||||
])
|
||||
// 导出选中答卷
|
||||
const opChange = (e)=>{
|
||||
const {key} = e
|
||||
console.log(key);
|
||||
if(selectKeys.value.length===0){
|
||||
message.error('请选择需要操作的数据');
|
||||
selectedSns: {},
|
||||
template_type: {},
|
||||
other_send_status: {},
|
||||
})
|
||||
const store = useStore()
|
||||
const { selectedSns } = toRefs(props)
|
||||
const answer_columns = computed(() => props.answer_columns)
|
||||
console.log('==========answer_columns', answer_columns.value)
|
||||
const emit = defineEmits()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const sn = computed(() => route.query.sn)
|
||||
const searchData = ref({
|
||||
test1: null,
|
||||
test2: null
|
||||
})
|
||||
const opList = ref([
|
||||
{ value: '3', label: '标记' },
|
||||
{ value: '4', label: '取消标记' },
|
||||
{ value: '0', label: '下载答卷' },
|
||||
{ value: '1', label: '导出数据' },
|
||||
{ value: '2', label: '删除' }
|
||||
])
|
||||
const syncDataLoading = ref(false);
|
||||
|
||||
// 导出选中答卷
|
||||
const opChange = (e) => {
|
||||
const { key } = e
|
||||
console.log(key)
|
||||
if (selectKeys.value.length === 0) {
|
||||
message.error('请选择需要操作的数据')
|
||||
return
|
||||
}
|
||||
if(key=='0'){
|
||||
if (key == '0') {
|
||||
getSurveysAnswersExport()
|
||||
}
|
||||
if(key=='1'){
|
||||
if (key == '1') {
|
||||
// getSurveysAnswersDown()
|
||||
emit('dataExport',1)
|
||||
emit('dataExport', 1)
|
||||
}
|
||||
if(key=='2'){
|
||||
if (key == '2') {
|
||||
// delSurveysAnswers()
|
||||
emit('delFn')
|
||||
}
|
||||
if (key == '3') {
|
||||
// delSurveysAnswers()
|
||||
emit('sign', undefined, true)
|
||||
}
|
||||
const dataList = ref([
|
||||
if (key == '4') {
|
||||
// delSurveysAnswers()
|
||||
emit('sign', undefined, false)
|
||||
}
|
||||
}
|
||||
const dataList = ref([
|
||||
// {value:'0',label:'添加数据'},
|
||||
// {value:'1',label:'导入数据'},
|
||||
{value:'2',label:'导出数据'},
|
||||
])
|
||||
// 添加数据 导入数据 导出数据
|
||||
const dataChange = (e)=>{
|
||||
const {key} = e
|
||||
console.log(key);
|
||||
if(key=='0'){
|
||||
// { value: '1', label: '导入数据' }
|
||||
{ value: '2', label: '导出数据' }
|
||||
])
|
||||
// 添加数据 导入数据 导出数据
|
||||
const dataChange = (e) => {
|
||||
const { key } = e
|
||||
console.log(key)
|
||||
if (key == '0') {
|
||||
getSurveysAnswersDown()
|
||||
}
|
||||
if(key=='1'){
|
||||
if (key == '1') {
|
||||
emit('dataImport')
|
||||
}
|
||||
if(key=='2'){
|
||||
emit('dataExport',0)
|
||||
if (key == '2') {
|
||||
emit('dataExport', 0)
|
||||
}
|
||||
}
|
||||
// 配置列表
|
||||
const configVisible = ref(false);
|
||||
const handleConfig =()=> {
|
||||
}
|
||||
// 配置列表
|
||||
const configVisible = ref(false)
|
||||
const handleConfig = () => {
|
||||
emit('configOk')
|
||||
}
|
||||
}
|
||||
|
||||
// 导出
|
||||
const downloadVisible = ref(false);
|
||||
const downloadCenterVisible = ref(false)
|
||||
const queryState = ref({})
|
||||
const handleDownload = ()=>{
|
||||
// 导出
|
||||
const downloadVisible = ref(false)
|
||||
const downloadCenterVisible = ref(false)
|
||||
const queryState = ref({})
|
||||
const handleDownload = () => {
|
||||
emit('downloadOk')
|
||||
}
|
||||
const selectKeys = computed(()=>store.state.dataFilter.selectKeys)
|
||||
// 导出
|
||||
const getSurveysAnswersExport = async()=>{
|
||||
}
|
||||
const selectKeys = computed(() => store.state.dataFilter.selectKeys)
|
||||
// 导出
|
||||
const getSurveysAnswersExport = async () => {
|
||||
try {
|
||||
const subData = {
|
||||
sn:sn.value,
|
||||
sns:selectKeys.value.join()
|
||||
sn: sn.value,
|
||||
sns: selectKeys.value.join()
|
||||
}
|
||||
if(selectKeys.value.length==1) {
|
||||
const res =await store.dispatch('dataFilter/getSurveysAnswersExport',subData)
|
||||
if (selectKeys.value.length == 1) {
|
||||
const res = await store.dispatch('dataFilter/getSurveysAnswersExport', subData)
|
||||
// download(res.data.download_url)
|
||||
// console.log('getSurveysAnswersExport',res);
|
||||
const {title,url} = res.data.download_url;
|
||||
const { title, url } = res.data.download_url
|
||||
const subdata = {
|
||||
fileURL:url,
|
||||
fileName:title
|
||||
fileURL: url,
|
||||
fileName: title
|
||||
}
|
||||
store.dispatch('common/fileDown',subdata)
|
||||
}else{
|
||||
let data ={ download_type: '2', sns:selectKeys.value.join()}
|
||||
addDownloadCenter(sn.value,data).then(res=>{
|
||||
store.dispatch('dataFilter/selectIds', [])
|
||||
store.dispatch('dataFilter/selectKeys', [])
|
||||
store.dispatch('common/fileDown', subdata)
|
||||
} else {
|
||||
let data = { download_type: '2', sns: selectKeys.value.join() }
|
||||
addDownloadCenter(sn.value, data).then((res) => {
|
||||
// 下载中心
|
||||
store.dispatch('downloadCenter/changeCenterUrl',route.path)
|
||||
store.dispatch('downloadCenter/changeCenterUrl', route.path)
|
||||
// downloadCenterVisible.value = true
|
||||
store.dispatch('downloadCenter/changeCenterShow',true)
|
||||
store.dispatch('downloadCenter/changeCenterShow', true)
|
||||
store.dispatch('dataFilter/selectIds', [])
|
||||
store.dispatch('dataFilter/selectKeys', [])
|
||||
// router.push({
|
||||
// path: "/downloadCenter",
|
||||
// query: { path:route.path,sn:sn.value },
|
||||
@@ -189,68 +215,89 @@
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
// 下载
|
||||
const dataFilterInfo = computed(()=>store.state.dataFilter.dataFilterInfo)
|
||||
const getSurveysAnswersDown = async()=>{
|
||||
}
|
||||
// 下载
|
||||
const dataFilterInfo = computed(() => store.state.dataFilter.dataFilterInfo)
|
||||
const getSurveysAnswersDown = async () => {
|
||||
try {
|
||||
const subData = {
|
||||
...dataFilterInfo.value,
|
||||
sn:sn.value,
|
||||
sns:selectKeys.value.join(),
|
||||
sn: sn.value,
|
||||
sns: selectKeys.value.join()
|
||||
}
|
||||
const res =await store.dispatch('dataFilter/getSurveysAnswersDown',subData)
|
||||
const res = await store.dispatch('dataFilter/getSurveysAnswersDown', subData)
|
||||
download(res.data.download_url)
|
||||
console.log('getSurveysAnswersDown',res);
|
||||
console.log('getSurveysAnswersDown', res)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
// 删除
|
||||
const delSurveysAnswers = async (flag)=>{
|
||||
}
|
||||
// 删除
|
||||
const delSurveysAnswers = async (flag) => {
|
||||
try {
|
||||
const subData = {
|
||||
sn:sn.value,
|
||||
sn: sn.value
|
||||
}
|
||||
if(!flag)subData.sns = selectKeys.value.join()
|
||||
if (!flag) subData.sns = selectKeys.value.join()
|
||||
else subData.full = 1
|
||||
const res =await store.dispatch('dataFilter/delSurveysAnswers',subData)
|
||||
store.dispatch('dataFilter/selectKeys',[])
|
||||
const res = await store.dispatch('dataFilter/delSurveysAnswers', subData)
|
||||
store.dispatch('dataFilter/selectKeys', [])
|
||||
emit('delOk')
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
const download = (data)=>{
|
||||
}
|
||||
const download = (data) => {
|
||||
const url = data
|
||||
const a = document.createElement("a"); // 创建a标签
|
||||
a.setAttribute("download", ""); // download属性
|
||||
a.setAttribute("href", url); // href链接
|
||||
a.click(); // 自执行点击事件
|
||||
const a = document.createElement('a') // 创建a标签
|
||||
a.setAttribute('download', '') // download属性
|
||||
a.setAttribute('href', url) // href链接
|
||||
a.click() // 自执行点击事件
|
||||
}
|
||||
|
||||
const noData = () => {
|
||||
emit('noData')
|
||||
}
|
||||
|
||||
// 同步数据
|
||||
async function syncData() {
|
||||
syncDataLoading.value = true;
|
||||
try {
|
||||
await syncProductTest(sn.value);
|
||||
if (props.other_send_status) {
|
||||
return message.success("同步成功,您还需在产品测试模块导入该问卷哦~");
|
||||
}
|
||||
defineExpose({delSurveysAnswers})
|
||||
</script>
|
||||
<style scoped lang='scss'>
|
||||
.content{
|
||||
message.success("同步成功!");
|
||||
emit("update:other_send_status", 1);
|
||||
} catch (error) {
|
||||
console.error("同步数据错误", error);
|
||||
}
|
||||
syncDataLoading.value = false;
|
||||
}
|
||||
|
||||
defineExpose({ delSurveysAnswers })
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 80px;
|
||||
}
|
||||
.searchSelect{
|
||||
}
|
||||
.searchSelect {
|
||||
width: 110px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.operChd:not(:first-child){
|
||||
}
|
||||
.operChd:not(:first-child) {
|
||||
margin-left: 14px;
|
||||
}
|
||||
.suffix-icon{
|
||||
}
|
||||
.suffix-icon {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: auto;
|
||||
height: 12px;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const defaultOptions = {
|
||||
left_fixed_key: 'id',// 左侧固定列
|
||||
left_fixed_key: 'id', // 左侧固定列
|
||||
right_fixed_key: 'operation', //右侧固定列
|
||||
show_operator: true, // 是否显示操作列
|
||||
show_check: true,
|
||||
fixed: 'left'
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 是否为特殊题型,特指图文题、上传题
|
||||
*/
|
||||
|
||||
@@ -15,41 +17,81 @@ function includeSpecialType(type) {
|
||||
}
|
||||
|
||||
export default function useGeneratorTableColumns(columns, options = {}) {
|
||||
options = {...defaultOptions, ...options}
|
||||
// debugger
|
||||
options = { ...defaultOptions, ...options }
|
||||
const tableHeaders = ref([])
|
||||
function flatData(columns) {
|
||||
let columnsSing = {}
|
||||
let columnsType = {}
|
||||
let columnsMemo = {}
|
||||
if (options.show_check) {
|
||||
columnsSing = {
|
||||
title: '',
|
||||
key: 'is_mark',
|
||||
dataIndex: 'is_mark',
|
||||
align: 'center',
|
||||
width: 50,
|
||||
slots: { customRender: 'is_mark' },
|
||||
fixed: 'left'
|
||||
}
|
||||
// columnsType = {
|
||||
// title: '数据类型',
|
||||
// key: 'type',
|
||||
// dataIndex: 'type',
|
||||
// align: 'center',
|
||||
// width: 100,
|
||||
// slots: { customRender: 'type' },
|
||||
// fixed: 'left'
|
||||
// }
|
||||
columnsMemo = {
|
||||
title: '标记原因',
|
||||
key: 'mark_des',
|
||||
dataIndex: 'mark_des',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
slots: { customRender: 'mark_des' },
|
||||
fixed: 'left'
|
||||
}
|
||||
}
|
||||
let result = columns.reduce((previousValue, currentValue) => {
|
||||
const arr = Object.entries(currentValue).map(([key, value]) => ({
|
||||
...value,
|
||||
key,
|
||||
dataIndex: key,
|
||||
width: key === options.left_fixed_key? 100: includeSpecialType(value.question_type) ? 300 : 200,
|
||||
fixed: key === options.left_fixed_key ? 'left': null,
|
||||
align: 'center',
|
||||
slots: {customRender: key },
|
||||
}));
|
||||
return previousValue.concat(arr);
|
||||
}, []);
|
||||
width: key === options.left_fixed_key ? 100 : includeSpecialType(value.question_type) ? 300 : 200,
|
||||
fixed: key === options.fixed,
|
||||
// align: 'center',
|
||||
slots: { customRender: key }
|
||||
}))
|
||||
return previousValue.concat(arr)
|
||||
}, [])
|
||||
// 手动修改作答ID数组位置
|
||||
const snData = result.find(el=>el.key =='id')
|
||||
result = result.filter(el=>el.key!='id')
|
||||
if(snData)result.unshift(snData)
|
||||
if(options.show_operator) {
|
||||
const snData = result.find((el) => el.key == 'id')
|
||||
result = result.filter((el) => el.key != 'id')
|
||||
result.unshift(columnsMemo)
|
||||
result.unshift(columnsType)
|
||||
if (snData) {
|
||||
snData.fixed = 'left'
|
||||
result.unshift(snData)
|
||||
}
|
||||
result.unshift(columnsSing)
|
||||
if (options.show_operator) {
|
||||
result.push({
|
||||
title: '操作',
|
||||
key: 'operation',
|
||||
dataIndex: 'operation',
|
||||
width: 130,
|
||||
slots: {customRender: "operation" },
|
||||
fixed: 'right',
|
||||
width: 120,
|
||||
slots: { customRender: 'operation' },
|
||||
fixed: 'right'
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
watch(columns, (data) => {
|
||||
if(data) {
|
||||
tableHeaders.value = flatData(data);
|
||||
if (data) {
|
||||
tableHeaders.value = flatData(data)
|
||||
}
|
||||
})
|
||||
return { columns, tableHeaders};
|
||||
return { columns, tableHeaders }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ref, watch } from "vue";
|
||||
import CustomTableHeaderCell from '@/views/DataAnalyse/components/CustomTableHeaderCell'
|
||||
export default function renderCustomHeader(columns, sn ,search_params) {
|
||||
|
||||
const customHeaders = ref([])
|
||||
|
||||
function renderCell(data, sn, search_params) {
|
||||
|
||||