前言

问卷调查表也是目前前端比较常见的开发项目,目前比较成熟的现成的问卷调查工具有番茄表单,问卷星等。那么如果要自己实现一个类型的问卷项目,应该如何入手呢,本文主要分享通过 vue 封装一个调查问卷组件。有了这个组件,基本调查问卷形式(包含填空,单选,多选形式的)都可以直接使用。本组件的封装是建立在element ui的 el-alert 组件、el-form-item组件、el-radio-group组件、el-radio组件、el-checkbox-group组件及el-checkbox组件的基础上,其实也就是对element ui 的单选多选组件进行二次封装,可以直接用于调查问卷。

一、Questionnaire 组件

组件说明:
实现问卷调查。

效果展示:
在这里插入图片描述
在这里插入图片描述

二、使用案例

<template>
<div>
    <el-questionnaire
      ref="mychild"
      :objSource="displayObj"
      :dataSource="dataSource"
      :load="loading"
      :item="item"
      :isDisabled="isDisabled"
      :isPlaceholder="isPlaceholder"
      btnText="提交"
    />
</template>
<script>
 export default{
    data(){
          return {
        item:{name:"问卷调查",status:"edit"},
        isDisabled:false,
        loading:false,
        isPlaceholder:"",
        dataSource: [
          {
            title: '一、基本情况',
            shortOption: [
              {label: "姓名", paramStr: "name", placeholder: "请输入姓名", value: "", errorMsg: "请输入姓名"},
              {label: '电话', paramStr: "mobile", placeholder: "请输入电话", value: "", errorMsg: "请输入电话"}
            ],
            isChildAnswer: "1",
            value: "1",
          },
          {
            title: '二、工作情况', shortOption: [],
            choiceOption: [
              {
                value: [],
                paramStr: "gradate",
                title: "工作几年?",
                type:"checkbox",
                list: ['1年-3年', "3年-5年", "5年以上"],
                errorMsg: "请选择工作年限,如果选择了其他,请填写"
              },
              {
                value: "",
                paramStr: "job",
                isOther: true,
                title: "从事什么职业",
                otherValue: "",
                list: ['前端开发', "后端开发", "测试", "产品经理"],
                errorMsg: "请选择所从事的职业"
              },
            ],
            isChildAnswer: "1",
            value: "1",
          },
          {
            title: '三、其他情况', shortOption: [],
            choiceOption: [
              {
                value: "",
                paramStr: "fruit",
                title: "是否喜欢吃水果",
                otherValue: "",
                isChildAnswer: "是",
                list: ['是', '否'],
                errorMsg: "请选择是否喜欢吃水果",
                shortOption: [
                  {label: "最喜欢的水果种类", paramStr: "fruit_kind", placeholder: "请输入最喜欢的水果种类", value: "", errorMsg: "请输入最喜欢的水果种类"}
                ],
                choiceOption: [{
                  value: "",
                  paramStr: "fruit_link",
                  title: "喜欢吃的水果",
                  otherValue: "",
                  list: ['苹果', '香蕉', '梨子'],
                  errorMsg: "请选择喜欢吃的水果"
                }],
              },
              {
                value: [],
                type:"checkbox",
                paramStr: "sport",
                title: "喜欢什么运动",
                isOther: true,
                otherValue: "",
                list: ['篮球', '足球', '羽毛球'],
                errorMsg: "请选择喜欢的运动"
              },
            ],
            isChildAnswer: "1",
            value: "1",
          }
        ],
        displayObj:{},
      }
    },
    },
    methods:{
      
    }
}
</script>

三、API 使用指南

属性说明类型默认值
objSource反显答案的数据源Object{}
dataSource题目的数据源Array[]
load初始加载的loading图Booleantrue
item包含问卷名称以及是反显状态还是编辑状态Object{}
isDisabled是否禁用Booleanfalse
isPlaceholder是否显示提示文字Booleantrue
btnText提交的按钮文字String提交

item的选项:

属性说明类型默认值
name问卷标题名称String问卷调查
status问卷状态,是编辑还是反显答案Stringedit

dataSource题目数据源的选项

属性说明类型默认值
title标题String“”
choiceOption选择题的问卷题目集合Array[]
shortOption填空题的问卷题目集合Array[]
isChildAnswer是否有子数据以及子数据出现的答案any
value用户选中的值String

choiceOption选择题的问卷题目集合参数说明

属性说明类型默认值
value用户选中的值String
paramStr需要给后台传的字段String
title题目标题String
list选择题的选项数组Array[]
errorMsg对非空校验的提示框String
isChildAnswer是否展示第二级问卷的答案String
isOther是否有其他选项Booleantrue
otherValue其他选项的答案String

shortOption填空题的问卷题目集合参数说明

属性说明类型默认值
label填空题问题String“”
paramStr需要给后台传的字段String
placeholder输入框提示文字String
value用户输入的值any
errorMsg对非空校验的提示框String
isChildAnswer是否展示第二级问卷的答案any
isArea是否是textarea多行输入框Booleantrue

备注:isChildAnswer与value结合使用,两者相等时出现第二级问卷。比如是否喜欢吃水果,答案为是。(isChildAnswer设置为‘是’),则出现喜欢吃什么样的水果调查,如果选了不是,则不进行下一级答问。

四、源代码

List.vue(用于填空题)

<template>
  <div
    :class="disabled == 'disabled'?'list-bg-disabled':(item.value==''?'':'list-bg')">
  <div class="cm-plr-10 cm-bottom">
  <div class="cm-flex cm-fw-bold cm-ai-c" v-if="!item.isArea">
    <label for=""><span class="cm-c-red" v-if="item.errorMsg"> * </span>
      {{item.label}}
    </label>
    <input v-model="item.value"
           :placeholder="isPlaceholder!='无'?item.placeholder:isPlaceholder"
           class="list-input" :disabled="disabled"/>
  </div>
    <div class="cm-fw-bold" v-if="item.isArea">
      <div class="cm-pt-10"><span class="cm-c-red" v-if="item.errorMsg"> * </span>{{item.label}}</div>
      <textarea v-model="item.value"
                maxlength="500"
                :placeholder="isPlaceholder!='无'?item.placeholder:isPlaceholder"
                :class="disabled == 'disabled'?'list-textarea-disabled':(item.value!=''?'list-textarea-value':'list-textarea')"
                :disabled="disabled"
      /></textarea>
    </div>
    <el-alert v-if="item.value == ''&& isShow && item.errorMsg"
              :title="item.errorMsg"
              type="error" show-icon
              effect="light">
    </el-alert>
  </div>
  </div>
</template>
<script>
  import '../index.css';
  export default {
    name: 'List',
    data () {
      return {

      }
    },
    props: {
      item: {
        type: Object,
        default: {}
      },
      isShow: {
        type: Boolean,
        default: false
      },disabled:{
        default: false
      },isPlaceholder:{
        type: String,
        default: ""
      }
    },
    methods:{},
    created(){},
  }
</script>
<style scoped>
  .list-input{
    height: 3rem;
    text-align: right;
    flex: 1;
    font-size: 0.875rem;
    color: #000;
    opacity:1
  }
  input:disabled,input[disabled]{
    color: #000;
    opacity:1
  }
  textarea:disabled,textarea[disabled]{
    color: #000;
    opacity:1
  }
  .list-textarea{
    font-size: 0.875rem;
    color: #333;
    width: 100%;
    border: none;
    margin: 0.5rem 0;
    background: #fff;
    outline: none;
  }
  .list-textarea-value{
    font-size: 0.875rem;
    color: #333;
    width: 100%;
    border: none;
    margin: 0.5rem 0;
    background: #f5f5f9;
    outline: none;
  }
  .list-textarea-disabled{
    background-color: #f5f5f5;
    font-size: 0.875rem;
    color: #333;
    width: 100%;
    border: none;
    margin: 0.5rem 0;
    outline: none;
  }
  .list-bg{
    background: #f5f5f5;
  }
  .list-bg-disabled{
    background-color: #f5f5f5;
  }
  input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{
    font-size: 0.875rem;
  }
</style>

Select.vue(用于单选和多选)

<template>
  <div>
  <el-form-item class="cm-bottom  sel-mar-10 cm-fw-bold">
    <div><span class="cm-c-red" v-if="items.errorMsg">* </span>{{items.title}}</div>
    <el-radio-group v-model="items.value"  v-if="items.type != 'checkbox'" class="cm-width-full">
        <el-radio :label="item"  v-for="(item,index) in items.list" :disabled="disabled" :key="index" class="sel-width-35"></el-radio>
      <div class="cm-mb-10 cm-flex cm-ai-c"  v-if="items.isOther">
        <el-radio label="其他"  class="sel-width-35" :disabled="disabled"></el-radio>
        <input class="sel-input" v-model="items.otherValue" :disabled="disabled"  placeholder="请输入" v-if="items.value == '其他'"/>
      </div>
      <el-alert v-if="(items.value == ''||items.value == '其他' && !items.otherValue) && isShow && items.errorMsg"
        :title="items.errorMsg"
        type="error" show-icon
        effect="light">
      </el-alert>
    </el-radio-group>
    <el-checkbox-group v-model="items.value"  v-if="items.type == 'checkbox'" class="cm-width-full sel-line-height">
        <el-checkbox name="type" :disabled="disabled"   :label="item"  v-for="(item,index) in items.list" :key="index" class="sel-width-35"></el-checkbox>
      <div class="cm-mb-10 cm-flex cm-ai-c"  v-if="items.isOther">
        <el-checkbox label="其他"   :disabled="disabled" class="sel-width-35 sel-checkbox-mr"></el-checkbox>
        <input class="sel-input" maxlength="20" v-model="items.otherValue" :disabled="disabled"  placeholder="请输入"   v-if="items.value &&(items.value != null) && items.value.indexOf('其他')>-1"/>
      </div>
      <el-alert v-if="(items.value && items.value.length == 0||(items.value.indexOf('其他')>-1 && !items.otherValue)) && isShow && items.errorMsg"
                :title="items.errorMsg"
                type="error" show-icon
                effect="light"
      >
      </el-alert>
    </el-checkbox-group>
  </el-form-item>
    <slot v-if="items.value == items.isChildAnswer"></slot>
  </div>
</template>
<script>
  import '../index.css';
  let self;
  export default {
    name: 'Select',
    data () {
      return {

      }
    },
    props: {
      items: {
        type: Object,
        default: {}
      },
      isShow: {
        type: Boolean,
        default: false
      },disabled:{
        default: false
      },type:{
        type: String,
        default: ""
      }
    },
    created(){
      self=this;
    },
    methods:{},
  }
</script>
<style>
  .sel-width-35{
    width: 40%;
    line-height: 40px;
  }
  .sel-checkbox-mr{
    margin-right: 30px!important;
  }
  .sel-mar-10{
    padding:0 1rem;
    margin-bottom: 0;
  }
  .sel-input{
    -webkit-appearance: none;
    border-radius: 4px;
    border: 1px solid #DCDFE6;
    box-sizing: border-box;
    color: #606266;
    font-weight: 500;
    font-size: 0.875rem;
    opacity:1;
    outline: 0;
    height: 2rem;
    padding: 0 0.3rem;
    width: 150px;
  }
  input:disabled,input[disabled]{
    color: #606266;
    font-weight: 500;
    opacity:1
  }
  textarea:disabled,textarea[disabled]{
    color: #606266;
    font-weight: 500;
    opacity:1
  }
  .sel-line-height{
    line-height: 1;
  }
  .el-checkbox__input.is-disabled+span.el-checkbox__label{
    color: #606266!important;
    opacity:1
  }
  .el-radio__input.is-disabled+span.el-radio__label{
    color: #606266!important;
    opacity:1
  }
</style>

Questionnaire.vue

<template>
  <div  v-loading="load"
        element-loading-text="提交中,请稍候..."
        element-loading-spinner="el-icon-loading"
        v-loading.fullscreen.lock="load"
  >
    <div class="cm-flex cm-jc-c cm-ptb-08">
      <div class="cm-fw-bold cm-pr-10 cm-fs-12">{{item.name}}</div>
    </div>
    <el-form>
      <div v-for="itemOption in dataSource">
        <div class="cm-bottom cm-pad-08-10 cm-fw-bold cm-fs-11">{{itemOption.title}}</div>
        <el-list class="fs-0875" :isPlaceholder="isPlaceholder"  :item="item" :disabled="isDisabled" :isShow="isShow" v-for="(item,index) in itemOption.shortOption"
                 :key="item.label"></el-list>
        <el-select :items="list"  :disabled="isDisabled" :isShow="isShow" :key="index" v-for="(list,index) in itemOption.choiceOption">
          <div class="expand-style">
            <el-list :item="item" :disabled="isDisabled" :isPlaceholder="isPlaceholder"  :isShow="isShow" v-for="(item,index) in list.shortOption"
                     :key="item.label"></el-list>
            <el-select :items="list" :disabled="isDisabled" :isPlaceholder="isPlaceholder" :isShow="isShow" :key="index"
                       v-for="(list,index) in list.choiceOption"></el-select>
          </div>
        </el-select>
      </div>
      <el-form-item class="cm-fw-bold">
        <label class="cm-ml-10">其他建议 </label>
        <div class="cm-flex flex-fill">
            <textarea ref="textarea"  maxlength="500" name="" id=""
                      :placeholder="isPlaceholder!='无'?'请输入您的建议':isPlaceholder"
                      v-model="other_advice"
                      class="hos-textarea"
                      :disabled="isDisabled"
            ></textarea>
        </div>
      </el-form-item>
      <div class="hos-btn" @click="submitForm()" v-if="item.status=='edit'">{{btnText}}</div>
    </el-form>
  </div>
</template>
<script>
  import '../index.css';
  import select from './Select.vue';
  import list from './List.vue';
  let self;
  export default {
    name: 'ElQuestionnaire',
    components: {
      "el-select": select,
      "el-list": list
    },
    data () {
      return {
        other_advice: '',
        isShow:false
      }
    },
    props:{
      dataSource:{
          type:Array,
          default:[]
      }, 
      objSource:{
        type:Object,
        default:{}
      }, 
      load:{
        type:Boolean,
        default:true
      }, 
      item:{
        type:Object,
        default:{}
      },
      isDisabled:{
        type:String|Boolean,
        default:false
      },
      isPlaceholder:{
        type:String,
        default:""
      },
      btnText:{
        type:String,
        default:"提交"
      }
    },
    created(){
      self = this;
    },
    mounted(){
      var textarea = document.getElementsByTagName("textarea");
      //多行输入框高度自适应
      setTimeout(function () {
        for(var i=0;i<textarea.length;i++){
          textarea[i].style.height = textarea[i].scrollHeight + 'px';
          textarea[i].addEventListener('input',function (e) {
            e.target.style.height = 'auto';
            e.target.scrollTop = 0; //防抖动
            e.target.style.height = e.target.scrollHeight + 'px';
          })
        }
      },200)
    },
    methods: {
        //提交
      submitForm(){
        self.isShow = true;
        var arr = [];
        var obj = {};
        self.generate(self.dataSource,{},arr,obj);
        obj = Object.assign(obj,{"other_advice":self.other_advice});
        console.log(obj);
        this.$parent.submit(arr,obj);
      },
      //将数据源轮循
      generate: (list,displayObj,arr, obj) => {
        list.map((item) => {
          if(arr && obj){
            if (item && item.value !== undefined && item && item.paramStr !== undefined) {
              //多选如果有其他,将其他数值添加进去
              let value;
              //其他值不等于空并且不是填空
              if(item.otherValue != "" && item.otherValue != undefined && !item.label){
                if(item.type == "checkbox") {
                    if(!item.value.includes(item.otherValue)){
                      item.value.push(item.otherValue);
                    }
                    //有其他值反选值,但是其他label没有勾选,就将其他值去掉
                  if(item.value.includes(item.otherValue) && !item.value.includes('其他')){
                    item.value = item.value.filter((item1)=>{return item1 != item.otherValue});
                  }
                  value = item.value;
                } else {
                  if(item.otherValue && item.value=='其他'){
                    value = item.otherValue;
                  }
                }
              }else {
                  console.log(item);
                value = item.value;
                //如果其他值为空,但是选择了“其他”,则需要校验
                if(item.value.indexOf('其他')>-1||item.value=='其他'){
                  arr.push({"value": item.otherValue});
                }
              }
              obj = Object.assign(obj, {[item.paramStr]: value});
              if(item.errorMsg){
                arr.push({"value": item.value});
              }
            }
            if (item.isChildAnswer && item.value == item.isChildAnswer) {
              if (item.shortOption && item.shortOption.length > 0) {
                self.generate(item.shortOption, {},arr, obj);
              }
              if (item.choiceOption && item.choiceOption.length > 0) {
                self.generate(item.choiceOption, {},arr, obj);
              }
            }
          }else {
            if (item && item.value !== undefined && item && item.paramStr !== undefined) {
              if(displayObj[item.paramStr]){
                if(item.type == "checkbox" && displayObj[item.paramStr] && displayObj[item.paramStr].length>0){
                  item.value = displayObj[item.paramStr];
                  let allList =item.list.concat(displayObj[item.paramStr]);
                  item.value.map((res)=>{
                    if(item.list.indexOf(res)<0){
                      item.isOther = true;
                      if(item.otherValue!=res){
                        item.otherValue = res;
                      }
                    }
                  });
                  //value去重
                  item.value = item.value.filter((item1,index)=>{
                    return item.value && item1 && item.value.indexOf(item1)==index
                  })
                  //如果返回的值中有与页面值不同的则添加到页面值中
                  item.list = allList.filter((item1,index)=>{
                    return (allList.indexOf(item1))==index && item1 && item1!=item.otherValue && item1!='其他'
                  });
                }else if(item.list && item.type != "checkbox"){
                  if(item.list.indexOf(displayObj[item.paramStr])<0 && displayObj[item.paramStr]){
                    item.isOther = true;
                    item.value="其他";
                    item.otherValue = displayObj[item.paramStr];
                  }else{
                    item.value = displayObj[item.paramStr];
                  }
                }else {
                  item.value = displayObj[item.paramStr];
                }
              }
            }
            if (item.isChildAnswer && item.value == item.isChildAnswer) {
              if (item.shortOption && item.shortOption.length > 0) {
                self.generate(item.shortOption,displayObj);
              }
              if (item.choiceOption && item.choiceOption.length > 0) {
                self.generate(item.choiceOption,displayObj);
              }
            }
            if(displayObj.other_advice){
                self.other_advice = displayObj.other_advice;
            }
          }
        });
        return {obj, arr};
      }
      }
    }
</script>

<style>
  .expand-style {
    font-size: 0.875rem;
    /*background: #f5f5f5;*/
  }
  .fs-0875{
    font-size: 0.875rem;
  }
  .hos-btn {
    background: #409EFF;
    color: #fff;
    margin: 1rem;
    padding: 0.8rem 0;
    text-align: center;
    border-radius: 0.5rem;
  }

  .hos-textarea {
    margin: 0 1rem;
    word-break: break-all;
    resize: none;
    border-radius: 0.3rem;
    outline: none;
    line-height: 1rem;
    width: 100%;
    border: 1px solid #ddd;
    font-size: 0.8rem;
    color: #333;
    padding:0.5rem;
  }

</style>

公共样式 index.css

/*init*/
body,p{
  margin: 0;
  padding: 0;
}
html{
  /*font-size: 62.5%;*/
}
input{
  border:none;
  outline:none;
  background: none;
}
input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{
  color:#ccc;
}
/*layout*/
.cm-flex{
  display: flex;
}
.cm-flex-col{
  display: flex;
  flex-direction: column;
}
.flex-fill{
  flex: 1;
}
.cm-flex-dir{
  flex-direction: column;
}
.cm-jc-c{
  justify-content: center;
}
.cm-jc-sb{
  justify-content: space-between;
}
.cm-jc-sa{
  justify-content: space-around;
}
.cm-ai-c{
  align-items: center;
}
.cm-flex-row{
  display: flex;
  justify-content: center;
  align-items: center;
}
.cm-flex-col-c{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.cm-as-end{
  align-self: flex-end;
}
.cm-tx-c{
  text-align: center;
}
.cm-tx-l{
  text-align: left;
}
.cm-tx-r{
  text-align: right;
}

/*margin/padding*/
.cm-mt-02{
  margin-top: 0.2rem;
}
.cm-mt-03{
  margin-top: 0.3rem;
}
.cm-mt-05{
  margin-top:0.5rem;
}
.cm-mt-08{
  margin-top:0.8rem;
}
.cm-mt-10{
  margin-top: 1rem;
}
.cm-mt-12{
  margin-top: 1.2rem;
}
.cm-mt-20{
  margin-top: 2rem;
}
.cm-mar-10{
  margin: 1rem;
}
.cm-mb-10{
  margin-bottom: 1rem;
}
.cm-mb-20{
  margin-bottom: 2rem;
}
.cm-mb-05{
  margin-bottom:0.5rem;
}

.cm-mb-08{
  margin-bottom:0.8rem;
}
.cm-mtb-02{
  margin:0.2rem 0;
}
.cm-ml-10{
  margin-left: 1rem;
}
.cm-m-10{
  margin: 1rem;
}
.cm-ml-05{
  margin-left: 0.5rem;
}
.cm-ml-03{
  margin-left: 0.3rem;
}
.cm-mr-05{
  margin-right: 0.5rem;
}
.cm-mr-03{
  margin-right: 0.3rem;
}
.cm-mlr-03{
  margin-left: 0.3rem;
  margin-right: 0.3rem;
}
.cm-mlr-06{
  margin-left: 0.6rem;
  margin-right: 0.6rem;
}
.cm-mrl-percent1{
  margin-left: 3%;
  margin-right: 3%;
}
.cm-mlr-05{
  margin-left: 0.5rem;
  margin-right: 0.5rem;
}
.cm-mlr-10{
  margin-left: 1rem;
  margin-right: 1rem;
}
.cm-mtb-10{
  margin-top: 1rem;
  margin-bottom: 1rem;
}
.cm-mtb-08{
  margin-top: 0.8rem;
  margin-bottom: 0.8rem;
}
.cm-mtb-06{
  margin-top: 0.6rem;
  margin-bottom: 0.6rem;
}
.cm-m-05{
  margin: 0.5rem;
}
.cm-mr-10{
  margin-right: 1rem;
}
.cm-pt-03{
  padding-top: 0.3rem;
}
.cm-pt-05{
  padding-top: 0.5rem;
}
.cm-pt-10{
  padding-top: 1rem;
}
.cm-pb-10{
  padding-bottom: 1rem;
}
.cm-pb-05{
  padding-bottom: 0.5rem;
}
.cm-ptb-10{
  padding-top: 1rem;
  padding-bottom: 1rem;
}
.cm-p-05{
  padding: 0.5rem;
}
.cm-p-10{
  padding: 1rem;
}
.cm-plr-06{
  padding: 0 0.6rem;
}
.cm-plr-08{
  padding: 0 0.8rem;
}
.cm-pl-10{
  padding-left: 1rem;
}
.cm-pr-10{
  padding-right: 1rem;
}
.cm-plr-10{
  padding: 0 1rem;
}
.cm-plr-03{
  padding: 0 0.3rem;
}
.cm-plr-05{
  padding-left:0.5rem;
  padding-bottom: 0.5rem;
}
.cm-ptb-03{
  padding: 0.3rem 0;
}
.cm-ptb-05{
  padding: 0.5rem 0;
}
.cm-ptb-08{
  padding: 0.8rem 0;
}
.cm-pad-05-08{
  padding: 0.5rem 0.8rem;
}
.cm-pad-08-05{
  padding: 0.8rem 0.5rem;
}
.cm-pad-06-05{
  padding: 0.6rem 0.5rem;
}
.cm-pad-05-10{
  padding: 0.5rem 1rem;
}
.cm-pad-08-10{
  padding: 0.8rem 1rem;
}
/*font*/
.cm-fw-bold{
  font-weight: bold;
}
.cm-fs-06{
  font-size: 0.6rem;
}
.cm-fs-07{
  font-size: 0.7rem;
}
.cm-fs-08{
  font-size: 0.8rem;
}
.cm-fs-09{
  font-size: 0.9rem;
}
.cm-fs-10{
  font-size: 1rem;
}
.cm-fs-11{
  font-size: 1.1rem;
}
.cm-fs-12{
  font-size: 1.2rem;
}
.cm-fs-14{
  font-size: 1.4rem;
}
/*color*/
.cm-c-main{

}
.cm-c-red{
  color: red;
}
.cm-c-white{
  color: #fff;
}
.cm-c-gray{
  color: #999;
}
.cm-c-blue{
  color: #1890ff;
}
.cm-c-333{
  color: #333;
}
.cm-c-000{
  color: #000;
}
.cm-c-999{
  color: #999;
}
.cm-c-666{
  color: #666;
}
/*background*/
.cm-bc-main{

}
.cm-bc-white{
  background: #fff;
}
.cm-bg-white{
  background: #fff;
}
.cm-bottom{
  border-bottom: 1px solid #dddddd;
}
.cm-border-top{
  border-top: 1px solid #dddddd;
}
.cm-bottom-eee{
  border-bottom: 1px solid #eeeeee;
}
.cm-border-radius{
  border-radius: 50%;
}
.cm-img-20{
  width: 2rem;
  height: 2rem;
}
.cm-img-25{
  width: 2.5rem;
  height: 2.5rem;
}
.cm-img-30{
  width: 3rem;
  height: 3rem;
}
.cm-img-08{
  width: 0.8rem;
  height: 0.8rem;
}
.cm-img-10{
  width: 1rem;
  height: 1rem;
}
.cm-img-12{
  width: 1.2rem;
  height: 1.2rem;
}
.cm-img-13{
  width: 1.3rem;
  height: 1.3rem;
}
.cm-img-15{
  width: 1.5rem;
  height: 1.5rem;
}
.cm-width-full{
  width: 100%;
}
.cm-size-100{
  width: 100%;
  height: 100%;
}
* {
  -webkit-overflow-scrolling: touch;
}
Logo

前往低代码交流专区

更多推荐