Ver código fonte

feat:护工注册
- Login界面ui布局
- 身份证信息提取
- 图片上传组件优化

seamong 6 anos atrás
pai
commit
69ebf469ca

+ 32 - 0
www/webapp/safety/src/components/title.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="title"><span v-if="required" class="red">*</span>{{text}}</div>
+</template>
+<script>
+export default {
+  props: {
+    required: {
+      type: Boolean,
+      default: false,
+    },
+    text: {
+      type: String,
+      default: '',
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.title {
+  color: #333;
+  font-size: 14px;
+  position: relative;
+  line-height: 40px;
+  .red {
+    color: #f44;
+    position: absolute;
+    left: -8px;
+    // top: 5px;
+  }
+}
+</style>

+ 27 - 1
www/webapp/safety/src/main.js

@@ -1,15 +1,41 @@
 // The Vue build version to load with the `import` command
 // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
 import Vue from 'vue';
-import { Toast } from 'vant';
+import {
+  Toast,
+  Cell,
+  CellGroup,
+  Field,
+  RadioGroup,
+  Radio,
+  DatetimePicker,
+  Popup,
+  Button,
+  NavBar,
+} from 'vant';
 import ajaxPlugin from '@/util/ajax';
 import App from './App';
 import router from './router';
 // eslint-disable-next-line
 import 'amfe-flexible';
+// components
+import hTitle from './components/title';
 
 Vue.config.productionTip = false;
+// vant-start
 Vue.use(Toast);
+Vue.use(Cell).use(CellGroup);
+Vue.use(Field);
+Vue.use(RadioGroup);
+Vue.use(Radio);
+Vue.use(DatetimePicker);
+Vue.use(Popup);
+Vue.use(Button);
+Vue.use(NavBar);
+// vant-end
+// components-start
+Vue.component('h-title', hTitle);
+// components-end
 Vue.prototype.$http = ajaxPlugin;
 /* eslint-disable no-new */
 new Vue({

+ 170 - 0
www/webapp/safety/src/util/index.js

@@ -0,0 +1,170 @@
+/* eslint-disable */
+/**
+ * 检验身份证
+ * @param {String} idcard
+ * @return {Boolean} true|false
+ */
+export function testIDCard(idcard) {
+  const Errors = new Array(
+    '验证通过!',
+    '身份证号码位数不对!',
+    '身份证号码出生日期超出范围或含有非法字符!',
+    '身份证号码校验错误!',
+    '身份证地区非法!',
+  );
+  const area = {
+    11: '北京',
+    12: '天津',
+    13: '河北',
+    14: '山西',
+    15: '内蒙古',
+    21: '辽宁',
+    22: '吉林',
+    23: '黑龙江',
+    31: '上海',
+    32: '江苏',
+    33: '浙江',
+    34: '安徽',
+    35: '福建',
+    36: '江西',
+    37: '山东',
+    41: '河南',
+    42: '湖北',
+    43: '湖南',
+    44: '广东',
+    45: '广西',
+    46: '海南',
+    50: '重庆',
+    51: '四川',
+    52: '贵州',
+    53: '云南',
+    54: '西藏',
+    61: '陕西',
+    62: '甘肃',
+    63: '青海',
+    64: '宁夏',
+    65: '新疆',
+    71: '台湾',
+    81: '香港',
+    82: '澳门',
+    91: '国外',
+  };
+  let ereg, Y, JYM;
+  let S, M;
+  let idCard_array = new Array();
+  idCard_array = idcard.split('');
+  if (area[Number.parseInt(idcard.substr(0, 2))] == null) return Errors[4];
+  switch (idcard.length) {
+    case 15:
+      if (
+        (Number.parseInt(idcard.substr(6, 2)) + 1900) % 4 == 0 ||
+        ((Number.parseInt(idcard.substr(6, 2)) + 1900) % 100 == 0 &&
+          (Number.parseInt(idcard.substr(6, 2)) + 1900) % 4 == 0)
+      ) {
+        ereg = /^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$/; //测试出生日期的合法性
+      } else {
+        ereg = /^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$/; //测试出生日期的合法性
+      }
+      if (ereg.test(idcard)) return Errors[0];
+      else return Errors[2];
+      break;
+    case 18:
+      if (
+        Number.parseInt(idcard.substr(6, 4)) % 4 == 0 ||
+        (Number.parseInt(idcard.substr(6, 4)) % 100 == 0 &&
+          Number.parseInt(idcard.substr(6, 4)) % 4 == 0)
+      ) {
+        ereg = /^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$/; //闰年出生日期的合法性正则表达式
+      } else {
+        ereg = /^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$/; //平年出生日期的合法性正则表达式
+      }
+      if (ereg.test(idcard)) {
+        S =
+          (Number.parseInt(idCard_array[0]) +
+            Number.parseInt(idCard_array[10])) *
+            7 +
+          (Number.parseInt(idCard_array[1]) +
+            Number.parseInt(idCard_array[11])) *
+            9 +
+          (Number.parseInt(idCard_array[2]) +
+            Number.parseInt(idCard_array[12])) *
+            10 +
+          (Number.parseInt(idCard_array[3]) +
+            Number.parseInt(idCard_array[13])) *
+            5 +
+          (Number.parseInt(idCard_array[4]) +
+            Number.parseInt(idCard_array[14])) *
+            8 +
+          (Number.parseInt(idCard_array[5]) +
+            Number.parseInt(idCard_array[15])) *
+            4 +
+          (Number.parseInt(idCard_array[6]) +
+            Number.parseInt(idCard_array[16])) *
+            2 +
+          Number.parseInt(idCard_array[7]) * 1 +
+          Number.parseInt(idCard_array[8]) * 6 +
+          Number.parseInt(idCard_array[9]) * 3;
+        Y = S % 11;
+        M = 'F';
+        JYM = '10X98765432';
+        M = JYM.substr(Y, 1);
+        if (M == idCard_array[17]) return Errors[0];
+        else return Errors[3];
+      } else return Errors[2];
+      break;
+    default:
+      return Errors[1];
+      break;
+  }
+}
+
+/**
+ * 传入身份证号码和num.获取出生日期,性别跟年龄
+ * @param UUserCard 身份证号码
+ * @param num 1 获取出生日期
+ *            2 获取性别
+ *            3 获取年龄,年龄小于1岁的时候默认为1岁
+ * @returns {*}
+ * @constructor
+ */
+export function IdCard(UUserCard, num) {
+  let birth;
+  if (num == 1) {
+    //获取出生日期
+    birth =
+      UUserCard.substring(6, 10) +
+      '-' +
+      UUserCard.substring(10, 12) +
+      '-' +
+      UUserCard.substring(12, 14);
+    return birth;
+  }
+  if (num == 2) {
+    //获取性别
+    if (parseInt(UUserCard.substr(16, 1)) % 2 == 1) {
+      //男
+      return '男';
+    } else {
+      //女
+      return '女';
+    }
+  }
+  if (num == 3) {
+    //获取年龄
+    var myDate = new Date();
+    var month = myDate.getMonth() + 1;
+    var day = myDate.getDate();
+    var age = myDate.getFullYear() - UUserCard.substring(6, 10) - 1;
+    if (
+      UUserCard.substring(10, 12) < month ||
+      (UUserCard.substring(10, 12) == month &&
+        UUserCard.substring(12, 14) <= day)
+    ) {
+      age++;
+    }
+    if (age <= 0) {
+      age = 1;
+    }
+    return age;
+  }
+}

+ 34 - 0
www/webapp/safety/src/views/Care/Login/from/birthday.vue

@@ -0,0 +1,34 @@
+<template>
+  <van-cell>
+    <div class="birthday-wrapper">
+      <h-title required text='生日选择' />
+      <div @click='show =!show'>
+        @click='show =!show'
+      </div>
+      <van-popup v-model="show" position="bottom">
+        <van-datetime-picker v-model="currentDate" type="datetime"
+          :min-date='minDate' :max-date="maxDate" />
+      </van-popup>
+    </div>
+  </van-cell>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      show: false,
+      minHour: 10,
+      maxHour: 20,
+      maxDate: new Date(),
+      minDate: new Date(1950, 10, 1),
+      currentDate: new Date(),
+    };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.birthday-wrapper {
+  padding: 0 10px;
+}
+</style>

+ 49 - 0
www/webapp/safety/src/views/Care/Login/from/sex.vue

@@ -0,0 +1,49 @@
+<template>
+  <div class="sex-wrapper">
+    <h-title required text='性别选择' />
+    <van-radio-group v-model="sex">
+      <van-cell-group>
+        <van-cell title="男" clickable @click="sexChange('1')">
+          <van-radio name="1" />
+        </van-cell>
+        <van-cell title="女" clickable @click="sexChange('2')">
+          <van-radio name="2" />
+        </van-cell>
+      </van-cell-group>
+    </van-radio-group>
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {
+      sex: '-1',
+    };
+  },
+  methods: {
+    sexChange(index) {
+      this.sex = index;
+      this.$emit('sex', this.sex);
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.sex-wrapper {
+  padding: 0 15px;
+  .title {
+    color: #333;
+    font-size: 14px;
+    position: relative;
+    line-height: 40px;
+    .red {
+      color: #f44;
+      position: absolute;
+      left: -8px;
+      top: 5px;
+    }
+  }
+}
+</style>
+

+ 97 - 48
www/webapp/safety/src/views/Care/Login/index.vue

@@ -1,28 +1,65 @@
 <template>
   <div class="login-wrapper" ref="login">
+    <van-nav-bar title="标题" left-text="返回" @click-left="onClickLeft"
+      left-arrow fixed />
     <van-cell-group>
-      <van-field required clearable left-icon="contact"
-        v-model="user.name" label="用户名" placeholder="请输入用户名"
-        autosize />
-      <van-field v-model="user.phone" label="手机号" left-icon="phone"
-        placeholder="请输入手机号" autosize />
-      <div class="sex-wrapper">
-        <div class="title"><span class="red">*</span>性别选择</div>
-        <van-radio-group v-model="user.sex">
-          <van-cell-group>
-            <van-cell title="男" clickable @click="user.sex = '1'">
-              <van-radio name="1" />
-            </van-cell>
-            <van-cell title="女" clickable @click="user.sex = '2'">
-              <van-radio name="2" />
-            </van-cell>
-          </van-cell-group>
-        </van-radio-group>
+      <!-- 姓名: name -->
+      <van-field required clearable v-model="user.name"
+        label="姓名" placeholder="请输入姓名" autosize />
+      <!-- 性别: sex -->
+      <!-- <h-sex @sex='getSex' /> -->
+      <!-- 生日: birthday -->
+      <!-- <h-birthday></h-birthday> -->
+      <!-- 身份证: IDcard -->
+      <van-field required clearable v-model="user.IDcard"
+        label="身份证" placeholder="请输入身份证" autosize />
+      <!-- 手机: mobilePhone -->
+      <van-field required clearable v-model="user.mobilePhone"
+        label="手机" placeholder="请输入手机号码" autosize />
+      <!-- 电话: phone -->
+      <van-field required clearable v-model="user.phone"
+        label="电话" placeholder="请输入电话号码" autosize />
+      <!-- 邮箱: email -->
+      <van-field required clearable type='email' v-model="user.email"
+        label="邮箱" placeholder="请输入邮箱" autosize />
+      <!-- 户籍地址: address1 -->
+      <van-field required clearable v-model="user.address1"
+        label="户籍地址" placeholder="请输入户籍地址" autosize />
+      <!-- 居住地址: address2 -->
+      <van-field required clearable v-model="user.address2"
+        label="居住地址" placeholder="请输入居住地址" autosize />
+      <!-- 通讯地址: address3 -->
+      <van-field required clearable v-model="user.address3"
+        label="通讯地址" placeholder="请输入通讯地址" autosize />
+      <!-- 邮编: ZIPcode -->
+      <van-field required clearable v-model="user.ZIPcode"
+        label="邮编" placeholder="请输入邮编" autosize />
+      <!-- 证书(图片): certificate -->
+      <div>
+        <!-- <video class="my-video" src="../../../assets/02.mp4"></video> -->
+        <!-- <video id="my-player" class="my-video video-js" controls
+          preload="auto" autoplay="autoplay" data-setup='{}'>
+          <source src="../../../assets/02.mp4" type="video/mp4">
+          </source>
+        </video> -->
       </div>
       <div class="certificate-wrapper">
-        <uploader @imgSrc='getImgSrc' title='添加证书(正面)' />
-        <uploader @imgSrc='getImgSrc' title='添加证书(反面)' />
+        <h-title required text='添加证书'></h-title>
+        <div class="add">
+          <uploader @imgSrc='getImgSrc' />
+          <!-- <uploader @imgSrc='getImgSrc' title='添加证书(反面)' /> -->
+        </div>
       </div>
+      <!-- 护理机构: nurse -->
+      <van-field required clearable v-model="user.nurse"
+        label="护理机构" placeholder="请输入护理机构" autosize />
+      <!-- 状态: status -->
+      <van-field required clearable v-model="user.status"
+        label="护理状态" placeholder="请输入状态" autosize />
+      <!-- 备注: desc -->
+      <van-field required clearable v-model="user.desc"
+        label="备注" placeholder="请输入备注" autosize />
+      <van-button class="btn" size="large" type="primary">提交</van-button>
     </van-cell-group>
   </div>
 </template>
@@ -44,18 +81,30 @@
  * 状态: status
  * 备注: desc
  */
-import { Cell, CellGroup, Field, RadioGroup, Radio } from 'vant';
+// import { Cell, CellGroup, Field, RadioGroup, Radio } from 'vant';
 import Bscroll from 'better-scroll';
+// import { testIDCard, IdCard } from '@/util/index';
 import uploader from './uploader';
+import hSex from './from/sex';
+import hBirthday from './from/birthday';
 
 export default {
   data() {
     return {
       user: {
         name: '',
+        IDcard: '',
+        mobilePhone: '',
         phone: '',
+        email: '',
+        address1: '',
+        address2: '',
+        address3: '',
+        ZIPcode: '',
         certificate: [],
-        sex: 0,
+        nurse: '',
+        status: '',
+        desc: '',
       },
       phoneError: false,
     };
@@ -66,17 +115,24 @@ export default {
     },
   },
   components: {
-    [Cell.name]: Cell,
-    [CellGroup.name]: CellGroup,
-    [Field.name]: Field,
-    [RadioGroup.name]: RadioGroup,
-    [Radio.name]: Radio,
+    // [Cell.name]: Cell,
+    // [CellGroup.name]: CellGroup,
+    // [Field.name]: Field,
+    // [RadioGroup.name]: RadioGroup,
+    // [Radio.name]: Radio,
     uploader,
+    hSex,
+    hBirthday,
   },
   mounted() {
-    this.initScroll();
+    // this.initScroll();
+    // console.log(testIDCard('331023199407260318'));
+    // console.log(IdCard('331023199407260318', 1));
+    // console.log(IdCard('331023199407260318', 2));
+    // console.log(IdCard('331023199407260318', 3));
   },
   methods: {
+    testIDCard() {},
     initScroll() {
       if (!this.scroll) {
         this.scroll = new Bscroll(this.$refs.login, {
@@ -107,34 +163,27 @@ export default {
       this.user.certificate.push(src);
       console.log(this.user.certificate);
     },
+    onClickLeft() {},
   },
 };
 </script>
 <style lang="less" scoped>
 .login-wrapper {
-  height: 100vh;
-  background-color: #999;
-  .sex-wrapper {
-    padding: 0 15px;
-    .title {
-      color: #333;
-      font-size: 14px;
-      position: relative;
-      line-height: 40px;
-      .red {
-        color: #f44;
-        position: absolute;
-        left: -8px;
-        top: 5px;
-      }
-    }
-  }
+  padding: 46px 10px 0;
+  height: 100%;
+  background-color: #fff;
   .certificate-wrapper {
-    display: flex;
-    .uploader-wrapper {
-      flex: 1;
+    padding: 5px 15px;
+    .add {
+      // border: 1px solid black;
     }
   }
+  .my-video {
+    width: 100vw;
+  }
+  .btn {
+    display: block;
+    margin: 30px auto;
+  }
 }
-
 </style>

+ 79 - 49
www/webapp/safety/src/views/Care/Login/uploader.vue

@@ -1,16 +1,18 @@
 <template>
   <div class="uploader-wrapper">
     <van-uploader :after-read="onRead">
-      <van-icon v-if='percent == 0 && imgSrc.length === 0'
-        name="add" />
-      <div class="title" v-if='percent == 0 && imgSrc.length === 0'>
-        {{title}}
-      </div>
-      <van-circle v-model="currentRate" v-if='percent > 0 && imgSrc.length === 0'
-        :rate="percent" :speed="100" :text="text" />
-      <img v-if='imgSrc.length > 0' :src="imgSrc" alt="" />
     </van-uploader>
-
+    <!-- <div class="add-icon" v-if='percent == 0 && imgSrc.length === 0'> -->
+    <div class="add-icon" v-if='percent === 0'>
+      <van-icon name="add" />
+      <!-- <div class="title" v-if="title.length > 0">
+        {{title}}
+      </div> -->
+    </div>
+    <img v-if='imgSrc.length > 0' :src="imgSrc" alt="" />
+    <!-- <div v-if='imgSrc.length > 0'>{{imgSrc}}</div> -->
+    <van-circle v-model="currentRate" v-if='percent > 0 && imgSrc.length === 0'
+      :rate="percent" :speed="100" :text="text" />
   </div>
 </template>
 
@@ -36,12 +38,12 @@ export default {
       percent: 0,
       currentRate: 0,
       imgSrc: '',
+      name: '',
     };
   },
   props: {
     title: {
       type: String,
-      default: '添加图片',
     },
   },
   computed: {
@@ -55,6 +57,11 @@ export default {
     [Circle.name]: Circle,
   },
   methods: {
+    getFileName(name) {
+      const oldName = name.split('.');
+      oldName[0] = md5(oldName[0]);
+      return `${oldName[0]}.${oldName[1]}`;
+    },
     onRead(file) {
       const self = this;
       const MAXFILE = 1024 * 1024 * 8;
@@ -72,7 +79,8 @@ export default {
         useCdnDomain: true,
         region: qiniu.region.z0,
       };
-      const key = md5(file.file.name);
+      const key = this.getFileName(file.file.name);
+      self.name = key;
       const putextra = {
         fname: file.file.name,
         params: {},
@@ -88,11 +96,19 @@ export default {
             self.percent = 0;
             self.currentRate = 0;
             self.$toast.success('上传成功');
+            // self.$nextTick(() => {
+            //   self.imgSrc = file.content;
+            // });
             self.imgSrc =
               process.env.NODE_ENV === 'development'
                 ? `${self.qiniu.test}/${key}`
                 : `${self.qiniu.certificate}/${key}`;
-            self.$emit('imgSrc', self.imgSrc);
+            self.$emit(
+              'imgSrc',
+              process.env.NODE_ENV === 'development'
+                ? `${self.qiniu.test}/${key}`
+                : `${self.qiniu.certificate}/${key}`,
+            );
           }
           // self.$nextTick(() => {});
         },
@@ -130,49 +146,63 @@ export default {
 </script>
 <style lang="less" scoped>
 .uploader-wrapper {
+  position: relative;
+  font-size: 15px;
+  text-align: center;
+  min-height: 100px;
+  max-height: 250px;
+  overflow: hidden;
   .van-uploader {
-    position: relative;
     padding: 20px;
     font-size: 15px;
+    position: absolute;
+    z-index: 6;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+  }
+  .van-circle {
+    display: block;
+    position: static;
+    width: 70px !important;
+    height: 70px !important;
+    font-size: 15px;
+    position: absolute;
+    z-index: 999;
+    top: calc(50% - 35px);
+    left: calc(50% - 35px);
+  }
+  .add-icon {
+    position: absolute;
+    z-index: 4;
+    top: calc(50% - 25px);
+    left: calc(50% - 25px);
+  }
+  .van-icon {
+    margin: 0 auto;
+    display: block;
+    height: 50px;
+    line-height: 50px;
     text-align: center;
-    display: flex;
-    flex-direction: column;
-    align-content: center;
-    justify-content: center;
-    .van-icon {
-      margin: 0 auto;
-      display: block;
-      height: 50px;
-      line-height: 50px;
-      text-align: center;
-      width: 50px;
-      font-size: 50px;
-      color: #999;
-    }
-    .title {
-      margin-top: 10px;
-    }
-    .van-circle {
-      display: block;
-      position: static;
-      width: 60px !important;
-      height: 60px !important;
-    }
-    img {
-      display: block;
-      width: 100%;
-      height: auto;
-    }
+    width: 50px;
+    font-size: 50px;
+    color: #eee;
   }
-  &:nth-child(odd) {
-    .van-uploader {
-      padding-right: 10px;
-    }
+  .title {
+    margin-top: 10px;
+    color: #fff;
+    text-shadow: 1px 1px 1px #000;
   }
-  &:nth-child(even) {
-    .van-uploader {
-      padding-left: 10px;
-    }
+
+  img {
+    display: block;
+    width: 100%;
+    height: 100%;
+    // height: auto;
+    // width: 80px;
+    // height: 80px;
+    margin: 0 auto;
   }
 }
 </style>