survey-js问卷创建 vue3中的使用

800 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天

线上文档:surveyjs.io

surveyjs 问卷创建

image.png

<template>
  <div class="surveyCreator_box">
    <a-button class="button_class" type="primary" @click="router.go(-1)">返回</a-button>
    <div id="surveyCreator"></div>
  </div>
</template>
<script setup>
  import { onMounted } from 'vue';
  import 'survey-core/defaultV2.min.css';
  import 'survey-core/survey.i18n';
  import 'survey-creator-core/survey-creator-core.i18n';
  import 'survey-creator-core/survey-creator-core.min.css';
  import { SurveyCreator } from 'survey-creator-knockout';
  import { localization } from 'survey-creator-core';
  import { surveyLocalization } from 'survey-core';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useRouter } from 'vue-router';
  const router = useRouter();

  // 自定义属性按钮
  // Serializer.addProperty('radiogroup', {
  //   name: 'radioValue',
  //   type: 'itemvalues',
  //   // default: 0,
  //   choices: [
  //     { value: '3', text: '选项- 1' },
  //     { value: '2', text: '选项- 2' },
  //     { value: '1', text: '选项- 3' },
  //   ],
  //   category: 'choices',
  // });
  surveyLocalization.supportedLocales = ['zh-cn', 'en'];
  surveyLocalization.defaultLocale = 'zh-cn';
  // surveyLocalization.getProperty('radiogroup', '');
  localization.currentLocale = 'zh-cn';
  const translations = localization.getLocale('zh-cn');
  translations.ed.survey = '问卷';
  translations.pe.tabs.general = '常规';
  translations.pe.tabs.logo = '问卷标题 Logo';
  translations.pe.tabs.pages = '分页页面';
  translations.pe.tabs.logic = '逻辑';
  translations.pe.tabs.data = '数据';
  translations.pe.tabs.validation = '校验';
  translations.pe.tabs.layout = '布局';
  translations.qt.image = '图片';
  translations.qt.ranking = '排序';
  translations.qt.signaturepad = '签名';
  // const obj = router.currentRoute.value.query.obj;
  let obj = window.localStorage.getItem('question_data');
  console.log(obj);
  let question_text = {};
  question_text = JSON.parse(obj);

  onMounted(() => {
    document.documentElement.style.setProperty('--primary', '#6793ff');

    const creator = new SurveyCreator({
      showLogicTab: true,
      isAutoSave: false,
      questionTypes: ['radiogroup'],
      haveCommercialLicense: true,
    });
    // let blackList = ['visible', 'isRequired'];
    // creator.onShowingProperty.add(function (_, options) {
    //   if (options.obj.getType() == 'panel') {
    //     // Hide properties found in `blackList`
    //     options.canShow = blackList.indexOf(options.property.name) < 0;

    //     // Hide all properties except those found in `whiteList`
    //     // options.canShow = whiteList.indexOf(options.property.name) > -1;
    //   }
    // });
    const { createMessage } = useMessage();
    if (question_text.isUpdate === 'true') {
      // console.log(question_text.question_data);
      if (Object.keys(question_text.question_data).length === 0) {
        return createMessage.error('问卷为空');
      }
      // 回显问卷
      creator.text = JSON.stringify(question_text.question_data);
    }
    // 保存问卷
    creator.saveSurveyFunc = (saveNo, callback) => {
      if (creator.text == '{}') {
        return createMessage.error('问卷不得为空');
      }
      if (question_text.isUpdate === 'true') {
        createMessage.success('问卷编辑成功~');
      } else if (question_text.isUpdate === 'false') {
        createMessage.success('问卷新建成功~');
      } else {
        createMessage.warning('问卷状态不明,请重试~');
      }
      router.go(-1);
      callback(saveNo, true);
    };
    creator.render('surveyCreator');
  });
</script>
<style lang="less" scoped>
  .surveyCreator_box {
    width: 100%;
    height: 100%;
    padding: 15px 0px 15px 15px;
    // background-color: #fff;

    .button_class {
      margin-left: 93.5%;
      // margin-top: 10px;
      margin-bottom: 10px;
    }

    #surveyCreator {
      width: 100%;
      height: calc(100vh - 115px);
    }
  }
</style>

surveyjs 问卷回答

image.png

<html lang="en">
  <head>
    <title>问卷填答</title>
    <meta name="viewport" charset="UTF-8" content="width=device-width"/>
    <script src="./components/knockout-latest.js"></script>
    <script src="./components/survey.core.min.js"></script>
    <script src="./components/survey.i18n.min.js"></script>
    <script src="./components/survey-knockout-ui.js"></script>
    <link href="./components/defaultV2.min.css" type="text/css" rel="stylesheet"/>
    </head>
    <style>

      .sd-completedpage{
        background-color: #fbfbfd;

        /* background-image: url(../../src/assets/xxxxx.png);
        background-position: left;
        background-size: 100% 100%; */
      }
      /* .heard_box{
        color: #fff;
      } */
      .answer_class{
        margin: 0 auto;
        width: 100%;
        display: block;
        text-align: left;
        /* background-color: rgb(38, 25, 25); */
        display: flex;
        justify-content: center;
        align-items:center;
        flex-direction: column;
      }
      .answer_class_label{
        font-size: 16px;
        font-weight: 600;
        line-height: 2;
        width: 100%;
      }
      .answer_class_value{
        font-size: 14px;
        font-weight: normal;
      }
      /* form {
        margin: 0;
      } */
      .surveyResult{
        /* width: 100%; */
        /* height: calc(100vh - 165px); */
        display: block;
        /* background-image: url(../../src/assets/images/Graphs-Graph\ Sidebar.png);
        background-position: left;
        background-size: 100% 100%; */
        padding: 0 10px;
      }
      .sd-container-modern{
        width: 100vw;
        margin: 0;
        padding: 0;
      }
    </style>
  <body style="margin: 0; width: 100vw; height: 100vh">
    <div id="surveyElement" style="display:inline-block;width:100%;"></div>
    <div id="surveyResult"></div>
    <script type="text/javascript" src="./surveyQuestion.js"></script>
  </body>
</html>

Survey.locale = 'zh-cn'
Survey.StylesManager.applyTheme("defaultV2");
var json =  {
  "logoPosition": "right",
  "title": "测试问卷名称",
  "description": "测试问卷问卷描述文本",

  "completedHtml": "<h3 class='heard_box'>填答完毕,感谢您的参与!</h3>",
  "pages": [
      {
          "name": "页面1",
          "title": "页面名称1",
          "description": "页面1说明",
          "elements": [
              {
                  "type": "radiogroup",
                  "name": "页面1-问题1",
                  "choices": [
                      {
                          "value": "opt-1:10",
                          "text": "选项1"
                      },
                      {
                          "value": "opt-2:5",
                          "text": "选项2"
                      },
                      {
                          "value": "opt-3:5",
                          "text": "选项3"
                      }
                  ]
              },
              {
                  "type": "radiogroup",
                  "name": "页面1-问题2",
                  "choices": [
                      {
                          "value": "opt-1:10",
                          "text": "选项1"
                      },
                      {
                          "value": "opt-2:7",
                          "text": "选项2"
                      },
                      {
                          "value": "opt-3:3",
                          "text": "选项3"
                      }
                  ]
              }
          ]
      },
      {
          "name": "页面2",
          "title": "页面名称2",
          "description": "页面2说明",
          "elements": [
            {
                "type": "radiogroup",
                "name": "页面2-问题1",
                "choices": [
                    {
                        "value": "opt-1:100",
                        "text": "选项1"
                    },
                    {
                        "value": "opt-2:50",
                        "text": "选项2"
                    },
                    {
                        "value": "opt-3:50",
                        "text": "选项3"
                    }
                ]
            },
            {
                "type": "radiogroup",
                "name": "页面2-问题2",
                "choices": [
                    {
                        "value": "opt-1:80",
                        "text": "选项1"
                    },
                    {
                        "value": "opt-2:60",
                        "text": "选项2"
                    },
                    {
                        "value": "opt-3:30",
                        "text": "选项3"
                    }
                ]
            }
          ]
    }
  ],
  "pagePrevText": "上页",
  "pageNextText": "下页",
  "completeText": "提交"
}
window.survey = new Survey.Model(json);
// localization.currentLocale = 'zh-cn';

survey.onComplete.add(function (sender) {
  console.log('答案');
  console.log(sender.data);
    //  let a = {
    //   问题1: 'opt-1:10',
    //   问题2: 'opt-2:7',
    // };
    let b = [];
  
    for (const k in sender.data) {
      if (sender.data[k]) {
        b.push(+sender.data[k].split(':')[1]);
      }
    }
    let num = b.reduce((a, b) => a + b)
    let htmlText = `
    <span class="answer_class"> 
      <span class="answer_class_label"> 
       您的回答:
         <span class="answer_class_value">  ${JSON.stringify(sender.data, null, 3)} </span> 
      </span> 
      <span class="answer_class_label"> 
        您的得分:
          <span class="answer_class_value">  ${num}分 </span> </span> 
      </span>
   </span>
   `
   document.querySelector('#surveyResult').className = 'surveyResult'
  document.querySelector('#surveyResult').innerHTML = htmlText
});
var storageName = "question_data_value";
var timerId = 0;
function loadState(survey) {
  // Here should be the code to load the data from your database
  var storageSt = window.localStorage.getItem(storageName) || "";
  var res = {};
  if (storageSt) 
    res = JSON.parse(storageSt);
  

  // Set the loaded data into the survey.
  if (res.currentPageNo) 
    survey.currentPageNo = res.currentPageNo;
  
  if (res.data) 
    survey.data = res.data;
  
}
function saveState(survey) {
  var res = {
    currentPageNo: survey.currentPageNo,
    data: survey.data
  };
  // Here should be the code to save the data into your database
  window.localStorage.setItem(storageName, JSON.stringify(res));
}
survey.onCurrentPageChanged.add(function (survey, options) {
  saveState(survey);
});
survey.onComplete.add(function (sender, options) {
  // kill the timer
  clearInterval(timerId);
  // save the data on survey complete. You may call another function to store the final results
  saveState(sender);
});
// Load the initial state
loadState(survey);
// save the data every 10 seconds, it is a good idea to change it to 30-60 seconds or more.
timerId = window.setInterval(function () {
  saveState(survey);
}, 10000);
survey.render("surveyElement");

surveyjs 问卷分析

image.png

<template>
  <div class="analysis">
    <a-button class="btn" type="primary" @click="$router.go(-1)">返回</a-button>
    <div id="surveyVizPanel" />
  </div>
</template>

<script>
  import 'survey-analytics/survey.analytics.min.css';
  import { Model } from 'survey-core';
  import { VisualizationPanel } from 'survey-analytics';

  const surveyJson = {
    pages: [
      {
        name: '页面1',
        title: '页面名称1',
        description: '页面1说明',
        elements: [
          {
            type: 'radiogroup',
            name: '页面1-问题1',
            choices: [
              {
                value: 'opt-1:10',
                text: '选项1',
              },
              {
                value: 'opt-2:5',
                text: '选项2',
              },
              {
                value: 'opt-3:5',
                text: '选项3',
              },
            ],
          },
          {
            type: 'radiogroup',
            name: '页面1-问题2',
            choices: [
              {
                value: 'opt-1:10',
                text: '选项1',
              },
              {
                value: 'opt-2:7',
                text: '选项2',
              },
              {
                value: 'opt-3:3',
                text: '选项3',
              },
            ],
          },
        ],
      },
      {
        name: '页面2',
        title: '页面名称2',
        description: '页面2说明',
        elements: [
          {
            type: 'radiogroup',
            name: '页面2-问题1',
            choices: [
              {
                value: 'opt-1:100',
                text: '选项1',
              },
              {
                value: 'opt-2:50',
                text: '选项2',
              },
              {
                value: 'opt-3:50',
                text: '选项3',
              },
            ],
          },
          {
            type: 'radiogroup',
            name: '页面2-问题2',
            choices: [
              {
                value: 'opt-1:80',
                text: '选项1',
              },
              {
                value: 'opt-2:60',
                text: '选项2',
              },
              {
                value: 'opt-3:30',
                text: '选项3',
              },
            ],
          },
        ],
      },
    ],
  };

  const surveyResults = [
    {
      '页面1-问题1': 'opt-3:5',
      '页面1-问题2': 'opt-3:3',
      '页面2-问题1': 'opt-2:50',
      '页面2-问题2': 'opt-2:60',
    },
    {
      '页面2-问题1': 'opt-2:50',
      '页面2-问题2': 'opt-1:80',
      '页面1-问题1': 'opt-3:5',
      '页面1-问题2': 'opt-1:10',
    },
    {
      '页面1-问题1': 'opt-1:10',
      '页面1-问题2': 'opt-1:10',
      '页面2-问题1': 'opt-1:100',
      '页面2-问题2': 'opt-2:60',
    },
    {
      '页面1-问题1': 'opt-2:5',
      '页面1-问题2': 'opt-2:7',
      '页面2-问题1': 'opt-3:50',
      '页面2-问题2': 'opt-3:30',
    },
  ];

  const vizPanelOptions = {
    allowHideQuestions: false,
  };

  export default {
    name: 'survey-analytics',
    mounted() {
      const survey = new Model(surveyJson);
      const vizPanel = new VisualizationPanel(
        survey.getAllQuestions(),
        surveyResults,
        vizPanelOptions,
      );
      vizPanel.showHeader = false;
      vizPanel.render(document.getElementById('surveyVizPanel'));
    },
  };
</script>
<style lang="less" scoped>
  .analysis {
    width: 100%;
    height: 100%;
    padding: 15px 0;
    text-align: right;

    .btn {
      display: inline-block;
      margin-right: 30px;
    }

    #surveyVizPanel {
      text-align: left;
    }
  }
</style>

  • 有些依赖,需要单独下载。比如(survey-core/defaultV2.min.css)
  • 里面还有只读类型的问卷,暂时没用到过;
  • 有没有大神看一下,我的那个回答问卷的,demo为啥不能在vue3中使用
survey文档是纯英文,以我菜鸟只能弄到这个情况,希望大佬们有用到过的不吝赐教。survey文档是纯英文,以我菜鸟只能弄到这个情况,希望大佬们有用到过的不吝赐教。