曹冬冬 пре 5 година
родитељ
комит
ef99f4e2a3

+ 0 - 1
src/api/editor.js

@@ -48,7 +48,6 @@ const cncTestDetail = (data) => {
 const createTest = (data) => {
   return http.post('/testTheme/createTest', data)
 }
-
 module.exports = {
   houseList, cncTestDetail, createTest,
   getUserThemeList, saveTheme, updateTheme, uploadPic, uploadPsd, getPageByThemeId, getPicListByThemeId, delTheme, cncTestcaseList

+ 13 - 1
src/api/test.js

@@ -23,6 +23,18 @@ const exportExcelPath = (param) => {
   return http.post('/excel/exportExcelPath', param)
 }
 
+const answerData = (data) => {
+  return http.post('/analyse/answerData', data)
+}
+const saveAnalyseBag = (data) => {
+  return http.post('/analyse/saveAnalyseBag', data)
+}
+const condition = (data) => {
+  return http.post('/analyse/condition', data)
+}
+const crossAnalyse = (data) => {
+  return http.post('/analyse/crossAnalyse', data)
+}
 module.exports = {
-  testList, deleteTest, copyTest, queryTestTheme, exportExcelPath
+  testList, deleteTest, copyTest, queryTestTheme, exportExcelPath, answerData, saveAnalyseBag, condition, crossAnalyse
 }

+ 70 - 0
src/components/HeaderData.vue

@@ -0,0 +1,70 @@
+<template>
+  <div class="header">
+    <div class="tag">
+      <div class="left">
+        <span @click="home" style="cursor: pointer;">首页</span> > 数据
+      </div>
+      <div class="right">
+        <div class="operational-data">下载PDF</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    home() {
+      this.$router.push({ path: "/" });
+    }
+  }
+};
+</script>
+
+<style lang="less" scoped>
+.header {
+  z-index: 1;
+  position: fixed;
+  top: 0px;
+  width: 100%;
+  height: 60px;
+  box-shadow: 0 2px 8px 0 rgba(62, 67, 116, 0.1);
+  border-bottom: 0;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  padding: 0px 50px;
+  .tag {
+    max-width: 1180px;
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    font-size: 14px;
+    font-family: Helvetica;
+    color: rgba(51, 51, 51, 1);
+    line-height: 17px;
+  }
+  .right {
+    display: flex;
+    flex-direction: row;
+    .operational-data {
+      width: 88px;
+      height: 30px;
+      font-size: 12px;
+      font-family: STYuanti-SC-Regular, STYuanti-SC;
+      font-weight: 400;
+      color: rgba(255, 255, 255, 1);
+      background: rgba(78, 93, 255, 1);
+      border-radius: 15px;
+      line-height: 30px;
+      text-align: center;
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 4 - 16
src/components/HeaderEdit.vue

@@ -7,21 +7,11 @@
     </div>
     <div class="tools">
       <div class="next_return">
-        <div
-          class="return"
-          title="撤销"
-          @click="revocation"
-          :style="`opacity:${operationList.length>1?'1':'.3'}`"
-        >
+        <div class="return" title="撤销" @click="revocation" :style="`opacity:${operationList.length>1?'1':'.3'}`">
           <img class="retutn_icon" src="../assets/images/button_return.png" alt />
           <span>撤销</span>
         </div>
-        <div
-          class="return"
-          title="恢复"
-          @click="recover"
-          :style="`opacity:${nextList.length>0?'1':'.3'}`"
-        >
+        <div class="return" title="恢复" @click="recover" :style="`opacity:${nextList.length>0?'1':'.3'}`">
           <img class="retutn_icon" src="../assets/images/button_next.png" alt />
           <span>恢复</span>
         </div>
@@ -37,11 +27,9 @@
           <img class="size" @click="zoom(false)" src="../assets/images/subtraction.png"></img>
           <div class="zoom-num">
             <span
-              style="font-size:14px;font-family:MicrosoftYaHei;color:rgba(100,107,129,1);line-height:19px"
-            >{{zoomNum*100}}%</span>
+              style="font-size:14px;font-family:MicrosoftYaHei;color:rgba(100,107,129,1);line-height:19px">{{zoomNum*100}}%</span>
             <span
-              style="font-size:14px;font-family:MicrosoftYaHei;color:rgba(100,107,129,1);line-height:19px;"
-            >缩放</span>
+              style="font-size:14px;font-family:MicrosoftYaHei;color:rgba(100,107,129,1);line-height:19px;">缩放</span>
           </div>
           <img class="size" @click="zoom(true)" src="../assets/images/add.png"></img>
         </div>

+ 6 - 2
src/components/HeaderMain.vue

@@ -3,7 +3,7 @@
     <div class="logo" @click="home">
       <img class="logo-img" src="../assets/images/diaoyanbao-log.png" alt="">调研宝</div>
     <div class="right">
-      <div class="operational-data">去“看板”查看测试运营数据</div>
+      <div class="operational-data" @click="testData">查看数据</div>
       <el-dropdown placement="bottom" trigger="click">
         <div class="userinfo">用户名 <i class="el-icon-caret-bottom"></i></div>
         <el-dropdown-menu slot="dropdown">
@@ -23,6 +23,9 @@ export default {
   methods: {
     home() {
       this.$router.push({ path: "/" });
+    },
+    testData() {
+      this.$router.push({ path: "/testData" });
     }
   }
 };
@@ -58,7 +61,7 @@ export default {
     display: flex;
     flex-direction: row;
     .operational-data {
-      width: 240px;
+      width: 119px;
       height: 34px;
       background: #e6edff;
       border-radius: 17px;
@@ -67,6 +70,7 @@ export default {
       line-height: 34px;
       text-align: center;
       margin-right: 46px;
+      cursor: pointer;
     }
     .userinfo {
       width: 132px;

+ 42 - 0
src/components/HistogramHorizontal.vue

@@ -0,0 +1,42 @@
+<!-- 水平方向的柱状图 -->
+<template>
+  <div :id="chartId"></div>
+</template>
+<script>
+import { Chart } from "@antv/g2";
+import superHorizontal from "./SuperComponent";
+export default {
+  name: "chart",
+  data() {
+    return superHorizontal.rootComponent.data();
+  },
+  props: superHorizontal.rootComponent.props,
+  mounted() {
+    this.drawChart();
+  },
+  methods: {
+    drawChart: function() {
+      console.log("XXXXSSSS", this.chartId);
+      // Step 1: 创建 Chart 对象
+      const chart = new Chart({
+        container: this.chartId, // 指定图表容器 ID
+        autoFit: true,
+        height: 400,
+        padding: [40, 40]
+      });
+
+      // Step 2: 载入数据源
+      chart.data(this.chartData);
+
+      // Step 3: 创建图形语法,绘制柱状图
+      chart.interval().position("genre*sold");
+
+      // Step 4: 渲染图表
+      chart.render();
+    }
+  }
+};
+</script>
+
+<style scoped>
+</style>

+ 55 - 0
src/components/HistogramHorizontals.vue

@@ -0,0 +1,55 @@
+<!-- 水平方向的柱状图 -->
+<template>
+  <div :id="chartId"></div>
+</template>
+<script>
+import { Chart } from "@antv/g2";
+import superHorizontal from "./SuperComponent";
+export default {
+  name: "chart",
+  data() {
+    return superHorizontal.rootComponent.data();
+  },
+  props: superHorizontal.rootComponent.props,
+  mounted() {
+    this.drawChart();
+  },
+  methods: {
+    drawChart: function() {
+      console.log("XXXXSSSS", this.chartId);
+      // Step 1: 创建 Chart 对象
+      const chart = new Chart({
+        container: this.chartId,
+        autoFit: true,
+        height: 500
+      });
+      chart.data(this.chartData);
+
+      chart.axis("time", {
+        tickLine: null
+      });
+
+      // chart.legend({
+      //   position: "bottom"
+      // });
+
+      chart.tooltip({
+        shared: true,
+        showMarkers: false
+      });
+      chart.interaction("active-region");
+
+      chart
+        .interval()
+        .adjust("stack")
+        .position("time*value")
+        .color("type", ["#F3CC1C", "#1890ff", "#6190FF", "#36CFAA"]);
+
+      chart.render();
+    }
+  }
+};
+</script>
+
+<style scoped>
+</style>

+ 22 - 0
src/components/SuperComponent.js

@@ -0,0 +1,22 @@
+const rootComponent = {
+  data() {
+    return {
+      chart: null
+    }
+  },
+  props: {
+    chartData: {
+      type: Array,
+      default: function () {
+        return {
+          data: []
+        }
+      }
+    },
+    id: String,
+    chartId: String
+  }
+}
+export default {
+  rootComponent
+}

+ 4 - 0
src/routers.js

@@ -45,6 +45,10 @@ const router = new Router({
     path: '/cncTestLists',
     name: "cncTestLists",
     component: require('./views/cnctestlists/cncTestLists.vue')
+  }, {
+    path: '/testData',
+    name: "testData",
+    component: require('./views/testData/testData.vue')
   }]
 })
 router.beforeEach((to, from, next) => {

+ 1 - 1
src/util/appConst.js

@@ -9,7 +9,7 @@ if (process.env.NODE_ENV === 'test') {
   QINIU_DOMAIN = 'https://gatewaytest.elab-plus.com'
   DIAOYANBAO_PATH = 'http://h5test.elab-plus.com/diaoyanbao/#/preview?mgid='
 } else if (process.env.NODE_ENV === 'development') {//开发
-  BACKEND_DOMAIN = 'http://192.168.0.16:5318'
+  BACKEND_DOMAIN = 'http://43.254.221.77:5555/elab-diaoyanbao'
   DIAOYANBAO_PATH = 'http://192.168.4.249:8080/#/preview?mgid='
   QINIU_DOMAIN = 'https://gatewaytest.elab-plus.com'
   // BACKEND_DOMAIN = 'http://gatewaytest.elab-plus.com/elab-diaoyanbao'

+ 20 - 1
src/util/time.js

@@ -31,6 +31,25 @@ const dateStr = (date) => {
     return date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate();
   }
 }
+
+
+
+const getNowFormatDate = () => {
+  var date = new Date();
+  var year = date.getFullYear();
+  var month = date.getMonth() + 1;
+  var strDate = date.getDate();
+  if (month >= 1 && month <= 9) {
+    month = '0' + month;
+  }
+  if (strDate >= 0 && strDate <= 9) {
+    strDate = '0' + strDate;
+  }
+  var currentdate = year + '-' + month + '-' + strDate + ":" + date.getHours() + ":" + date.getMinutes();
+
+  console.log("XXXXXX", currentdate);
+  return currentdate;
+}
 export default {
-  dateStr
+  dateStr, getNowFormatDate
 }

+ 27 - 86
src/views/h5editor/overview.vue

@@ -2,18 +2,10 @@
   <div class="overview">
     <!-- 顶部tag -->
     <div class="preview-tag">
-      <div
-        class="page-tag-btn tagPage"
-        :class="{ active: viewState === 0 }"
-        @click="function () { viewState = 0 }"
-      >
+      <div class="page-tag-btn tagPage" :class="{ active: viewState === 0 }" @click="function () { viewState = 0 }">
         <div class="page-tag-btn-tip">页面</div>
       </div>
-      <div
-        class="page-tag-btn tagElement"
-        :class="{ active: viewState === 1 }"
-        @click="function () { viewState = 1 }"
-      >
+      <div class="page-tag-btn tagElement" :class="{ active: viewState === 1 }" @click="function () { viewState = 1 }">
         <div class="page-tag-btn-tip">元素</div>
       </div>
     </div>
@@ -25,21 +17,12 @@
           <div class="page_preview_tag_title">封面</div>
           <div class="item-page" v-for="(page,index) in pages" v-show="index==0">
             <span>1</span>
-            <div
-              class="page"
-              :class="{ active: page === editingPage }"
+            <div class="page" :class="{ active: page === editingPage }"
               :style="{ width: 70 + 4 + 'px', height: (70 / canvasWidth) * canvasHeight + 4 + 'px' }"
-              @click="setEditingPage(page,0)"
-              @click.right="rightEvent()"
-            >
-              <Page
-                :isOverView="true"
-                class="content"
-                :hideFoot="true"
+              @click="setEditingPage(page,0)" @click.right="rightEvent()">
+              <Page :isOverView="true" class="content" :hideFoot="true"
                 :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', transform: 'scale(' + 70 / canvasWidth +')',backgroundColor: bodyBackgroundColor }"
-                :elements="page.elements"
-                type="see"
-              />
+                :elements="page.elements" type="see" />
             </div>
           </div>
         </li>
@@ -48,27 +31,15 @@
           <div class="page_preview_tag_title">题目</div>
           <div class="item-page" v-for="(page,index) in pages" v-show="isShow(index)">
             <span>{{index + 1 }}</span>
-            <div
-              class="page"
-              :class="{ active: page === editingPage }"
+            <div class="page" :class="{ active: page === editingPage }"
               :style="{ width: 70 + 4 + 'px', height: (70 / canvasWidth) * canvasHeight + 4 + 'px' }"
-              @click="setEditingPage(page,index)"
-            >
-              <Page
-                :isOverView="true"
-                class="content"
-                :hideFoot="true"
+              @click="setEditingPage(page,index)">
+              <Page :isOverView="true" class="content" :hideFoot="true"
                 :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', transform: 'scale(' + 70 / canvasWidth +')',backgroundColor: bodyBackgroundColor }"
-                :elements="page.elements"
-                type="see"
-              />
+                :elements="page.elements" type="see" />
             </div>
-            <el-dropdown
-              placement="bottom"
-              trigger="click"
-              class="operation"
-              @command="command=>operationCommand(command, page, index)"
-            >
+            <el-dropdown placement="bottom" trigger="click" class="operation"
+              @command="command=>operationCommand(command, page, index)">
               <div class="operation_img"></div>
               <el-dropdown-menu slot="dropdown">
                 <el-dropdown-item command="insertBottom">向下插入新页面</el-dropdown-item>
@@ -84,27 +55,15 @@
           <div class="page_preview_tag_title">结论</div>
           <div class="item-page" v-for="(page,index) in pages" v-show="isShowResult(index)">
             <span>{{index + 1}}</span>
-            <div
-              class="page"
-              :class="{ active: page === editingPage }"
+            <div class="page" :class="{ active: page === editingPage }"
               :style="{ width: 70 + 4 + 'px', height: (70 / canvasWidth) * canvasHeight + 4 + 'px' }"
-              @click="setEditingPage(page,index)"
-            >
-              <Page
-                :isOverView="true"
-                class="content"
-                :hideFoot="true"
+              @click="setEditingPage(page,index)">
+              <Page :isOverView="true" class="content" :hideFoot="true"
                 :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', transform: 'scale(' + 70 / canvasWidth +')',backgroundColor: bodyBackgroundColor }"
-                :elements="page.elements"
-                type="see"
-              />
+                :elements="page.elements" type="see" />
             </div>
-            <el-dropdown
-              placement="bottom"
-              trigger="click"
-              class="operation"
-              @command="command=>operationCommand(command, page, index)"
-            >
+            <el-dropdown placement="bottom" trigger="click" class="operation"
+              @command="command=>operationCommand(command, page, index)">
               <div class="operation_img"></div>
               <el-dropdown-menu slot="dropdown">
                 <el-dropdown-item command="del">删除</el-dropdown-item>
@@ -116,31 +75,18 @@
       </ul>
     </div>
     <!-- 图层 -->
-    <div
-      class="list custom-scrollbar"
-      style="z-index: 2;"
-      v-show="viewState === 1"
-      :class="{ dragging: dragState === 1 }"
-    >
+    <div class="list custom-scrollbar" style="z-index: 2;" v-show="viewState === 1"
+      :class="{ dragging: dragState === 1 }">
       <ul>
         <li v-for="(layer, index) in layersNoBg" :key="index">
-          <div
-            class="layer"
-            :class="{ active: editingLayer === layer}"
-            @mousedown="moveLayer($event,layer)"
-          >
+          <div class="layer" :class="{ active: editingLayer === layer}" @mousedown="moveLayer($event,layer)">
             <span class="thumb" :style="{ backgroundImage: 'url(' + layer.imgSrc + ')' }"></span>
             {{ layer.type }}
           </div>
         </li>
       </ul>
-      <div
-        v-for="(layer, index) in layersBg"
-        :key="index"
-        class="layer"
-        :class="{ active: editingLayer === layer}"
-        @click="setEditingLayer(layer)"
-      >
+      <div v-for="(layer, index) in layersBg" :key="index" class="layer" :class="{ active: editingLayer === layer}"
+        @click="setEditingLayer(layer)">
         <span class="thumb" :style="{ backgroundImage: 'url(' + layer.imgSrc + ')' }"></span>
         {{ layer.type }}
       </div>
@@ -154,14 +100,8 @@
       <el-collapse-transition>
         <div v-show="showTopic">
           <div class="topic-group">
-            <el-checkbox
-              v-model="item.isChecked"
-              v-for="(item, index) in questionList"
-              :label="item.name"
-              :key="index"
-              @change="checked=>selectCheckbox(checked,item,index)"
-              :disabled="isDisabled(index)"
-            ></el-checkbox>
+            <el-checkbox v-model="item.isChecked" v-for="(item, index) in questionList" :label="item.name" :key="index"
+              @change="checked=>selectCheckbox(checked,item,index)" :disabled="isDisabled(index)"></el-checkbox>
           </div>
         </div>
       </el-collapse-transition>
@@ -260,7 +200,7 @@ export default {
         this.$store.state.editor.editorTheme.bodyBackgroundColor ||
         "rgba(255,255,255,0)";
       if (isTop) {
-        var position = index ;
+        var position = index;
       } else {
         var position = index + 1;
       }
@@ -764,6 +704,7 @@ export default {
     margin-left: 10px;
     border: 2px solid rgba(255, 255, 255, 1);
     background: #fff;
+    padding: 0px;
     &.active {
       border-color: rgba(78, 93, 255, 1);
       box-shadow: 0px 2px 4px 0px rgba(78, 93, 255, 1);

+ 206 - 0
src/views/testData/testData.html

@@ -0,0 +1,206 @@
+<div class="page" style="overflow:auto">
+  <!-- 头部 -->
+  <HeaderData></HeaderData>
+  <!-- 题目筛选 -->
+  <div class="testData">
+    <div class="testList">
+      <div class="testProject">
+        <el-dropdown trigger="click" @command="projectCommand">
+          <el-button type="primary">{{ownHouseName}} <i class="el-icon-caret-bottom icon-right"></i>
+          </el-button>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item>全部</el-dropdown-item>
+            <el-dropdown-item v-for="(item,index) in houseList" :key="item.houseId" :command="item">
+              {{item.houseName}}</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+      </div>
+      <div class="testItem">
+        <div class="itemArrow"><i class="el-icon-arrow-left"></i></div>
+        <div class="testContent">
+          <div class="testTopic" :class="{testTopicSel:item.isSelected}" v-for="(item,index) in dataList"
+            :key="item.created">
+            <div id></div>
+            <div style="display: -webkit-box;
+            -webkit-box-orient: vertical;
+            -webkit-line-clamp: 3;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            word-break: break-all;
+            word-wrap: break-word;">{{index+1}}.{{item.title}}</div>
+            <img v-if="item.isSelected" class="testSel" src="
+              https://dm.static.elab-plus.com/diaoyanbao/%E5%A4%9A%E9%80%89-%E9%80%89%E4%B8%AD@2x.png" alt=""
+              @click="changeTest(item)">
+            <img v-if="!item.isSelected" class="testSel"
+              src="https://dm.static.elab-plus.com/diaoyanbao/%E5%A4%9A%E9%80%89-%E6%9C%AA%E9%80%89@2x.png" alt=""
+              @click="changeTest(item)">
+          </div>
+        </div>
+        <div class="itemArrow"><i class="el-icon-arrow-right"></i></div>
+      </div>
+    </div>
+    <div class="testTip">
+      <div v-if="!isCrossAnalyse"><span
+          v-if="currentDate">截止到{{currentDate}},问卷共{{answerData.answerAll || 0}}人参与,完成全部题目的有{{answerData.answerJoin || 0}}人。</span>
+      </div>
+      <div v-if="isCrossAnalyse">
+        <div class="analyseBag">
+          <div class="analyseBagTitle">
+            <el-dropdown trigger="click" @command="analyseCommand">
+              <el-button type="primary">{{analyseCommandSel}}<i class="el-icon-caret-bottom icon-right"></i>
+              </el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item command="-1">全部</el-dropdown-item>
+                <el-dropdown-item command="0">数据包</el-dropdown-item>
+                <el-dropdown-item command="1">区域</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </div>
+          <div class="analyseBagList">
+            <el-cascader v-model="analyseValue" :options="analyseOptions"
+              :props="{ checkStrictly: analyseCommandSel== '区域' ? true : false }"
+              @change="handleAnalyseChange(analyseValue)">
+            </el-cascader>
+          </div>
+        </div>
+      </div>
+      <div class="switchItem">
+        <div class="switch" :class="{ switchSelected: !isCrossAnalyse}" @click="isCrossAnalyse=false">答题统计</div>
+        <div class="switch" :class="{ switchSelected: isCrossAnalyse}" @click="isCrossAnalyse=true">交叉分析</div>
+      </div>
+    </div>
+    <div class="answer" v-if="!isCrossAnalyse">
+      <div class="filter">
+        <img v-if="isFilter" class="filterIcon"
+          src="https://dm.static.elab-plus.com/diaoyanbao/%E5%8F%96%E6%B6%88%E7%AD%9B%E9%80%89%E6%8C%89%E9%92%AE@2x.png"
+          alt="" @click="isFilter=false">
+        <img v-if="!isFilter" class="filterIcon"
+          src="https://dm.static.elab-plus.com/diaoyanbao/%E7%AD%9B%E9%80%89%E6%8C%89%E9%92%AE@2x.png" alt=""
+          @click="isFilter=true">
+        <div class="rightFilter">
+          <div class="rightFilterItem" :class="{ rightFilterItemSel: !isShowTable}" @click="isShowTable=false">图形</div>
+          <div class="rightFilterItem" :class="{ rightFilterItemSel: isShowTable}" @click="isShowTable=true">表格</div>
+        </div>
+      </div>
+      <div class="filterContent" v-if="isFilter">
+        <div class="filterView">
+          <div class="filterItem" v-for="(items, indexs) in filterList" :key="indexs">
+            <div class="filterTitle"><span v-if="indexs==0">选择条件</span></div>
+            <div class="filterAnswer">
+              <el-cascader v-model="value[indexs]" :options="options" @change="handleChange(value[indexs],indexs)">
+              </el-cascader>
+            </div>
+            <div class="filterReply" v-if="questionListSel[indexs]">
+              <el-checkbox-group v-model="checkList[indexs]">
+                <el-checkbox v-for="(item, index) in questionListSel[indexs].optionList" :label="item.content"
+                  :key="index" @change="checked=>changequestionChild(checked,item, indexs)">
+                </el-checkbox>
+              </el-checkbox-group>
+            </div>
+            <div class="filterDel" @click="delFilter(indexs)"><i class="el-icon-delete"></i>
+            </div>
+          </div>
+          <div class="addfilter" @click="addFilter">
+            <img class="addfilterIcon"
+              src="https://dm.static.elab-plus.com/diaoyanbao/%E6%B7%BB%E5%8A%A0%E6%9D%A1%E4%BB%B6%E6%8C%89%E9%92%AE@2x.png"
+              alt="">
+          </div>
+          <div class="filterSave">
+            <div class="saveLocation" @click="getAnswerData">筛选</div>
+            <div class="saveOnLine" @click="saveOnLine">保存此筛选条件作为数据包</div>
+          </div>
+        </div>
+        <div class="filterResult">已为您筛选出【{{filterStr}}】共{{answerData.answerAll}}人,此条件下的用户题目答题情况如下:</div>
+      </div>
+      <div class="result" v-if="isShowTable">
+        <div class="resultItem" v-for="(item, index) in answerData.questionList" :key="index">
+          <div class="resultTitle">题目{{index+1}}:{{item.content}}[{{item.chooseType == '1'? '单选':'多选'}}]</div>
+          <div class="resultTable">
+            <div class="tableHeader">
+              <div class="option">选项</div>
+              <div class="numbers">答题人数</div>
+              <div class="percent">占该题总答题人数百分比</div>
+            </div>
+            <div class="tableRow" v-for="(optionItem, optionIndex) in item.optionList" :key="optionIndex">
+              <div class="option">{{optionItem.content}}</div>
+              <div class="numbers">{{optionItem.answerCount}}</div>
+              <div class="percent">
+                <el-progress :percentage="((optionItem.answerCount/item.answerTotal)*100).toFixed(0) || 0"
+                  color="#4E5DFF" :stroke-width="8">
+                </el-progress>
+              </div>
+            </div>
+            <div class="tableRow">
+              <div class="option">总计</div>
+              <div class="numbers">{{item.answerTotal}}</div>
+              <div class="percent">_ _</div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="chart" v-if="!isShowTable">
+        <div class="chartItem" v-for="(item, index) in chartData" :key="index">
+          <div class="chartTitle">题目{{index+1}}:{{item.content}}[{{item.chooseType == '1'? '单选':'多选'}}]</div>
+          <div class="chartData">
+            <HistogramHorizontal :id="'c1'" :chartId="'c'+item.questionId" :chart-data="item.data">
+            </HistogramHorizontal>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div v-if="isCrossAnalyse" class="crossAnalyse">
+      <div class="crossFilter">
+        <div class="xyFilter">
+          <div><span class="crossFilterTitle">自变量 X</span><span
+              class="crossFilterSubTitle">(一般为样本属性,例如性别,年龄等。限2题)</span></div>
+          <div style="margin-top: 8px;" v-for="(items, indexs) in filterXList" :key="indexs">
+            <el-cascader v-model="optionsXValue[indexs]" :options="optionsX"
+              @change="handleChangeX(optionsXValue[indexs],indexs)">
+            </el-cascader>
+          </div>
+          <div class="addfilter" @click="addfilterX" v-if="filterXList.length<2">
+            <img class="addfilterIcon"
+              src="https://dm.static.elab-plus.com/diaoyanbao/%E6%B7%BB%E5%8A%A0%E6%9D%A1%E4%BB%B6%E6%8C%89%E9%92%AE@2x.png"
+              alt="">
+          </div>
+        </div>
+        <div class="xyFilter" style="margin-left: 40px;">
+          <div><span class="crossFilterTitle">因变量 Y</span><span class="crossFilterSubTitle">(您要分析的目标题目)</span></div>
+          <div style="margin-top: 8px;" v-for="(items, indexs) in filterYList" :key="indexs">
+            <el-cascader v-model="optionsYValue[indexs]" :options="optionsY"
+              @change="handleChangeY(optionsYValue[indexs],indexs)">
+            </el-cascader>
+          </div>
+          <div class="addfilter" @click="addfilterY">
+            <img class="addfilterIcon"
+              src="https://dm.static.elab-plus.com/diaoyanbao/%E6%B7%BB%E5%8A%A0%E6%9D%A1%E4%BB%B6%E6%8C%89%E9%92%AE@2x.png"
+              alt="">
+          </div>
+        </div>
+        <div class="analyse">
+          <div class="startAnalyse" @click="getCrossAnalyse">开始分析</div>
+          <div class="analyseTip">*不可选择同样的题目</div>
+        </div>
+      </div>
+      <div class="crossAnalyseTable" v-for="(item, index) in crossAnalyse" :key="index">
+        <div class="crossAnalyseTitle">题目{{index+1}}:</div>
+        <div class="crossAnalyseChart">
+          <HistogramHorizontals :id="'c2'" :chartId="'caaaaa'+index" :chart-data="data">
+          </HistogramHorizontals>
+        </div>
+        <div class="table">
+          <div class="caTable">
+            <div class="headerRow" style="width: 100px;">X\Y</div>
+            <div class="headerRow" v-for="(item1,index1) in item[0].title" :key="index1"
+              :style="`width:${840/(item[0].title.length || 1)}px`">{{item1}}</div>
+          </div>
+          <div class="caTable" v-for="(items,indexs) in item" :key="indexs">
+            <div class="tabkeRow" style="width: 100px;">{{items.name}}</div>
+            <div class="tabkeRow" v-for="(item0,index0) in items.value" :key="index0"
+              :style="`width:${840/(items.value.length || 1)}px`">{{item0}}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 608 - 0
src/views/testData/testData.js

@@ -0,0 +1,608 @@
+import HeaderData from "../../components/HeaderData";
+import HistogramHorizontal from "../../components/HistogramHorizontal";
+import HistogramHorizontals from "../../components/HistogramHorizontals";
+import api from '../../api/test'
+import editorApi from '../../api/editor'
+import timeFormat from '../../util/time'
+import { format } from "util";
+export default {
+  components: {
+    HeaderData, HistogramHorizontal, HistogramHorizontals
+  },
+  data() {
+    return {
+      isCopy: false,
+      houseList: [],
+      ownHouseName: "所属项目",
+      dataList: [],
+      isFilter: false,
+      isShowTable: true,
+      checkList: [[]],
+      data: [],
+      value: [],
+      oldValue: [],
+      options: [],
+      questionList: [],
+      questionListSel: [],
+      filterList: [""],
+      questionChilds: [],
+      answerData: [],
+      currentDate: null,
+      filterStr: "",
+      chartData: [],
+      isCrossAnalyse: false,
+      condition: [],
+      analyseCommandSel: "全部",
+      analyseOptions: [],
+      analyseValue: [],
+      crossAnalyse: [],
+      optionsX: [],
+      optionsXValue: [],
+      optionsXOldValue: [],
+      optionsY: [],
+      optionsYValue: [],
+      optionsYOldValue: [],
+
+      filterXList: [""],
+      filterYList: [""],
+      selectedDataList: [],
+    }
+  },
+  watch: {
+    answerData: function (val) {
+      var questionList = val.questionList;
+      this.chartData = []
+      for (var i = 0; i < questionList.length; i++) {
+        var question = questionList[i];
+        var data = []
+        var optionList = question.optionList;
+        for (var j = 0; j < optionList.length; j++) {
+          data.push({ genre: optionList[j].content, sold: optionList[j].answerCount })
+        }
+        var conditionQuestion = { data: data, ...question }
+        this.chartData.push(conditionQuestion);
+      }
+    },
+    analyseCommandSel: function (val) {
+      this.analyseOptions = [];
+      this.analyseValue = [];
+      if (val == "全部") {
+
+      } else if (val == "数据包") {
+        var bagList = this.condition.bagList;
+        for (var i = 0; i < bagList.length; i++) {
+          this.analyseOptions.push({ value: bagList[i].analyseBagId, label: bagList[i].title, disabled: false })
+        }
+      } else {
+        var locationList = this.condition.locationList;
+        let locationTemp = []
+        for (var i = 0; i < locationList.length; i++) {
+          var item = locationList[i]
+          if (item.city == "") {
+            item.city = item.province;
+          }
+          locationTemp.push(item)
+        }
+        locationList = locationTemp;
+        let result = Object.values(locationList.reduce((m, n) => {
+          if (!m[n.province]) {
+            m[n.province] = { value: n.province, children: [] }
+          }
+          m[n.province].children.push(n)
+          return m
+        }, {}))
+        console.log("XXXX:result:", result)
+        var arr = []
+        for (var i = 0; i < result.length; i++) {
+
+          var list = result[i].children;
+          let results = Object.values(list.reduce((m, n) => {
+            if (!m[n.city]) {
+              m[n.city] = { value: n.city, label: n.city, children: [] }
+            }
+            m[n.city].children.push({ value: n.district, label: n.district })
+            return m
+          }, {}))
+          arr.push({ value: result[i].value, label: result[i].value, children: results })
+        }
+
+        this.analyseOptions = arr;
+      }
+    }
+  },
+  created() {
+    this.houseList = [];
+    editorApi.houseList().then((res) => {
+      if (res.success) {
+        this.houseList = res.list;
+      }
+    });
+    this.getTestList();
+  },
+  methods: {
+    async changeTest(item) {
+      console.log("XXXXXX1", item);
+      var list = []
+      for (var i = 0; i < this.dataList.length; i++) {
+        var element = this.dataList[i]
+        if (item._id == element._id) {
+          element.isSelected = !element.isSelected;
+        }
+        list.push(element)
+      }
+      console.log("XXXxXXX", list);
+      this.dataList = list;
+
+      this.options = []
+      this.questionList = []
+      for (var i = 0; i < this.dataList.length; i++) {
+        var element = this.dataList[i]
+        if (element.isSelected) {
+          this.getCNCTestDetail(element)
+        }
+      }
+
+      this.optionsX = []
+      for (var i = 0; i < this.dataList.length; i++) {
+        var element = this.dataList[i]
+        if (element.isSelected) {
+          this.getCNCTestDetailX(element)
+        }
+      }
+
+      this.optionsY = []
+      for (var i = 0; i < this.dataList.length; i++) {
+        var element = this.dataList[i]
+        if (element.isSelected) {
+          this.getCNCTestDetailY(element)
+        }
+      }
+    },
+    async getCondition() {
+      var testThemesIdList = [];
+      for (var i = 0; i < this.options.length; i++) {
+        var element = this.options[i]
+        testThemesIdList.push(element.id);
+      }
+      let data = {
+        testThemesIdList: testThemesIdList
+      }
+      api.condition(data).then((res) => {
+        if (res.success) {
+          console.log("success", res.single);
+          this.condition = res.single;
+        } else {
+          console.log("error");
+        }
+      });
+    },
+    async getCNCTestDetail(item) {
+      this.currentDate = timeFormat.getNowFormatDate();
+      let data = {
+        testThemesIdList: [item._id]
+      }
+      api.answerData(data).then((res) => {
+        if (res.success) {
+          this.answerData = res.single;
+          console.log("success", res);
+          var questionList = res.single.questionList;
+          var children = []
+          for (var i = 0; i < questionList.length; i++) {
+            children.push({ value: questionList[i].questionId, label: questionList[i].content, disabled: false })
+          }
+          var element = { value: item._id, label: item.title, children: children, id: item._id };
+          this.options.push(element);
+          this.questionList = questionList;
+          // 查询数据包列表
+          this.getCondition();
+        } else {
+          console.log("error");
+        }
+      });
+    },
+    async getCNCTestDetailX(item) {
+      let data = {
+        testThemesIdList: [item._id]
+      }
+      api.answerData(data).then((res) => {
+        if (res.success) {
+          this.answerData = res.single;
+          console.log("success", res);
+          var questionList = res.single.questionList;
+          var children = []
+          for (var i = 0; i < questionList.length; i++) {
+            children.push({ value: questionList[i].questionId, label: questionList[i].content, disabled: false })
+          }
+          var element = { value: item._id, label: item.title, children: children, id: item._id };
+          this.optionsX.push(element);
+        } else {
+          console.log("error");
+        }
+      });
+    },
+    async getCNCTestDetailY(item) {
+      let data = {
+        testThemesIdList: [item._id]
+      }
+      api.answerData(data).then((res) => {
+        if (res.success) {
+          this.answerData = res.single;
+          console.log("success", res);
+          var questionList = res.single.questionList;
+          var children = []
+          for (var i = 0; i < questionList.length; i++) {
+            children.push({ value: questionList[i].questionId, label: questionList[i].content, disabled: false })
+          }
+          var element = { value: item._id, label: item.title, children: children, id: item._id };
+          this.optionsY.push(element);
+        } else {
+          console.log("error");
+        }
+      });
+    },
+    handleChange(value, index) {
+      console.log(value, index, this.oldValue);
+      for (var i = 0; i < this.questionList.length; i++) {
+        if (value[1] == this.questionList[i].questionId) {
+          if (this.oldValue.length >= index + 1) {
+            console.log("XXXXXXXXXXXXX");
+            this.setOptionsDisabled(this.oldValue[index], false);
+          }
+          this.questionListSel[index] = this.questionList[i];
+        }
+      }
+      this.setOptionsDisabled(value, true);
+
+      this.value[index] = value;
+      this.oldValue[index] = value;
+      this.checkList.splice(index, 1, []);
+      this.questionChilds.splice(index, 1, []);
+    },
+    handleChangeX(value, index) {
+      console.log("handleChangeX", value, index, this.optionsXOldValue);
+      for (var i = 0; i < this.questionList.length; i++) {
+        if (value[1] == this.questionList[i].questionId) {
+          if (this.optionsXOldValue.length >= index + 1) {
+            console.log("XXXXXXXXXXXXX");
+            this.setOptionsDisabledXY(this.optionsXOldValue[index], false, 0);
+
+            this.setOptionsDisabledXY(this.optionsYOldValue[index], false, 1);
+          }
+          // this.questionListSel[index] = this.questionList[i];
+        }
+      }
+
+      this.setOptionsDisabledXY(value, true, 1);
+      this.setOptionsDisabledXY(value, true, 0);
+
+      this.optionsXValue[index] = value;
+      this.optionsXOldValue[index] = value;
+      // this.checkList.splice(index, 1, []);
+      // this.questionChilds.splice(index, 1, []);
+    },
+    handleChangeY(value, index) {
+      console.log("handleChangeX", value, index, this.optionsYOldValue);
+      for (var i = 0; i < this.questionList.length; i++) {
+        if (value[1] == this.questionList[i].questionId) {
+          if (this.optionsYOldValue.length >= index + 1) {
+            console.log("XXXXXXXXXXXXX");
+            this.setOptionsDisabledXY(this.optionsYOldValue[index], false, 1);
+            this.setOptionsDisabledXY(this.optionsYOldValue[index], false, 0);
+          }
+          // this.questionListSel[index] = this.questionList[i];
+        }
+      }
+      this.setOptionsDisabledXY(value, true, 1);
+      this.setOptionsDisabledXY(value, true, 0);
+
+      this.optionsYValue[index] = value;
+      this.optionsYOldValue[index] = value;
+      // this.checkList.splice(index, 1, []);
+      // this.questionChilds.splice(index, 1, []);
+    },
+    addfilterX() {
+      this.filterXList.push('');
+    },
+    addfilterY() {
+      this.filterYList.push('');
+    },
+    handleAnalyseChange(value) {
+      console.log(value);
+    },
+    setOptionsDisabledXY(value, disabled, type = 0) {
+      var newOptions = [];
+      console.log("XXXXXXX", value)
+      var options = type == 0 ? this.optionsX : this.optionsY;
+      for (var i = 0; i < options.length; i++) {
+        var item = options[i];
+        if (item.value == value[0]) {
+          for (var j = 0; j < options[i].children.length; j++) {
+            var children = []
+            var element = options[i].children[j];
+            if (element.value == value[1]) {
+              element.disabled = disabled
+            }
+            children.push(element)
+          }
+        }
+        newOptions.push(item)
+      }
+      if (type == 0) {
+        this.optionsX = newOptions;
+      } else {
+        this.optionsY = newOptions;
+      }
+
+    },
+    setOptionsDisabled(value, disabled) {
+      var newOptions = [];
+      console.log("XXXXXXX", value)
+      for (var i = 0; i < this.options.length; i++) {
+        var item = this.options[i];
+        if (item.value == value[0]) {
+          for (var j = 0; j < this.options[i].children.length; j++) {
+            var children = []
+            var element = this.options[i].children[j];
+            if (element.value == value[1]) {
+              element.disabled = disabled
+            }
+            children.push(element)
+          }
+        }
+        newOptions.push(item)
+      }
+      this.options = newOptions;
+    },
+    addFilter() {
+      this.filterList.push('');
+      this.checkList.push([]);
+    },
+    delFilter(index) {
+      if (this.value[index]) {
+        this.setOptionsDisabled(this.value[index], false);
+      }
+
+      this.filterList.splice(index, 1);
+      this.value.splice(index, 1);
+
+      this.questionListSel.splice(index, 1);
+      this.questionChilds.splice(index, 1);
+      this.checkList.splice(index, 1);
+    },
+    projectCommand(command) {
+      if (this.houseList.indexOf(command) == -1) {
+        console.log("不存在");
+        this.ownHouseName = "所属项目";
+      } else {
+        console.log("存在", command.houseName);
+        this.ownHouseName = command.houseName;
+      }
+      this.getTestList();
+    },
+    analyseCommand(command) {
+      console.log("XXXXXXX", command)
+      if (command == -1) {
+        this.analyseCommandSel = "全部";
+      } else if (command == 0) {
+        this.analyseCommandSel = "数据包";
+      } else {
+        this.analyseCommandSel = "区域";
+      }
+      // this.getTestList();
+    },
+    changequestionChild(checked, value, index) {
+      console.log("XXXXXX", value, index, checked);
+
+      var arr = this.questionChilds;
+      if (this.questionChilds.length <= index) { // 没有
+        if (checked) {
+          console.log("选中");
+          for (var i = 0; i < this.filterList.length; i++) {
+            if (i < index) {
+              if (this.questionChilds.length < index) {
+                this.questionChilds.push([]);
+              }
+            }
+          }
+          this.questionChilds.push([value]);
+        } else {
+          console.log("取消选中")
+        }
+      } else { // 有
+        console.log("有")
+        var questionList = this.questionChilds[index];
+        if (checked) {
+          questionList.push(value)
+        } else {
+          var arr = questionList;
+          for (var i = 0; i < questionList.length; i++) {
+            var option = questionList[i];
+            if (option.optionId == value.optionId) {
+              arr.splice(i, 1);
+            }
+          }
+          questionList = arr;
+        }
+        this.questionChilds[index] = questionList;
+      }
+
+    },
+    getTestList() {
+
+      let data = {
+        "orderType": "",
+        "ownHouseName": this.ownHouseName == "所属项目" ? '' : this.ownHouseName,
+        "pageNo": 1,
+        "pageSize": 100,
+        "houseAnswerStatus": ""
+      }
+      api.testList(data).then((res) => {
+        if (res.success) {
+          this.total = res.pageModel.total;
+          this.dataList = [];
+          this.dataList.push(...res.pageModel.resultSet);
+          this.dataList.forEach(element => {
+            element.isSelected = false
+          });
+          console.log("success", this.dataList, res.pageModel);
+        } else {
+          console.log("error");
+        }
+      });
+    },
+    async getAnswerData() {
+      this.filterStr = "";
+
+      var conditionQuestionList = [];
+      var testThemesIdList = [];
+      for (var i = 0; i < this.questionChilds.length; i++) {
+        var question = this.questionChilds[i];
+        var value = this.value[i];
+        var optionList = [];
+        for (var j = 0; j < question.length; j++) {
+          optionList.push({ optionId: question[j].optionId })
+          this.filterStr += question[j].content + "/";
+        }
+        var conditionQuestion = { questionId: value[1], optionList: optionList }
+        conditionQuestionList.push(conditionQuestion);
+      }
+
+      for (var i = 0; i < this.options.length; i++) {
+        testThemesIdList.push(this.options[i].id);
+      }
+      this.filterStr = this.filterStr.substr(0, this.filterStr.length - 1)
+      let data = {
+        conditionQuestionList: conditionQuestionList,
+        testThemesIdList: testThemesIdList
+      }
+      api.answerData(data).then((res) => {
+        if (res.success) {
+          this.answerData = res.single;
+          console.log("success", res);
+        } else {
+          console.log("error");
+        }
+      });
+    },
+    saveOnLine() {
+      var checkList = [];
+
+      for (var i = 0; i < this.questionChilds.length; i++) {
+        var question = this.questionChilds[i]
+        for (var j = 0; j < question.length; j++) {
+          var option = question[j];
+          var questionObj = this.questionListSel[i];
+          console.log("SSSSSS", option, questionObj);
+          checkList.push({ subOptionContent: option.content, subOptionId: option.optionId, subQuestionContent: questionObj.content, subQuestionId: questionObj.questionId })
+        }
+      }
+
+      console.log("编辑数据包", checkList);
+      this.$prompt("请数据包名称", "提保存筛选条件作为数据包", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/,
+        inputErrorMessage: "数据包名称不为空",
+        inputValue: this.title
+      })
+        .then(({ value }) => {
+          let param = {
+            checkList: checkList,
+            analyseBagTitle: value,
+            operator: "admin"
+          };
+          api.saveAnalyseBag(param).then(res => {
+            if (res.success) {
+              this.$message.success("保存成功");
+            } else {
+              this.$message.error("数据加载失败,请重试");
+            }
+          });
+        })
+        .catch(() => { });
+    },
+    async getCrossAnalyse() {
+      var testThemesIdList = [];
+      for (var i = 0; i < this.options.length; i++) {
+        testThemesIdList.push(this.options[i].id);
+      }
+      var xlist = [];
+      var ylist = [];
+      for (var i = 0; i < this.questionList.length; i++) {
+        var item = this.questionList[i];
+        for (var m = 0; m < this.optionsXValue.length; m++) {
+          var element = this.optionsXValue[m];
+          if (item.questionId == element[1]) {
+            xlist.push(item);
+          }
+        }
+        for (var n = 0; n < this.optionsYValue.length; n++) {
+          var element = this.optionsYValue[n];
+          if (item.questionId == element[1]) {
+            ylist.push(item);
+          }
+        }
+      }
+
+      let data = {
+        testThemesIdList: testThemesIdList,
+        xlist: xlist,
+        ylist: ylist
+      }
+      console.log("XXXXXX", data);
+      api.crossAnalyse(data).then((res) => {
+        if (res.success) {
+          console.log("success", res.list);
+          var crossAnalyse = res.list;
+          this.crossAnalyse = []
+          var result = [];
+          var rowArr = [];
+          for (var n = 0; n < crossAnalyse.length; n++) {
+            var arrs = []
+            var crossResult = crossAnalyse[n].crossResult;
+            console.log("XXXXX", Object.keys(crossResult), Object.values(crossResult))
+            rowArr = Object.keys(crossResult);
+            var values = Object.values(crossResult)
+            for (var m = 0; m < values.length; m++) {
+              console.log("SSSSS", Object.keys(values[m]), Object.values(values[m]))
+              arrs.push({ name: Object.keys(values[m]), value: Object.values(values[m]) })
+            }
+            result.push(arrs);
+          }
+
+          console.log("AAAAAA", result);
+
+          for (var x = 0; x < result.length; x++) {
+            var qqq = result[x];
+            var sss = [];
+            for (var q = 0; q < qqq.length; q++) {
+              sss.push({ name: rowArr[q], title: qqq[q].name, value: qqq[q].value })
+            }
+            this.crossAnalyse.push(sss);
+          }
+          console.log("SSSSS", this.crossAnalyse);
+
+          var data = [];
+          for (var x = 0; x < this.crossAnalyse.length; x++) {
+            var top = this.crossAnalyse[x];
+            for (var y = 0; y < top.length; y++) {
+              var one = top[y].value;
+              console.log("one", top[y].name)
+              for (var z = 0; z < one.length; z++) {
+                var two = one[z];
+                data.push({ time: top[y].name, type: top[y].title[z], value: two })
+              }
+            }
+          }
+          console.log("data", data);
+          this.data = data
+
+        } else {
+          console.log("error");
+        }
+      });
+    }
+
+
+  },
+}

+ 591 - 0
src/views/testData/testData.scss

@@ -0,0 +1,591 @@
+.page {
+  padding: 60px 0px;
+  width: 100%;
+  height: 100%;
+  background: rgba(237,239,247,1);
+}
+.testData {
+  width: 1180px;  
+  margin: 0 auto;
+  display: flex;
+  flex-direction: column;
+  .testList {
+    width: 100%;
+    height: 148px;
+    background: white;
+    margin-top: 16px;
+    border-radius:6px;
+    .testProject {
+      margin-top: 16px;
+      margin-left: 135px;
+      .el-button{
+        padding: 7px 20px;
+        position: relative
+      }
+      .el-button--primary{
+        width: 144px;
+        height: 32px;
+        border-radius: 17px;
+        font-size: 14px;
+        color: #4E5DFF;
+        background:rgba(245,248,255,1);
+        border-color: #fff;
+      }
+      .el-button--primary:focus,.el-button--primary:hover {
+        background: #4E5DFF;
+        border-color: #4E5DFF;
+        color: #fff;
+      }
+    }
+    .testItem {
+      width: calc(100% - 200px);
+      height: 78px;
+      display: flex;
+      flex-direction: row;
+      margin-left: 100px;
+      margin-top: 16px;
+      .itemArrow {
+        width: 30px;
+        height: 100%;
+        margin-top: 20px;
+        cursor: pointer;
+        font-size: 30px;
+        color: #999999;
+      }
+      .testContent {
+        flex-grow: 2;
+        display: flex;
+        flex-direction: row;
+        overflow-x: auto;
+        .testTopic {
+          width: 145px;
+          height: 68px;
+          margin:0px 5px;
+          flex-shrink: 0;
+          background:rgba(237,237,237,1);
+          border-radius:2px;
+          font-size:14px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(100,107,129,1);
+          line-height:20px;
+          padding: 5px;
+          box-sizing: border-box;
+          position: relative;
+          .testSel {
+            position: absolute;
+            bottom: 2px;
+            right: 2px;
+            width: 16px;
+            height: 16px;
+          }
+        }
+        .testTopicSel {
+          background:rgba(78,93,255,1);
+          color:rgba(255,255,255,1);
+        }
+      }
+    }
+  }
+  .testTip {
+    width: 100%;
+    height: 80px;
+    line-height: 80px;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    font-size:18px;
+    font-family:PingFangSC-Medium,PingFang SC;
+    font-weight:500;
+    color:rgba(51,51,51,1);
+    .switchItem {
+      display: flex;
+      flex-direction: row;
+      height: 40px;
+      background:rgba(255,255,255,1);
+      border-radius:20px;
+      .switch {
+        width: 80px;
+        height: 40px;
+        line-height: 40px;
+        background:rgba(255,255,255,1);
+        border-radius:20px;
+        text-align: center;
+        font-size:14px;
+        font-family:PingFangSC-Regular,PingFang SC;
+        font-weight:400;
+        color:rgba(78,93,255,1);
+        cursor: pointer;
+      }
+      .switchSelected {
+        color:rgba(255,255,255,1);
+        background:rgba(78,93,255,1);
+      }
+    }
+    .analyseBag {
+      display: flex;
+      flex-direction: row;
+      width:340px;
+      height:34px;
+      background:rgba(255,255,255,1);
+      border-radius:17px;
+      .analyseBagTitle {
+        width:64px;
+        height:34px;
+        border-radius:17px;
+        text-align: center;
+        font-size:14px;
+        font-family:PingFangSC-Regular,PingFang SC;
+        font-weight:400;
+        color:rgba(255,255,255,1);
+        line-height:34px;
+        .el-button{
+          padding: 7px 0px;
+          position: relative
+        }
+        .el-button--primary{
+          width:64px;
+          height:34px;
+          border-radius: 17px;
+          font-size: 14px;
+          color: #fff;
+          background: #4E5DFF;
+          border-color: #fff;
+        }
+        .el-button--primary:focus,.el-button--primary:hover {
+          background: #4E5DFF;
+          border-color: #4E5DFF;
+          color: #fff;
+        }
+      }
+      .analyseBagList {
+        height: 34px;
+        margin-top: -24px;
+        .el-cascader {
+          width: 260px;
+          background:rgba(241,241,241,1);
+          line-height: 34px;
+          font-size:14px;
+          color:rgba(51,51,51,1);
+          .el-input__inner {
+            height: 34px;
+            line-height: 34px;
+            background:rgba(255,255,255,1);
+            border: 0px;
+          }
+          .el-input__icon {
+            line-height: 34px;
+          }
+        }
+      }
+    }
+  }
+  .answer {
+    width: 100%;
+    background: white;
+    border-radius:6px;
+    padding: 24px 120px;
+    box-sizing: border-box;
+    .filter {
+      width: 100%;
+      height: 40px;
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      .filterIcon {
+        width: 100px;
+        height: 40px;
+        cursor: pointer;
+      }
+      .rightFilter {
+        display: flex;
+        flex-direction: row;
+        .rightFilterItem {
+          width: 48px;
+          height: 24px;
+          font-size:12px;
+          font-family:PingFangSC-Regular,PingFang SC;
+          font-weight:400;
+          color:rgba(153,160,182,1);
+          line-height:24px;
+          border-radius:14px;
+          border:1px solid rgba(153,160,182,1);
+          text-align: center;
+          margin: 0px 4px;
+          cursor: pointer;
+        }
+        .rightFilterItemSel {
+          color:rgba(78,93,255,1);
+          border:1px solid rgba(78,93,255,1);
+        }
+      }
+    }
+    .filterContent {
+      width: 100%;
+      .filterView {
+        background:rgba(250,250,250,1);
+        border-radius:6px;
+        padding: 24px 16px;
+      }
+      .filterItem {
+        width: 100%;
+        margin: 4px 0px;
+        display: flex;
+        flex-direction: row;
+        box-sizing: border-box;
+        .filterTitle {
+          margin-top: 5px;
+          margin-left: 8px;
+          font-size:14px;
+          font-family:PingFangSC-Regular,PingFang SC;
+          font-weight:400;
+          color:rgba(51,51,51,1);
+          line-height:20px;
+          flex-shrink: 0;
+          width: 57px;
+        }
+        .filterAnswer {
+          margin-left: 10px;
+          flex-shrink: 0;
+          margin-right: 10px;
+          .el-cascader {
+            width: 320px;
+            background:rgba(241,241,241,1);
+            line-height: 30px;
+            font-size:14px;
+            color:rgba(51,51,51,1);
+            .el-input__inner {
+              height: 30px;
+              line-height: 30px;
+              background:rgba(241,241,241,1);
+            }
+            .el-input__icon {
+              line-height: 30px;
+            }
+          }
+        }
+        .filterReply {
+          display: flex;
+          align-items:center;
+        }
+      }
+      .addfilter{
+        width:320px;
+        height:30px;
+        border:1px dashed rgba(202,204,210,1);
+        margin-left: 74px;
+        margin-top: 8px;
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+        cursor: pointer;
+        .addfilterIcon {
+          width: 74px;
+          height: 18px;
+        }
+      }
+      .filterDel {
+        cursor: pointer;
+        display: flex;
+        align-items:center;
+        color: #646B81;
+        margin-left: 10px;
+      }
+      .filterSave {
+        height: 28px;
+        margin-left: 74px;
+        margin-top: 16px;
+        display: flex;
+        text-align: center;
+        .saveLocation {
+          width:80px;
+          height:28px;
+          background:rgba(78,93,255,1);
+          border-radius:14px;
+          font-size:14px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(255,255,255,1);
+          line-height:28px;
+        }
+        .saveOnLine {
+          margin-left: 16px;
+          font-size:14px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(78,93,255,1);
+          line-height:28px;
+          width:200px;
+          height:28px;
+          border-radius:14px;
+          border:1px solid rgba(78,93,255,1);
+          cursor: pointer;
+        }
+      }
+      .filterResult {
+        font-size:14px;
+        font-family:PingFangSC-Regular,PingFang SC;
+        font-weight:400;
+        color:rgba(51,51,51,1);
+        line-height:20px;
+        border-bottom: 1px dashed #E8E8E8;
+        padding-top: 4px;
+        padding-bottom: 15px;
+      }
+    }
+    .result {
+      .resultItem {
+        margin-top: 36px;
+        padding-bottom: 20px;
+        border-bottom:1px dashed rgba(202,204,210,1);
+        .resultTitle {
+          font-size:18px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(51,51,51,1);
+          line-height:25px;
+        }
+        .resultTable {
+
+          border-radius:4px;
+          border:1px solid rgba(232,232,232,1);
+          margin-top: 8px;
+        }
+        .tableHeader {
+          display: flex;
+          flex-direction: row;
+          height: 32px;
+          background:rgba(250,250,250,1);
+          border-radius:4px 0px 0px 0px;
+          font-size:14px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(0,0,0,0.85);
+          line-height:21px;
+          align-items:flex-end;
+          .option {
+           flex-grow: 2;
+           padding-left: 25px;
+           box-sizing: border-box;
+          }
+          .numbers {
+            width:236px;
+            height: 100%;
+            padding-top: 8px;
+            padding-left: 25px;
+            box-sizing: border-box;
+            border-left:1px solid rgba(232,232,232,1);
+            border-right:1px solid rgba(232,232,232,1);
+          }
+          .percent {
+            width: 408px;
+            padding-left: 25px;
+            box-sizing: border-box;
+          }
+        }
+        .tableRow {
+          display: flex;
+          flex-direction: row;
+          height: 32px;
+          font-size:14px;
+          font-family:PingFangSC-Regular,PingFang SC;
+          font-weight:400;
+          color:rgba(0,0,0,0.65);
+          line-height:21px;
+          align-items:flex-end;
+          .option {
+           flex-grow: 2;
+           height: 100%;
+           padding-top: 8px;
+           padding-left: 25px;
+           box-sizing: border-box;
+           border-top:1px solid rgba(232,232,232,1);
+          }
+          .numbers {
+            width:236px;
+            height: 100%;
+            padding-top: 8px;
+            padding-left: 25px;
+            box-sizing: border-box;
+            border-left:1px solid rgba(232,232,232,1);
+            border-right:1px solid rgba(232,232,232,1);
+            border-top:1px solid rgba(232,232,232,1);
+          }
+          .percent {
+            width: 408px;
+            height: 100%;
+            padding-top: 8px;
+            padding-left: 25px;
+            box-sizing: border-box;
+            border-top:1px solid rgba(232,232,232,1);
+          }
+        }
+      }
+    }
+    .chart {
+      display: flex;
+      flex-direction: column;
+      margin-top: 30px;
+      .chartItem {
+        display: flex;
+        flex-direction: column;
+        .chartTitle {
+          font-size:18px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(51,51,51,1);
+          line-height:25px;
+        }
+        .chartData {
+          width: 100%;
+          height: 400px;
+        }
+      }
+    }
+    
+  }
+  .crossAnalyse {
+    width: 100%;
+    background: white;
+    border-radius:6px;
+    padding: 24px 120px;
+    box-sizing: border-box;
+    .crossFilter{
+      background:rgba(250,250,250,1);
+      border-radius:6px;
+      display: flex;
+      flex-direction: row;
+      justify-content: center;
+      flex-wrap:wrap;
+      .xyFilter {
+        width: 360px;
+        .el-cascader {
+          width: 320px;
+          background:rgba(241,241,241,1);
+          line-height: 30px;
+          font-size:14px;
+          color:rgba(51,51,51,1);
+          .el-input__inner {
+            height: 30px;
+            line-height: 30px;
+            background:rgba(241,241,241,1);
+          }
+          .el-input__icon {
+            line-height: 30px;
+          }
+        }
+        .addfilter{
+          width:320px;
+          height:30px;
+          border:1px dashed rgba(202,204,210,1);
+          margin-top: 8px;
+          display: flex;
+          flex-direction: row;
+          justify-content: center;
+          align-items: center;
+          cursor: pointer;
+          .addfilterIcon {
+            width: 74px;
+            height: 18px;
+          }
+        }
+      }
+      .crossFilterTitle {
+        font-size:14px;
+        font-family:PingFangSC-Medium,PingFang SC;
+        font-weight:500;
+        color:rgba(51,51,51,1);
+        line-height:20px;
+      }
+      .crossFilterSubTitle {
+        font-size:12px;
+        font-family:PingFangSC-Regular,PingFang SC;
+        font-weight:400;
+        color:rgba(51,51,51,1);
+        line-height:20px;
+      }
+      .analyse {
+        width: 100%;
+        margin: 16px 0px;
+        display: flex;
+        flex-direction: row;
+        .startAnalyse {
+          margin-left: 90px;
+          width:80px;
+          height:28px;
+          background:rgba(78,93,255,1);
+          border-radius:14px;
+          font-size:14px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(255,255,255,1);
+          line-height:28px;
+          text-align: center;
+        }
+        .analyseTip {
+          font-size:12px;
+          font-family:PingFangSC-Regular,PingFang SC;
+          font-weight:400;
+          color:rgba(255,0,0,1);
+          line-height:28px;
+          margin-left: 8px;
+        }
+      }
+    }
+    .crossAnalyseTable {
+      .crossAnalyseTitle {
+        font-size:18px;
+        font-family:PingFangSC-Medium,PingFang SC;
+        font-weight:500;
+        color:rgba(51,51,51,1);
+        line-height:25px;
+        margin-top: 32px;
+      }
+      .crossAnalyseChart {
+        width: 100%;
+        margin: 8px 0px;
+      }
+      .table{
+        border-radius:4px;
+        border-top:1px solid rgba(232,232,232,1); 
+        border-left:1px solid rgba(232,232,232,1); 
+      }
+      .caTable {
+        display: flex;
+        flex-direction: row;
+        .headerRow {
+          background:rgba(250,250,250,1);
+          border-radius:4px 0px 0px 0px;
+          font-size:14px;
+          font-family:PingFangSC-Medium,PingFang SC;
+          font-weight:500;
+          color:rgba(0,0,0,0.85);
+          line-height:21px;
+          align-items:flex-end;
+          padding-top: 8px;
+          padding-bottom: 12px;
+          box-sizing: border-box;
+          border-bottom: 1px solid #E8E8E8;
+          border-right: 1px solid #E8E8E8;
+        }
+        .tabkeRow {
+          font-size:14px;
+          font-family:PingFangSC-Regular,PingFang SC;
+          font-weight:400;
+          color:rgba(0,0,0,0.65);
+          line-height:21px;
+          align-items:flex-end;
+          padding-top: 8px;
+          padding-bottom: 1px;
+          padding-left: 5px;
+          box-sizing: border-box;
+          border-bottom: 1px solid #E8E8E8;
+          border-right: 1px solid #E8E8E8;
+        }
+        
+      }
+    }
+  }
+}

+ 7 - 0
src/views/testData/testData.vue

@@ -0,0 +1,7 @@
+<template src='./testData.html'>
+</template>
+<script src="./testData.js">
+</script>
+<style lang="scss">
+@import "./testData.scss";
+</style>