天天看點

Vue實戰篇九:使用省市區級聯選擇插件

系列文章目錄

文章目錄

  • ​​系列文章目錄​​
  • ​​一、背景​​
  • ​​二、實作方式​​
  • ​​2.1 安裝中國省市區級聯資料​​
  • ​​2.2 代碼實作​​
  • ​​2.3 實作效果​​

一、背景

  • 在搭建公司注冊界面或進行送貨位址登記時,需要錄入省市區資訊,通過級聯選擇插件能極大提高使用者操作體驗:
  1. 級聯插件的資料集合有清晰的層級結構,
  2. 使用者可根據層次結構逐級檢視并進行選擇操作。

二、實作方式

2.1 安裝中國省市區級聯資料

  • ​​github位址​​
> npm install      

2.2 代碼實作

<template>
  <div class="page-register">
    <article class="header">
      <header>
        <el-avatar icon="el-icon-user-solid" shape="circle"></el-avatar>
        <span class="login">
          <em class="bold">已有賬号?</em>
          <a href="/login">
            <el-button type="primary" size="small">登入</el-button>
          </a>
        </span>
      </header>
    </article>
    <el-steps :active="active" finish-status="success">
      <el-step title="閱讀注冊協定"></el-step>
      <el-step title="填寫登入資訊"></el-step>
      <el-step title="填寫公司資訊"></el-step>
    </el-steps>
    <section>
      <el-form
        ref="ruleForm"
        :model="ruleForm"
        :rules="rules"
        label-width="100px"
        autocomplete="off"
        size="medium"
      >
        <div v-if="active == 0">
          <el-form-item prop="textarea">
            <el-input
              type="textarea"
              :autosize="{ minRows: 2, maxRows: 10 }"
              :readonly="true"
              v-html="ruleForm.textarea"
            >
            </el-input>
          </el-form-item>
          <el-form-item prop="agreed">
            <el-checkbox v-model="ruleForm.agreed">同意注冊協定</el-checkbox>
          </el-form-item>
        </div>
        <div v-if="active == 1"style="padding-top:">
          <el-form-item label="登入名" prop="name">
            <el-col :span="10">
              <el-input
                v-model="ruleForm.name"
                placeholder="請輸入登入使用者名稱"
              />
            </el-col>
          </el-form-item>

          <el-form-item label="郵箱" prop="email">
            <el-col :span="10">
              <el-input
                v-model="ruleForm.email"
                placeholder="輸入郵箱并點選發送驗證碼"
              />
            </el-col>
            <el-button
              :loading="codeLoading"
              :disabled="isDisable"
              size="small"
              round
              @click="sendMsg"
            >發送驗證碼</el-button>

            <span class="status">{{ statusMsg }}</span>
          </el-form-item>
          <el-form-item label="驗證碼" prop="code">
            <el-col :span="10">
              <el-input
                v-model="ruleForm.code"
                maxlength="6"
                placeholder="請登入郵箱接收驗證碼"
              />
            </el-col>
          </el-form-item>
          <!-- <el-form-item label="手機号" prop="phone">
            <el-col :span="10">
              <el-input v-model="ruleForm.phone" maxlength="11" />
            </el-col>
          </el-form-item> -->
          <el-form-item label="密碼" prop="pwd">
            <el-col :span="10">
              <el-input v-model="ruleForm.pwd" type="password" />
            </el-col>
          </el-form-item>
          <el-form-item label="确認密碼" prop="cpwd">
            <el-col :span="10">
              <el-input v-model="ruleForm.cpwd" type="password" />
            </el-col>
          </el-form-item>
        </div>
        <div v-if="active == 2">
          <el-form-item label="公司名稱" prop="supplierFullName" size="mini">
            <el-input v-model="ruleForm.supplierFullName" />

          </el-form-item>
          <el-row>
            <el-col :span="8">
              <el-form-item label="所在省市" prop="area" size="mini">
                <el-cascader
                  v-model="selectedOptions"
                  size="mini"
                  :options="options"
                  filterable
                  clearable
                  @change="handleChange"
                >

                </el-cascader>
              </el-form-item>
            </el-col>
            <el-col :span="16">
              <el-form-item label="詳細位址" prop="supplierAdd" size="mini">
                <el-input v-model="ruleForm.supplierAdd" />
              </el-form-item>
            </el-col>
          </el-row>

          <el-form-item label="供貨範圍" prop="supplierGoods" size="mini">
            <el-input v-model="ruleForm.supplierGoods" type="textarea" />
          </el-form-item>
          <el-row>
            <el-col :span="12">
              <el-form-item label="法人" prop="person" size="mini">
                <el-input v-model="ruleForm.person" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="注冊資金" prop="fund" size="mini">
                <el-input v-model="ruleForm.fund" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row>
            <el-col :span="8">
              <el-form-item label="電話" prop="telNo" size="mini">
                <el-input v-model="ruleForm.telNo" />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="傳真" prop="faxNo" size="mini">
                <el-input v-model="ruleForm.faxNo" />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="聯系人" prop="contact" size="mini">
                <el-input v-model="ruleForm.contact" />
              </el-form-item>
            </el-col>
          </el-row>
        </div>
      </el-form>
    </section>

    <div class="footer">
      <el-button
        v-if="active > 0"
        type="info"
        icon="el-icon-arrow-left"
        @click="prev"
      >上一步
      </el-button>
      <el-button
        v-if="active < step - 1"
        type="primary"
        icon="el-icon-arrow-right"
        @click="next"
      >下一步</el-button>
      <el-button
        v-if="active == step - 1"
        type="primary"
        @click="register"
      >注冊</el-button>
      <div class="error">{{ error }}</div>
    </div>
  </div>
</template>

<script>import { getEmailCode, register } from '@/api/srm/supplier'
import { encrypt } from '@/utils/rsaEncrypt'
import { regionData, CodeToText } from 'element-china-area-data'
export default {
  data() {
    return {
      step: 3,
      active: 0,
      statusMsg: '',
      error: '',
      isDisable: false,
      codeLoading: false,
      options: regionData,
      selectedOptions: [],
      ruleForm: {
        textarea: '<h1 style=" line-height:40px; font-size:24px; text-align:center;">“SRM采購平台”服務條例</h1>' +
          ' 6.1 如因系統維護或更新的需要而需暫停平台服務,“電子化采購平台”将盡可能事先進行通告 <br />' +
          '6.2 如發生下列任何一種情形,“電子化采購平台”有權随時中斷或終止向使用者提供本協定項下的平台服務而無需通知使用者: <br />' +
          '(a) 使用者提供的資料不真實; <br /> (b) 使用者違反本條例中規定的規則; <br />(c)其他嚴重違反“電子化采購平台”管理規定的行為。 <br />' +
          '6.3 除前款所述情形外,“電子化采購平台”保留随時修改其服務體系和價格而不需通知使用者的權利,對于所有服務的中斷或終止而造成的任何損失,“高子化采購平台”無需對使用者或任何第三方承擔任何責任。' +
          ' 6.1 如因系統維護或更新的需要而需暫停平台服務,“電子化采購平台”将盡可能事先進行通告 <br />' +
          '6.2 如發生下列任何一種情形,“電子化采購平台”有權随時中斷或終止向使用者提供本協定項下的平台服務而無需通知使用者: <br />' +
          '(a) 使用者提供的資料不真實; <br /> (b) 使用者違反本條例中規定的規則; <br />(c)其他嚴重違反“電子化采購平台”管理規定的行為。 <br />',
        agreed: false,
        name: '',
        code: '',
        pwd: '',
        cpwd: '',
        email: '',
        supplierFullName: '',
        supplierAdd: '',
        telNo: '',
        faxNo: '',
        contact: '',
        socialCreditCode: '',
        area: ''
      },
      rules: {
        agreed: [{
          validator: (rule, value, callback) => {
            if (value !== true) {
              callback(new Error('請确認同意注冊協定'))
            } else {
              callback()
            }
          },
          trigger: 'blur'
        }],
        name: [{
          required: true,
          type: 'string',
          message: '請輸入登入名',
          trigger: 'blur'
        }, { min: 3, message: '長度最少要3個字元', trigger: 'blur' }
        ],
        code: [{
          required: true,
          type: 'string',
          message: '請輸入驗證碼',
          trigger: 'blur'
        }],
        email: [{
          required: true,
          type: 'email',
          message: '請輸入郵箱',
          trigger: 'blur'
        }],
        // phone: [
        //   { required: true, message: '請輸入手機号碼', trigger: 'blur' },
        //   {
        //     validator: function(rule, value, callback) {
        //       if (/^1[34578]\d{9}$/.test(value) === false) {
        //         callback(new Error('請輸入正确的手機号'))
        //       } else {
        //         callback()
        //       }
        //     }, trigger: 'blur'
        //   }
        // ],
        pwd: [{
          required: true,
          message: '建立密碼',
          trigger: 'blur'
        }, { pattern: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,20}$/, message: '密碼必須同時包含數字與字母,且長度為 8-20位' }],
        cpwd: [{
          required: true,
          message: '确認密碼',
          trigger: 'blur'
        }, {
          validator: (rule, value, callback) => {
            if (value === '') {
              callback(new Error('請再次輸入密碼'))
            } else if (value !== this.ruleForm.pwd) {
              callback(new Error('兩次輸入密碼不一緻'))
            } else {
              callback()
            }
          },
          trigger: 'blur'
        }],
        area: [{
          required: true,
          type: 'string',
          message: '請選擇省市地區',
          trigger: 'blur'
        }],
        supplierFullName: [{
          required: true,
          type: 'string',
          message: '請輸入公司名稱',
          trigger: 'blur'
        }],
        telNo: [{
          required: true,
          type: 'string',
          message: '請輸入電話',
          trigger: 'blur'
        }]
      }
    }
  },
  layout: 'blank',
  methods: {
    sendMsg: function() {
      const self = this
      let namePass
      let emailPass
      let timerid
      // console.log(timerid)
      if (timerid) {
        return false
      }
      this.$refs['ruleForm'].validateField('name', (valid) => {
        namePass = valid
      })
      self.statusMsg = ''
      if (namePass) {
        return false
      }
      this.$refs['ruleForm'].validateField('email', (valid) => {
        emailPass = valid
      })
      // 向背景API驗證碼發送
      if (!namePass && !emailPass) {
        self.codeLoading = true
        self.statusMsg = '驗證碼發送中...'
        getEmailCode(self.ruleForm.name, self.ruleForm.email).then(res => {
          this.$message({
            showClose: true,
            message: '發送成功,驗證碼有效期5分鐘',
            type: 'success'
          })
          let count = 60
          self.ruleForm.code = ''
          self.codeLoading = false
          self.isDisable = true
          self.statusMsg = `驗證碼已發送,${count--}秒後重新發送`
          timerid = window.setInterval(function() {
            self.statusMsg = `驗證碼已發送,${count--}秒後重新發送`
            if (count <= 0) {
              console.log('clear' + timerid)
              window.clearInterval(timerid)
              self.isDisable = false
              self.statusMsg = ''
            }
          }, 1000)
        }).catch(err => {
          this.isDisable = false
          this.statusMsg = ''
          this.codeLoading = false
          console.log(err.response.data.message)
        })
      }
    },
    handleChange(value) {
      var loc = ''
      for (let i = 0; i < this.selectedOptions.length; i++) {
        loc += CodeToText[this.selectedOptions[i]] + '/'
      }
      this.ruleForm.area = loc
    },

    next: function() {
      if (this.active === 0) {
        this.$refs['ruleForm'].validateField('agreed', (valid) => {
          if (valid === '') {
            this.active++
          }
        })
      } else if (this.active === 1) {
        let namePass
        let emailPass
        let codePass
        let pwdPass
        let cpwdPass
        this.$refs['ruleForm'].validateField('name', (valid) => {
          namePass = valid
        })
        self.statusMsg = ''
        if (namePass) {
          return false
        }
        this.$refs['ruleForm'].validateField('email', (valid) => {
          emailPass = valid
        })
        if (emailPass) {
          return false
        }
        this.$refs['ruleForm'].validateField('code', (valid) => {
          codePass = valid
        })
        if (codePass) {
          return false
        }
        this.$refs['ruleForm'].validateField('pwd', (valid) => {
          pwdPass = valid
        })
        if (pwdPass) {
          return false
        }
        this.$refs['ruleForm'].validateField('cpwd', (valid) => {
          cpwdPass = valid
        })
        if (cpwdPass) {
          return false
        }
        this.active++
      }
    },
    prev: function() {
      this.$refs['ruleForm'].clearValidate()
      if (--this.active < 0) this.active = 0
    },

    // 使用者注冊
    register: function() {
      this.$refs['ruleForm'].validate((valid) => {
        if (valid) {
          const user = {
            userName: this.ruleForm.name,
            nickName: this.ruleForm.name,
            code: this.ruleForm.code,
            password: encrypt(this.ruleForm.pwd),
            email: this.ruleForm.email,
            phone: this.ruleForm.telNo,
            enabled: true,
            area: this.ruleForm.area,
            supplierFullName: this.ruleForm.supplierFullName,
            supplierAdd: this.ruleForm.supplierAdd,
            faxNo: this.ruleForm.faxNo,
            contact: this.ruleForm.contact,
            socialCreditCode: this.ruleForm.socialCreditCode
          }
          register(this.ruleForm.code, user).then(res => {
            this.$message({
              showClose: true,
              message: '注冊成功,正在跳轉到登入界面...',
              type: 'success'
            })
            setTimeout(() => {
              this.$router.push('/')
            }, 2000)
          }).catch(err => {
            console.log(err.response.data.message)
          })
        }
      })
    }
  }
}</script>

<style  rel="stylesheet/scss" lang="scss">.page-register {
  .header {
    //border-bottom: 2px solid rgb(235, 232, 232);
    min-width: 980px;
    color: #666;

    header {
      margin: 0 auto;
      padding: 10px 0;
      width: 980px;

      .login {
        float: right;
      }

      .bold {
        font-style: normal;
      }
    }
  }

  .register {
    color: #1890ff;
  }

  a {
    color: #1890ff;
    text-decoration: none;
    background-color: transparent;
    outline: none;
    cursor: pointer;
    transition: color 0.3s;
  }

  > section {
    margin: 0 auto 30px;
    padding-top: 30px;
    width: 980px;
    min-height: 300px;
    padding-right: 100px;
    box-sizing: border-box;

    .status {
      font-size: 12px;
      margin-left: 20px;
      color: #e6a23c;
    }

    .error {
      color: red;
    }
  }

  .row {
    background: silver;
  }

  .footer {
    text-align: center;
    padding-right: 100px;
  }
}</style>      

2.3 實作效果

繼續閱讀