366 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
<template>
 | 
						||
  <section class="personal-signature">
 | 
						||
    <ai-list v-if="!showPhonePage">
 | 
						||
      <ai-title slot="title" title="个人签名" :isShowBottomBorder="false"/>
 | 
						||
      <template #custom>
 | 
						||
        <div class="signaturePane">
 | 
						||
          <div class="signatureCard" v-for="(op,i) in signatures" :key="i">
 | 
						||
            <div class="default" v-if="op.isDefault==1">默认</div>
 | 
						||
            <div class="body">
 | 
						||
              <el-image :src="`data:image/png;base64,${op.signSealData}`"/>
 | 
						||
            </div>
 | 
						||
            <div class="footer">
 | 
						||
              <el-button type="text" :disabled="op.isDefault==1" @click.stop="handleSetDefault(op.id)">设为默认</el-button>
 | 
						||
              <hr/>
 | 
						||
              <el-button type="text" :disabled="op.isDefault==1||op.signType>0" @click.stop="handleDelete(op.id)">删除
 | 
						||
              </el-button>
 | 
						||
            </div>
 | 
						||
          </div>
 | 
						||
          <div class="signatureCard add" @click="dialog=true">
 | 
						||
            <ai-icon icon="iconAdd" size="32px"/>
 | 
						||
            <span>点击添加签名</span>
 | 
						||
          </div>
 | 
						||
        </div>
 | 
						||
      </template>
 | 
						||
    </ai-list>
 | 
						||
    <ai-dialog :visible.sync="dialog" v-bind="dialogConf" @onConfirm="handleSubmit"
 | 
						||
               @closed="form={},drawPlaceholder=true,qrCode=null,showQRCode=false,getSignatures()">
 | 
						||
      <ai-drawer v-if="hasAuthed" :seal.sync="sealData" ref="aiDrawer">
 | 
						||
        <template #tools>
 | 
						||
          <el-popover trigger="manual" v-model="showQRCode">
 | 
						||
            <el-image :src="qrCode"/>
 | 
						||
            <div class="writeInPhone" slot="reference" @click.stop="showQR">
 | 
						||
              <ai-icon icon="iconEwm"/>
 | 
						||
              <span>手机签名</span>
 | 
						||
            </div>
 | 
						||
          </el-popover>
 | 
						||
        </template>
 | 
						||
      </ai-drawer>
 | 
						||
      <el-form size="small" :model="form" ref="authForm" :rules="rules" class="authZone" v-else label-suffix=":"
 | 
						||
               label-width="100px">
 | 
						||
        <el-alert type="warning" title="第一次添加个人签名,需先进行实名认证" show-icon :closable="false"/>
 | 
						||
        <el-form-item label="姓名" prop="personName">
 | 
						||
          <el-input v-model="form.personName" clearable placeholder="姓名"/>
 | 
						||
        </el-form-item>
 | 
						||
        <el-form-item label="身份证号" prop="idNumber">
 | 
						||
          <el-input v-model="form.idNumber" clearable placeholder="身份证号"/>
 | 
						||
        </el-form-item>
 | 
						||
        <el-form-item label="手机号码" prop="signPhone">
 | 
						||
          <el-input v-model="form.signPhone" clearable placeholder="手机号码"/>
 | 
						||
        </el-form-item>
 | 
						||
      </el-form>
 | 
						||
    </ai-dialog>
 | 
						||
    <draw-in-phone v-if="showPhonePage"/>
 | 
						||
  </section>
 | 
						||
</template>
 | 
						||
 | 
						||
<script>
 | 
						||
import {mapState} from "vuex";
 | 
						||
import DrawInPhone from "./drawInPhone";
 | 
						||
 | 
						||
export default {
 | 
						||
  name: "AppPersonalSignature",
 | 
						||
  label: "个人签名",
 | 
						||
  components: {DrawInPhone},
 | 
						||
  provide() {
 | 
						||
    return {
 | 
						||
      signature: this
 | 
						||
    }
 | 
						||
  },
 | 
						||
  props: {
 | 
						||
    instance: Function,
 | 
						||
    dict: Object,
 | 
						||
    permissions: Function
 | 
						||
  },
 | 
						||
  computed: {
 | 
						||
    ...mapState(['user']),
 | 
						||
    hasAuthed() {
 | 
						||
      return this.signatures.length > 0
 | 
						||
    },
 | 
						||
    dialogConf() {
 | 
						||
      return this.hasAuthed ? {
 | 
						||
        title: "手写签名",
 | 
						||
        width: '720px'
 | 
						||
      } : {
 | 
						||
        title: "实名认证",
 | 
						||
        width: '520px'
 | 
						||
      }
 | 
						||
    },
 | 
						||
    rules() {
 | 
						||
      return {
 | 
						||
        personName: [{required: true, message: "请填写姓名"}],
 | 
						||
        signPhone: [
 | 
						||
          {required: true, message: "请填写手机号码"},
 | 
						||
          {pattern: /^1[3456789]\d{9}$/, message: "手机号码格式有误"}
 | 
						||
        ],
 | 
						||
        idNumber: [
 | 
						||
          {required: true, message: "请填写身份证号码"},
 | 
						||
          {validator: (r, v, cb) => cb(this.idCardNoUtil.checkIdCardNo(v) ? undefined : "身份证号码格式有误")}
 | 
						||
        ],
 | 
						||
      }
 | 
						||
    }
 | 
						||
  },
 | 
						||
  data() {
 | 
						||
    return {
 | 
						||
      signatures: [],
 | 
						||
      dialog: false,
 | 
						||
      form: {},
 | 
						||
      sealData: null,
 | 
						||
      qrCode: null,
 | 
						||
      showQRCode: false,
 | 
						||
      showPhonePage: false,
 | 
						||
      loading: false,
 | 
						||
    }
 | 
						||
  },
 | 
						||
  created() {
 | 
						||
    if (this.$route.query.userId && this.$route.hash == "#phone") {
 | 
						||
      this.showPhonePage = true
 | 
						||
    } else {
 | 
						||
      this.getSignatures()
 | 
						||
    }
 | 
						||
  },
 | 
						||
  methods: {
 | 
						||
    getSignatures() {
 | 
						||
      this.instance.post("/app/syssignaccount/list", null, {
 | 
						||
        params: {
 | 
						||
          size: 999
 | 
						||
        }
 | 
						||
      }).then(res => {
 | 
						||
        if (res?.data) {
 | 
						||
          this.signatures = res.data.records
 | 
						||
        }
 | 
						||
      })
 | 
						||
    },
 | 
						||
    handleSubmit() {
 | 
						||
      if (this.loading) return
 | 
						||
      if (this.hasAuthed && this.$refs['aiDrawer'].drawPlaceholder) return this.$message.error("请签名")
 | 
						||
      this.loading = true
 | 
						||
      if (this.hasAuthed) {
 | 
						||
        let sealData = this.sealData?.replace(/data:image\/png;base64,/, '')
 | 
						||
        sealData && this.instance({
 | 
						||
          url: '/app/syssignaccount/upload-sealdata',
 | 
						||
          headers: {"Content-Type": "application/json"},
 | 
						||
          method: 'post',
 | 
						||
          params: {userId: this.user.info.id},
 | 
						||
          data: sealData
 | 
						||
        }).then(res => {
 | 
						||
          this.loading = false
 | 
						||
          if (res?.code == 0) {
 | 
						||
            this.dialog = false
 | 
						||
            this.$message.success("添加成功!")
 | 
						||
            this.getSignatures()
 | 
						||
          }
 | 
						||
        }).catch(() => {
 | 
						||
          this.loading = false
 | 
						||
        })
 | 
						||
      } else {
 | 
						||
        this.$refs.authForm.validate(v => {
 | 
						||
          if (v) {
 | 
						||
            this.instance.post("/app/syssignaccount/register", {
 | 
						||
              signPhone: this.form.signPhone,
 | 
						||
              signType: 1,
 | 
						||
              userType: 0,
 | 
						||
              registerInfo: {...this.form},
 | 
						||
              style: {personTemplateType: 'RECTANGLE', sealColor: 'RED'}
 | 
						||
            }).then(res => {
 | 
						||
              this.loading = false
 | 
						||
              if (res?.code == 0) {
 | 
						||
                this.dialog = false
 | 
						||
                this.$message.success("认证成功!")
 | 
						||
                this.getSignatures()
 | 
						||
              }
 | 
						||
            }).catch(() => {
 | 
						||
              this.loading = false
 | 
						||
            })
 | 
						||
          }
 | 
						||
        })
 | 
						||
      }
 | 
						||
    },
 | 
						||
    handleSetDefault(id) {
 | 
						||
      this.$confirm("是否设置该签名为默认签名?").then(() => {
 | 
						||
        this.instance.post("/app/syssignaccount/default", null, {params: {id, listType: 0}}).then(res => {
 | 
						||
          if (res?.code == 0) {
 | 
						||
            this.$message.success("设置成功!")
 | 
						||
            this.getSignatures()
 | 
						||
          }
 | 
						||
        }).catch(() => 0)
 | 
						||
      })
 | 
						||
    },
 | 
						||
    handleDelete(ids) {
 | 
						||
      this.$confirm("是否删除该签名?").then(() => {
 | 
						||
        this.instance.post("/app/syssignaccount/delete", null, {params: {ids}}).then(res => {
 | 
						||
          if (res?.code == 0) {
 | 
						||
            this.$message.success("删除成功!")
 | 
						||
            this.getSignatures()
 | 
						||
          }
 | 
						||
        }).catch(() => 0)
 | 
						||
      })
 | 
						||
    },
 | 
						||
    showQR() {
 | 
						||
      if (!this.qrCode) {
 | 
						||
        let url = `${location.href}?userId=${this.user.info.id}#phone`
 | 
						||
        this.instance.post("/app/syssignaccount/draw-qrcode", null, {
 | 
						||
          params: {url}
 | 
						||
        }).then(res => {
 | 
						||
          if (res?.data) {
 | 
						||
            this.showQRCode = true
 | 
						||
            this.qrCode = res.data
 | 
						||
          }
 | 
						||
        })
 | 
						||
      } else {
 | 
						||
        this.showQRCode = !this.showQRCode
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
</script>
 | 
						||
 | 
						||
<style lang="scss" scoped>
 | 
						||
.personal-signature {
 | 
						||
  height: 100%;
 | 
						||
  background: #f3f6f9;
 | 
						||
  overflow: auto;
 | 
						||
 | 
						||
  ::v-deep .signaturePane {
 | 
						||
    display: flex;
 | 
						||
    gap: 16px;
 | 
						||
    flex-wrap: wrap;
 | 
						||
    padding: 16px;
 | 
						||
 | 
						||
    .signatureCard {
 | 
						||
      width: 290px;
 | 
						||
      height: 258px;
 | 
						||
      background: #FFFFFF;
 | 
						||
      border-radius: 4px;
 | 
						||
      position: relative;
 | 
						||
      display: flex;
 | 
						||
      flex-direction: column;
 | 
						||
      overflow: hidden;
 | 
						||
 | 
						||
      &.add {
 | 
						||
        justify-content: center;
 | 
						||
        align-items: center;
 | 
						||
        color: #666666;
 | 
						||
        cursor: pointer;
 | 
						||
 | 
						||
        .AiIcon {
 | 
						||
          width: 32px;
 | 
						||
          height: 32px;
 | 
						||
          font-size: 32px;
 | 
						||
        }
 | 
						||
 | 
						||
        & > span {
 | 
						||
          font-size: 12px;
 | 
						||
          line-height: 16px;
 | 
						||
        }
 | 
						||
      }
 | 
						||
 | 
						||
      .default {
 | 
						||
        position: absolute;
 | 
						||
        width: 56px;
 | 
						||
        height: 24px;
 | 
						||
        background: #3573FF;
 | 
						||
        border-radius: 0 0 4px 0;
 | 
						||
        top: 0;
 | 
						||
        left: 0;
 | 
						||
        text-align: center;
 | 
						||
        line-height: 24px;
 | 
						||
        font-size: 12px;
 | 
						||
        color: #FFF;
 | 
						||
      }
 | 
						||
 | 
						||
      .body {
 | 
						||
        min-height: 0;
 | 
						||
        flex: 1;
 | 
						||
        display: flex;
 | 
						||
        justify-content: center;
 | 
						||
        align-items: center;
 | 
						||
        padding: 25px;
 | 
						||
        pointer-events: none;
 | 
						||
 | 
						||
        .el-image {
 | 
						||
          width: 100%;
 | 
						||
          height: 100%
 | 
						||
        }
 | 
						||
      }
 | 
						||
 | 
						||
      .footer {
 | 
						||
        flex-shrink: 0;
 | 
						||
        height: 40px;
 | 
						||
        background: rgba(#30426F, .5);
 | 
						||
        display: flex;
 | 
						||
        align-items: center;
 | 
						||
        padding: 8px 0;
 | 
						||
        box-sizing: border-box;
 | 
						||
 | 
						||
        hr {
 | 
						||
          height: 100%;
 | 
						||
          border-color: rgba(#fff, .5);
 | 
						||
        }
 | 
						||
 | 
						||
        & > .el-button {
 | 
						||
          flex: 1;
 | 
						||
          color: #fff;
 | 
						||
 | 
						||
          &[disabled] {
 | 
						||
            color: rgba(#fff, .5);
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  ::v-deep .writeInPhone {
 | 
						||
    position: absolute;
 | 
						||
    width: 100px;
 | 
						||
    height: 32px;
 | 
						||
    background: rgba(#000, .5);
 | 
						||
    border-radius: 16px;
 | 
						||
    display: flex;
 | 
						||
    align-items: center;
 | 
						||
    justify-content: center;
 | 
						||
    gap: 4px;
 | 
						||
    color: rgba(#fff, .6);
 | 
						||
    cursor: pointer;
 | 
						||
    left: 16px;
 | 
						||
    top: 16px;
 | 
						||
 | 
						||
    .AiIcon {
 | 
						||
      width: auto;
 | 
						||
      height: auto;
 | 
						||
    }
 | 
						||
 | 
						||
    &:hover {
 | 
						||
      color: #fff;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  ::v-deep .ai-dialog__wrapper {
 | 
						||
    .ai-dialog__content--wrapper {
 | 
						||
      padding-right: 0 !important;
 | 
						||
    }
 | 
						||
 | 
						||
    .el-dialog__body {
 | 
						||
      padding: 24px 0;
 | 
						||
    }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
    .authZone {
 | 
						||
      padding: 0 16px 24px;
 | 
						||
      width: 100%;
 | 
						||
      box-sizing: border-box;
 | 
						||
      display: flex;
 | 
						||
      flex-direction: column;
 | 
						||
      gap: 24px;
 | 
						||
 | 
						||
      .el-alert {
 | 
						||
        border: 1px solid #FF8822;
 | 
						||
      }
 | 
						||
 | 
						||
      .el-form-item {
 | 
						||
        margin-bottom: 0;
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
</style>
 |