小言_互联网的博客

Vue 组件封装之 Questionnaire 问卷调查

359人阅读  评论(0)

前言

问卷调查表也是目前前端比较常见的开发项目,目前比较成熟的现成的问卷调查工具有番茄表单,问卷星等。那么如果要自己实现一个类型的问卷项目,应该如何入手呢,本文主要分享通过 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图 Boolean true
item 包含问卷名称以及是反显状态还是编辑状态 Object {}
isDisabled 是否禁用 Boolean false
isPlaceholder 是否显示提示文字 Boolean true
btnText 提交的按钮文字 String 提交

item的选项:

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

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 是否有其他选项 Boolean true
otherValue 其他选项的答案 String

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

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

备注: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;
}

转载:https://blog.csdn.net/weixin_44135121/article/details/99712896
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场