Browse Source

更新页面

lex-xin 3 years ago
parent
commit
2d11a52cb0

+ 3 - 3
package-lock.json

@@ -2240,9 +2240,9 @@
       }
     },
     "@vant/use": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmmirror.com/@vant/use/-/use-1.3.4.tgz",
-      "integrity": "sha512-XvZkPCjcmEBhD+T3vB68thOG6P9jazld6aBTMenhbAQd4FT/x9AiKIWPJx4MvhYoSIWt7fju6K01XTJldWs1hw=="
+      "version": "1.3.6",
+      "resolved": "https://registry.npmmirror.com/@vant/use/-/use-1.3.6.tgz",
+      "integrity": "sha512-3z+nywPaV2F5BdJO7RQxWlgfzJeEOmViD2yHMb7Tg+R4NR/7iQskqW8v2Cnv9FWSJgTOSHlcr7UzeLpiTAP4HA=="
     },
     "@vitejs/plugin-legacy": {
       "version": "1.7.1",

BIN
public/favicon.ico


BIN
src/common/images/icon_checkbox.png


BIN
src/common/images/icon_checkbox_default.png


+ 3 - 0
src/components/ColHeader/index.module.less

@@ -5,6 +5,9 @@
       .van-nav-bar__title, .van-icon {
         color: #fff;
       }
+      .van-nav-bar__content {
+        height: inherit;
+      }
     }
   }
 }

+ 26 - 0
src/components/ColProtocol/index.module.less

@@ -0,0 +1,26 @@
+.colProtocol {
+  display: flex;
+  align-items: center;
+  font-size: 12px;
+  padding: 15px 14px;
+  color: #999;
+  .protocolText {
+    color: var(--van-primary);
+  }
+
+  .boxStyle {
+    background: transparent;
+    width: 15px;
+    height: 15px;
+    border: transparent;
+  }
+  :global {
+    .van-checkbox__icon {
+      height: 20px;
+      line-height: 15px;
+      display: flex;
+      align-items: center;
+    }
+  }
+}
+

+ 84 - 0
src/components/ColProtocol/index.tsx

@@ -0,0 +1,84 @@
+import { Checkbox, Icon, Popup } from "vant";
+import { defineComponent } from "vue";
+import styles from './index.module.less';
+import activeButtonIcon from '@common/images/icon_checkbox.png';
+import inactiveButtonIcon from '@common/images/icon_checkbox_default.png';
+
+export default defineComponent({
+  name: 'protocol',
+  props: {
+    value: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      checked: false,
+      popupStatus: false,
+      protocolHTML: '',
+      protocolPopup: null as any,
+    }
+  },
+  mounted() {
+    window.addEventListener('hashchange', this.onHash, false)
+  },
+  unmounted() {
+    window.removeEventListener('hashchange', this.onHash, false)
+  },
+  methods: {
+    onHash() {
+      this.popupStatus = false;
+    },
+    onPopupClose() {
+      // 判断是否有协议内容
+      // if (!this.protocolHTML) {
+      //   return
+      // }
+      this.popupStatus = !this.popupStatus
+
+      // 打开弹窗
+      if (this.popupStatus) {
+        const route = this.$route
+        let times = 0;
+        for (let i in route.query) {
+          times += 1
+        }
+        const origin = window.location.href
+        const url = times > 0 ? '&pto=' + (+new Date()) : '?pto=' + (+new Date())
+        history.pushState("", "", `${origin}${url}`)
+      } else {
+        window.history.go(-1)
+      }
+      if (this.protocolPopup) {
+        (this.protocolPopup as any).scrollTop = 0
+      }
+    }
+  },
+  render() {
+    return (
+      <div class={styles.colProtocol}>
+        <Checkbox v-model={this.checked}
+          // @ts-ignore
+          vSlots={{
+            icon: (props: any) => (
+              <Icon class={styles.boxStyle} name={props.checked ? activeButtonIcon : inactiveButtonIcon} size="15" />
+            )
+          }}
+        >
+          我已阅读并同意
+        </Checkbox>
+        <span onClick={this.onPopupClose} class={styles.protocolText}>《酷乐秀平台服务协议》</span>
+
+        <Popup ref={this.protocolPopup} show={this.popupStatus} position="bottom" style={{ height: '100%' }}>
+          <div class={styles.protocolContent}>
+            <div class={styles.protocolTitle}>酷乐秀平台服务协议</div>
+            <div class={styles.protocolContent}>
+              呆头呆脑的协议内容
+            </div>
+          </div>
+        </Popup>
+      </div>
+    )
+  }
+})

+ 38 - 1
src/helpers/validate.ts

@@ -1,4 +1,3 @@
-import { phoneRule } from './rules';
 // 学生地址
 export function vaildStudentUrl() {
   const url = window.location.href;
@@ -23,3 +22,41 @@ export function checkPhone(phone: string) {
   const phoneRule = /^1[3456789]\d{9}$/;
   return phoneRule.test(phone);
 }
+
+// 身份证号验证
+export function checkIDCard(idCardNo: string) {
+  let result = true;
+  //
+  const idCardReg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
+  if (idCardReg.test(idCardNo) === false) {
+    result = false;
+  }
+  return result;
+}
+
+// 港澳居民来往内地通行证(回乡证)
+export function checkPassport(idCardNo: string) {
+  // 港澳居民来往内地通行证
+  // 规则: H/M + 10位或6位数字
+  // 样本: H1234567890
+  let result = true;
+  // let idReg = /^[mMhH]\\d{10}|[mMhH]\\d{8}$/
+  const idReg = /^([A-Z]\d{6,10}(\(\w{1}\))?)$/;
+  if (idReg.test(idCardNo) === false) {
+    result = false;
+  }
+  return result;
+}
+
+// 台湾居民来往大陆通行证(台胞证)
+export function checkPassportTaiwan(idCardNo: string) {
+  // 台湾居民来往大陆通行证
+  // 规则: 新版8位或18位数字, 旧版10位数字 + 英文字母
+  // 样本: 12345678 或 1234567890B
+  let result = true
+  const idReg = /(^\\d{8}$)|(^[a-zA-Z0-9]{10}$)|(^\\d{18}$)/;
+  if (idReg.test(idCardNo) === false) {
+    result = false;
+  }
+  return result;
+}

+ 6 - 0
src/router/index-teacher.ts

@@ -4,4 +4,10 @@ const router: Router = createRouter({
   history: createWebHashHistory(),
   routes
 });
+
+router.beforeEach((to, from, next) => {
+  document.title = (to.meta.title || '酷乐秀') as any;
+  next();
+});
+
 export default router;

+ 8 - 0
src/router/routes-teacher.ts

@@ -21,6 +21,14 @@ export default [
         path: '/home',
         name: 'home',
         component: () => import('@/teacher/home/index')
+      },
+      {
+        path: 'teacherCert',
+        name: 'teacherCert',
+        component: () => import('@/teacher/teacherCert/index'),
+        meta: {
+          title: '老师认证'
+        }
       }
     ]
   },

+ 8 - 1
src/styles/index.less

@@ -13,6 +13,7 @@
   // --van-red: #ee0a24;
   // --van-blue: #1989fa;
   --van-primary: #2DC7AA !important;
+  --van-picker-confirm-action-color: #2DC7AA !important;
   // --van-orange: #ff976a;
   // --van-orange-dark: #ed6a0c;
   // --van-orange-light: #fffbe8;
@@ -76,6 +77,12 @@
   // --van-border-radius-max: 999px;
 }
 
+* {
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
 #app {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
@@ -84,5 +91,5 @@
 }
 
 body {
-  background-color: #f7f7f7;
+  background-color: #F6F8F9;
 }

+ 12 - 0
src/teacher/main.ts

@@ -10,6 +10,18 @@ import '../styles/index.less';
 
 const app = createApp(App);
 
+// 将selects全局混入当前vue实例中
+// import activeButtonIcon from '@/common/images/icon_check.png';
+// import inactiveButtonIcon from '@/common/images/icon_default.png';
+// app.mixin({
+//   data() {
+//     return {
+//       activeButtonIcon: activeButtonIcon,
+//       inactiveButtonIcon: inactiveButtonIcon,
+//     };
+//   }
+// });
+
 dayjs.locale('zh-ch');
 app.config.globalProperties.$dayjs = dayjs;
 app.use(router);

+ 58 - 0
src/teacher/teacherCert/certOne.module.less

@@ -0,0 +1,58 @@
+.certOne {
+  margin: 0 14px;
+  border-radius: 10px;
+  overflow: hidden;
+  background-color: #fff;
+  padding: 20px;
+
+  .codeText {
+    color: var(--van-primary);
+  }
+
+  .formTitle {
+    font-size: 17px;
+    color: #000;
+    line-height: 24px;
+    &::before {
+      content: '*';
+      color: #FF4E19;
+      font-size: 17px;
+    }
+  }
+
+  :global {
+    .van-field {
+      padding-left: 0;
+      padding-right: 0;
+    }
+    .van-button + .van-button {
+      margin-top: 20px;
+      color: #000 !important;
+    }
+  }
+
+  .radioGroup {
+    padding-top: 14px;
+    display: flex;
+  }
+  .radio {
+    width: 94px;
+    height: 28px;
+    line-height: 28px;
+    background: #F8F8F8;
+    border: 1px solid #F8F8F8;
+    border-radius: 5px;
+    font-size: 16px;
+    color: #C0C0C0;
+    text-align: center;
+    & + .radio {
+      margin-left: 5px;
+    }
+
+    &.active {
+      background: #E9FFF8;
+      border: 1px solid var(--van-primary);
+      color: var(--van-primary);
+    }
+  }
+}

+ 98 - 0
src/teacher/teacherCert/certOne.tsx

@@ -0,0 +1,98 @@
+import { Cell, CellGroup, Col, DatetimePicker, Field, Popup, Row } from "vant"
+import { defineComponent } from "vue";
+import dayjs from "dayjs";
+import { teacherState } from "./teacherState";
+import styles from './certOne.module.less';
+
+export default defineComponent({
+  name: 'certOne',
+  data() {
+    return {
+      maxDate: new Date(),
+      popupShow: false,
+      popupDate: new Date(),
+    }
+  },
+  methods: {
+    onConfirm(_date: any) {
+      teacherState.teacherCert.birthday = dayjs(this.popupDate).format('YYYY-MM-DD')
+      this.popupShow = false;
+    },
+    formatter(type: any, val: any) {
+      if (type === 'year') {
+        return `${val}年`;
+      }
+      if (type === 'month') {
+        return `${val}月`;
+      }
+      if (type === 'day') {
+        return `${val}日`;
+      }
+      return val;
+    }
+  },
+  render() {
+    return (
+      <div class={styles.certOne}>
+        <CellGroup border={false}>
+          <Row style={{ marginBottom: '16px' }}>
+            <Col span={24} class={styles.formTitle}>真实姓名</Col>
+            <Col span={24} class="van-hairline--bottom">
+              <Field
+                v-model={teacherState.teacherCert.username}
+                name="真实姓名"
+                placeholder="请输入您的真实姓名"
+                type="tel"
+                maxlength={11}
+              />
+            </Col>
+          </Row>
+          <Row style={{ marginBottom: '16px' }}>
+            <Col span={24} class={styles.formTitle}>身份证号</Col>
+            <Col span={24} class="van-hairline--bottom">
+              <Field
+                v-model={teacherState.teacherCert.idCard}
+                name="身份证号"
+                placeholder="请输入您的身份证号码"
+                type="tel"
+                maxlength={11}
+              />
+            </Col>
+          </Row>
+          <Row style={{ marginBottom: '16px' }}>
+            <Col span={24} class={styles.formTitle}>性别</Col>
+            <Col span={24} class={styles.radioGroup}>
+              <div onClick={() => teacherState.teacherCert.sex = 1 } class={[styles.radio, teacherState.teacherCert.sex === 1 ? styles.active : null]}>男</div>
+              <div onClick={() => teacherState.teacherCert.sex = 0 } class={[styles.radio,teacherState.teacherCert.sex === 0 ? styles.active : null]}>女</div>
+            </Col>
+          </Row>
+          <Row>
+            <Col span={24} class={styles.formTitle}>出生日期</Col>
+            <Col span={24} class="van-hairline--bottom">
+              <Field
+                v-model={teacherState.teacherCert.birthday}
+                name="出生日期"
+                onClick-input={() => this.popupShow = true}
+                readonly
+                isLink
+                placeholder="请选择您的出生日期"
+              />
+            </Col>
+          </Row>
+        </CellGroup>
+
+        <Popup show={this.popupShow} position="bottom" round>
+          <DatetimePicker
+            v-model={this.popupDate}
+            type="date"
+            close-on-popstate={true}
+            maxDate={this.maxDate}
+            onCancel={() => this.popupShow = false}
+            onConfirm={this.onConfirm}
+            formatter={this.formatter}>
+          </DatetimePicker>
+        </Popup>
+      </div>
+    )
+  }
+})

BIN
src/teacher/teacherCert/images/base_active.png


BIN
src/teacher/teacherCert/images/base_default.png


BIN
src/teacher/teacherCert/images/base_finish.png


BIN
src/teacher/teacherCert/images/education_active.png


BIN
src/teacher/teacherCert/images/education_default.png


BIN
src/teacher/teacherCert/images/education_finish.png


BIN
src/teacher/teacherCert/images/icon_horn.png


BIN
src/teacher/teacherCert/images/name_active.png


BIN
src/teacher/teacherCert/images/name_default.png


BIN
src/teacher/teacherCert/images/name_finish.png


+ 5 - 0
src/teacher/teacherCert/index.module.less

@@ -0,0 +1,5 @@
+.teacher-cert {
+  .btnGroup {
+    padding: 0 14px;
+  }
+}

+ 38 - 0
src/teacher/teacherCert/index.tsx

@@ -0,0 +1,38 @@
+
+import { defineComponent } from "vue";
+import styles from './index.module.less';
+import ColProtocol from "@/components/ColProtocol";
+import Steps from './steps';
+import CertOne from './certOne'
+import { Button, Toast } from "vant";
+
+
+export default defineComponent({
+  name: 'teacherCert',
+  data() {
+    return {
+    }
+  },
+  methods: {
+    next() {
+      const checked = (this as any).$refs.eleRef.checked;
+      if (!checked) {
+        Toast('请阅读并同意协议');
+        return
+      }
+    }
+  },
+  render() {
+    return (
+      <div class={styles['teacher-cert']}>
+        <Steps style={{ marginBottom: '12px' }} />
+
+        <CertOne />
+        <div class={styles.btnGroup}>
+          <ColProtocol ref='eleRef' style={{ paddingLeft: 0, paddingRight: 0 }} />
+          <Button block round onClick={this.next} type="primary" text="下一步" />
+        </div>
+      </div>
+    )
+  }
+})

+ 44 - 0
src/teacher/teacherCert/steps.module.less

@@ -0,0 +1,44 @@
+.steps {
+  background-color: #fff;
+  margin: 12px 14px 0;
+  padding: 20px;
+  border-radius: 10px;
+  &.paddingBottom12 {
+    padding-bottom: 12px;
+  }
+  .stepContent {
+    display: flex;
+    justify-content: space-between;
+  }
+  .stepItem {
+    text-align: center;
+    p {
+      font-size: 12px;
+      color: #B4B4B4;
+      &.active {
+        color: var(--van-primary);
+      }
+    }
+  }
+  .line {
+    display: block;
+    margin-top: 19px;
+    width: 54px;
+    height: 2px;
+    background-color: #E3E3E3;
+    &.lineActive {
+      background-color: #8BE1D1;
+    }
+  }
+
+  .stepTips {
+    margin-top: 20px;
+    padding: 7px;
+    background: linear-gradient(139deg, #FFF6EE 0%, #FFECDD 100%);
+    border-radius: 6px;
+    font-size: 12px;
+    color: #E0945A;
+    display: flex;
+    align-items: center;
+  }
+}

+ 74 - 0
src/teacher/teacherCert/steps.tsx

@@ -0,0 +1,74 @@
+import { defineComponent } from "vue";
+import { Icon } from 'vant';
+import { teacherState } from './teacherState'
+import styles from './steps.module.less';
+import baseDefault from './images/base_default.png';
+import baseActive from './images/base_active.png';
+import baseFinish from './images/base_finish.png';
+import nameDefault from './images/name_default.png';
+import nameActive from './images/name_active.png';
+import nameFinish from './images/name_finish.png';
+import educationDefault from './images/education_default.png';
+import educationActive from './images/education_active.png';
+import educationFinish from './images/education_finish.png';
+
+import horn from './images/icon_horn.png'
+
+export default defineComponent({
+  name: "steps",
+  computed: {
+    stepOne() {
+      if (teacherState.active === 1) {
+        return baseActive
+      } else if (teacherState.active > 1) {
+        return baseFinish
+      } else {
+        return baseDefault
+      }
+    },
+    stepTwo() {
+      if (teacherState.active === 2) {
+        return nameActive
+      } else if (teacherState.active > 2) {
+        return nameFinish
+      } else {
+        return nameDefault
+      }
+    },
+    stepThree() {
+      if (teacherState.active === 3) {
+        return educationActive
+      } else if (teacherState.active > 3) {
+        return educationFinish
+      } else {
+        return educationDefault
+      }
+    }
+  },
+  render() {
+    return (
+      <div class={[styles.steps, teacherState.active == 3 ? styles.paddingBottom12 : null]}>
+        <div class={styles.stepContent}>
+          <div class={[styles.stepItem]}>
+            <Icon name={this.stepOne} size="38" />
+            <p class={this.stepOne != baseDefault ? styles.active : null}>实名认证</p>
+          </div>
+          <div class={[styles.stepItem, styles.line, this.stepTwo != nameDefault ? styles.lineActive : null]}></div>
+          <div class={[styles.stepItem]}>
+            <Icon name={this.stepTwo} size="38" />
+            <p class={this.stepTwo != nameDefault ? styles.active : null}>基本信息</p>
+          </div>
+          <div class={[styles.stepItem, styles.line, this.stepThree != educationDefault ? styles.lineActive : null]}></div>
+          <div class={[styles.stepItem]}>
+            <Icon name={this.stepThree} size="38" />
+            <p class={this.stepThree != educationDefault ? styles.active : null}>学历信息</p>
+          </div>
+        </div>
+        { teacherState.active == 3 ? <div class={styles.stepTips}>
+          <Icon name={horn} size="20" style={{ marginRight: '6px' }} />
+          完整填写学历信息有助于您更快的通过认证审核
+        </div> : null }
+      </div>
+    )
+  }
+})

+ 11 - 0
src/teacher/teacherCert/teacherState.ts

@@ -0,0 +1,11 @@
+import { reactive } from 'vue';
+
+export const teacherState = reactive({
+  active: 1,
+  teacherCert: {
+    username: null,
+    idCard: null,
+    sex: 1,
+    birthday: null as any
+  }
+});