修改
17
App.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
onLaunch: function() {
|
||||||
|
console.log('App Launch')
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
console.log('App Show')
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
console.log('App Hide')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
|
||||||
|
@import "uview-ui/index.scss";
|
||||||
|
</style>
|
||||||
17
api/addexam/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import request from "../request.js"
|
||||||
|
|
||||||
|
export function getExamList() {
|
||||||
|
return request({
|
||||||
|
url: `/exam/api/exam/exam/getExamList?examType=2&userId=${uni.getStorageSync('examh5user').id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function save(data) {
|
||||||
|
return request({
|
||||||
|
url: `/exam/api/exam/registration/save`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
4
api/baseurl.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
var baseurl = "http://8.131.93.145:54012";
|
||||||
|
|
||||||
|
|
||||||
|
export default baseurl
|
||||||
8
api/examlist/index.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import request from "../request.js"
|
||||||
|
|
||||||
|
export function getRegExamList() {
|
||||||
|
return request({
|
||||||
|
url: `/exam/api/exam/registration/getRegExamList?userId=${uni.getStorageSync('examh5user').id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
10
api/login/index.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import request from "../request.js"
|
||||||
|
|
||||||
|
//注册
|
||||||
|
export function login(data) {
|
||||||
|
return request({
|
||||||
|
url: `/exam/api/sys/user/login`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
10
api/register/index.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import request from "../request.js"
|
||||||
|
|
||||||
|
//注册
|
||||||
|
export function reg(data) {
|
||||||
|
return request({
|
||||||
|
url: `/exam/api/sys/user/reg`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
53
api/request.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import baseurl from './baseurl.js'
|
||||||
|
|
||||||
|
var request = function(config) {
|
||||||
|
return new Promise((resolve, rejected) => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: ''
|
||||||
|
});
|
||||||
|
uni.request({
|
||||||
|
url: baseurl + config.url,
|
||||||
|
data: config.data,
|
||||||
|
method: config.method,
|
||||||
|
timeout: 10000,
|
||||||
|
header: {
|
||||||
|
...config.header,
|
||||||
|
token: uni.getStorageSync('examh5token')
|
||||||
|
},
|
||||||
|
success(res) {
|
||||||
|
uni.hideLoading();
|
||||||
|
if (res.data.code == 0) {
|
||||||
|
resolve(res.data)
|
||||||
|
} else if (res.data.code == 401 || res.data.code == 10010002 || res.data.code ==
|
||||||
|
90010001 || res.data.code == 90010002 || res.data.code == 90010005) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: res.data.msg,
|
||||||
|
showCancel: false,
|
||||||
|
success: function(res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.clearStorageSync();
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/login/login"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
showCancel: false,
|
||||||
|
content: res.data.msg,
|
||||||
|
success: function(res) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
uni.hideLoading();
|
||||||
|
rejected(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default request
|
||||||
12
api/user/index.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from "../request.js"
|
||||||
|
|
||||||
|
export function info(data) {
|
||||||
|
return request({
|
||||||
|
url: `/exam/api/sys/user/info`,
|
||||||
|
method: 'post',
|
||||||
|
header: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
52
components/signature/signature.vue
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<view class="signature" style="background-color: #F4F5F7;height: 800rpx;">
|
||||||
|
<Signature @init="onSignInit" style='background-color: #fff;height: 700rpx;width: 100%;'></Signature>
|
||||||
|
<view class="btns">
|
||||||
|
<button @click="clear">清空</button>
|
||||||
|
<button @click="revoke">撤回</button>
|
||||||
|
<button @click="saveTempFilePath">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Signature from '@/components/v-sign/v-sign.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Signature
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSignInit(signCtx) {
|
||||||
|
this.signCtx = signCtx
|
||||||
|
},
|
||||||
|
// 清空
|
||||||
|
clear() {
|
||||||
|
this.signCtx.clear()
|
||||||
|
},
|
||||||
|
// 撤回
|
||||||
|
revoke() {
|
||||||
|
this.signCtx.revoke()
|
||||||
|
},
|
||||||
|
// 保存为临时图片路径,h5返回 base64
|
||||||
|
async saveTempFilePath() {
|
||||||
|
const res = await this.signCtx.canvasToTempFilePath()
|
||||||
|
this.$emit('userSignaturePictureUrl', res)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss'>
|
||||||
|
.signature {
|
||||||
|
height: 800rpx;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btns {
|
||||||
|
margin-top: 50rpx;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
15
components/v-sign/utils.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* 判断是否未数值
|
||||||
|
* @param {Object} val
|
||||||
|
*/
|
||||||
|
export function isNumber(val) {
|
||||||
|
return !isNaN(Number(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理大小单位
|
||||||
|
* @param {Object} val
|
||||||
|
*/
|
||||||
|
export function formatSize(val) {
|
||||||
|
return isNumber(val) ? `${val}rpx` : val
|
||||||
|
}
|
||||||
162
components/v-sign/v-sign-action.vue
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<template>
|
||||||
|
<view class="v-sign-action" :style="[customStyle]">
|
||||||
|
<view
|
||||||
|
v-for="item in btns"
|
||||||
|
:key="item.label"
|
||||||
|
:class="['btn', { border: border }]"
|
||||||
|
:style="[{ 'margin-right': formatSize(space) }]"
|
||||||
|
@click="onBtnClick(item)"
|
||||||
|
>
|
||||||
|
<image :class="['icon', 'icon-' + item.action]" :src="item.icon"></image>
|
||||||
|
<text class="text">{{ item.label }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* v-sign-action 控制按钮组(v-sign 子组件)
|
||||||
|
* @description 控制 v-sign 组件的一些按钮
|
||||||
|
* @tutorial
|
||||||
|
* @property {Array} actions 按钮配置 所有值: 清空(clear), 撤回(prev) 保存图片(save)
|
||||||
|
* @property {Boolean} border 按钮是否有边框
|
||||||
|
* @property {String/Number} space 按钮间隔
|
||||||
|
* @property {Object} customStyle 根元素自定义样式
|
||||||
|
* @event {Function} 点击对应类型按钮触发对应事件, 例如点击 clear 则触发 clear 事件
|
||||||
|
* @example 示例
|
||||||
|
**/
|
||||||
|
import { formatSize } from './utils'
|
||||||
|
|
||||||
|
// v-sign 父组件提供的接口
|
||||||
|
let vSignInterface
|
||||||
|
// 按钮类型
|
||||||
|
const btn_type = {
|
||||||
|
CLEAR: 'clear', // 清空
|
||||||
|
PREV: 'prev', // 撤回/上一步
|
||||||
|
// NEXT: 'next',
|
||||||
|
SAVE: 'save' // 保存临时图片
|
||||||
|
}
|
||||||
|
const all_action = Object.values(btn_type)
|
||||||
|
const btnsConf = [
|
||||||
|
{
|
||||||
|
label: '清空',
|
||||||
|
action: btn_type.CLEAR,
|
||||||
|
icon: '/static/v-sign/clear.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '撤回',
|
||||||
|
action: btn_type.PREV,
|
||||||
|
icon: '/static/v-sign/prev.png'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// label: '取消撤回',
|
||||||
|
// action: btn_type.NEXT,
|
||||||
|
// icon: '/static/v-sign/next.png'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
label: '保存',
|
||||||
|
action: btn_type.SAVE,
|
||||||
|
icon: '/static/v-sign/save.png'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
export default {
|
||||||
|
name: 'v-sign-action',
|
||||||
|
props: {
|
||||||
|
// 按钮配置
|
||||||
|
actions: {
|
||||||
|
type: Array,
|
||||||
|
default: () => all_action
|
||||||
|
},
|
||||||
|
// 按钮是否有边框
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 按钮间隔
|
||||||
|
space: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 12
|
||||||
|
},
|
||||||
|
// 根元素自定义样式
|
||||||
|
customStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inject: ['getInterface'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formatSize
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
btns() {
|
||||||
|
return btnsConf.filter(item => this.actions.includes(item.action))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
vSignInterface = this.getInterface()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async onBtnClick(btn) {
|
||||||
|
// console.log(btn, btn.action)
|
||||||
|
let emit_result
|
||||||
|
switch (btn.action) {
|
||||||
|
case btn_type.CLEAR:
|
||||||
|
vSignInterface.clear()
|
||||||
|
break
|
||||||
|
case btn_type.PREV:
|
||||||
|
vSignInterface.revoke()
|
||||||
|
break
|
||||||
|
// case btn_type.NEXT:
|
||||||
|
// console.log('next')
|
||||||
|
// break
|
||||||
|
case btn_type.SAVE:
|
||||||
|
emit_result = await vSignInterface.canvasToTempFilePath()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// console.log(btn.action, emit_result);
|
||||||
|
// 触发按钮对应类型事件
|
||||||
|
this.$emit(btn.action, emit_result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.v-sign-action {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
.btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 12rpx;
|
||||||
|
min-width: 88rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
&.border {
|
||||||
|
border: 2rpx solid #666;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
&.icon-clear,
|
||||||
|
&.icon-prev,
|
||||||
|
&.icon-next {
|
||||||
|
margin-right: 4rpx;
|
||||||
|
}
|
||||||
|
&.icon-save {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.text {
|
||||||
|
color: #666;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
211
components/v-sign/v-sign-pen.vue
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
<template>
|
||||||
|
<view class="v-sign-pen">
|
||||||
|
<view class="label" v-if="label">{{ label }}</view>
|
||||||
|
<view class="options">
|
||||||
|
<view
|
||||||
|
class="opt-item"
|
||||||
|
:style="{
|
||||||
|
minHeight: minWrapHeight,
|
||||||
|
marginRight: space + 'rpx'
|
||||||
|
}"
|
||||||
|
v-for="item in csizes"
|
||||||
|
:key="item.size"
|
||||||
|
@click="onItemClick(item)"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
:class="type"
|
||||||
|
:style="{
|
||||||
|
border:
|
||||||
|
border && currentSelect.size === item.size
|
||||||
|
? `${borderWidth}rpx solid ${activeColor}`
|
||||||
|
: ''
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<view class="inner" :style="[defaultInnerStyle(item)]"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* v-sign-pen 画笔(v-sign 子组件)
|
||||||
|
* @description 控制 v-sign 画笔的线宽
|
||||||
|
* @tutorial
|
||||||
|
* @property {String} type 选项样式 line / circle
|
||||||
|
* @property {String} label 标签
|
||||||
|
* @property {Array} sizes 画笔大小数组,单位 px
|
||||||
|
* @property {String} color 选项颜色
|
||||||
|
* @property {String} activeColor 选中项颜色
|
||||||
|
* @property {Boolean} border 选中项是否有边框
|
||||||
|
* @property {Number} borderWidth 边框大小,单位 rpx
|
||||||
|
* @property {String} space 选项间隙,单位 rpx
|
||||||
|
* @property {Number} bigger 圆点变大变粗倍数
|
||||||
|
* @property {Number} minSize 圆点最小大小,单位 px
|
||||||
|
* @event {Function} change 选择画笔大小时触发
|
||||||
|
* @example
|
||||||
|
**/
|
||||||
|
// v-sign 父组件提供的接口
|
||||||
|
let vSignInterface
|
||||||
|
// 选项样式
|
||||||
|
const type_style = {
|
||||||
|
CIRCLE: 'circle',
|
||||||
|
LINE: 'line'
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
name: 'v-sign-pen',
|
||||||
|
props: {
|
||||||
|
// 选项样式
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: type_style.CIRCLE
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
// 画笔大小数组,单位是px
|
||||||
|
sizes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [2, 4, 6, 8, 10]
|
||||||
|
},
|
||||||
|
// 选项颜色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#333'
|
||||||
|
},
|
||||||
|
// 选中项颜色
|
||||||
|
activeColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#333'
|
||||||
|
},
|
||||||
|
// 选中项是否有边框
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 边框大小, 单位 rpx
|
||||||
|
borderWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 4
|
||||||
|
},
|
||||||
|
// 选项间隙, 单位 rpx
|
||||||
|
space: {
|
||||||
|
type: Number,
|
||||||
|
default: 20
|
||||||
|
},
|
||||||
|
// 圆点变大变粗倍数
|
||||||
|
bigger: {
|
||||||
|
type: Number,
|
||||||
|
default: 2
|
||||||
|
},
|
||||||
|
// 圆点最小大小,单位 px
|
||||||
|
minSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inject: ['getInterface'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
type_style,
|
||||||
|
currentSelect: null,
|
||||||
|
csizes: [],
|
||||||
|
maxSize: 0,
|
||||||
|
maxCsize: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
minWrapHeight() {
|
||||||
|
let height
|
||||||
|
switch (this.type) {
|
||||||
|
case type_style.CIRCLE:
|
||||||
|
height = this.maxCsize + 10 + 'px'
|
||||||
|
break
|
||||||
|
case type_style.LINE:
|
||||||
|
height = this.maxSize + 4 + 'px'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return height
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.csizes = this.sizes.map((size, index) => {
|
||||||
|
const csize = (index + 1) * this.bigger + this.minSize
|
||||||
|
this.maxSize = csize > this.maxSize ? csize : this.maxSize
|
||||||
|
this.maxCsize = csize > this.maxCsize ? csize : this.maxCsize
|
||||||
|
return {
|
||||||
|
size,
|
||||||
|
csize
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.currentSelect = this.csizes[0]
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
vSignInterface = this.getInterface()
|
||||||
|
this.setLineWidth()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onItemClick(opt) {
|
||||||
|
this.currentSelect = opt
|
||||||
|
this.setLineWidth()
|
||||||
|
this.$emit('change', opt.size)
|
||||||
|
},
|
||||||
|
setLineWidth() {
|
||||||
|
vSignInterface.setLineWidth(this.currentSelect.size)
|
||||||
|
},
|
||||||
|
defaultInnerStyle(item) {
|
||||||
|
let width
|
||||||
|
let height
|
||||||
|
switch (this.type) {
|
||||||
|
case type_style.CIRCLE:
|
||||||
|
width = `${item.csize}px`
|
||||||
|
height = `${item.csize}px`
|
||||||
|
break
|
||||||
|
case type_style.LINE:
|
||||||
|
width = '20px'
|
||||||
|
height = `${item.size}px`
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const background = this.currentSelect.size === item.size ? this.activeColor : this.color
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
background
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.v-sign-pen {
|
||||||
|
padding: 12rpx;
|
||||||
|
.label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.options {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
.opt-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: center;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.circle {
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 4rpx;
|
||||||
|
.inner {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.line {
|
||||||
|
padding: 4rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
238
components/v-sign/v-sign.vue
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
<template>
|
||||||
|
<view class="signature-wrap">
|
||||||
|
<canvas
|
||||||
|
:canvas-id="cid"
|
||||||
|
:id="cid"
|
||||||
|
@touchstart="onTouchStart"
|
||||||
|
@touchmove="onTouchMove"
|
||||||
|
@touchend="onTouchEnd"
|
||||||
|
style="height:600rpx"
|
||||||
|
:style="[{ width: formatSize(width)}, customStyle]"
|
||||||
|
></canvas>
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* sign canvas 手写签名
|
||||||
|
* @description 设置线条宽度、颜色,撤回,清空
|
||||||
|
* @tutorial
|
||||||
|
* @property {String} cid canvas id 不设置则默认为 v-sign-时间戳
|
||||||
|
* @property {String, Number} width canvas 宽度
|
||||||
|
* @property {String, Number} height canvas 高度
|
||||||
|
* @property {Object} customStyle 自定义样式
|
||||||
|
* @property {String} lineColor 画笔颜色
|
||||||
|
* @property {Number} lineWidth 画笔大小,权重大于 v-sign-pen 组件设置的画笔大小
|
||||||
|
* @event {Function} init 当创建完 canvas 实例后触发,向外提供 canvas实例,撤回,清空方法
|
||||||
|
* @example <v-sign @init="signInit"></v-sign>
|
||||||
|
*/
|
||||||
|
import { formatSize } from './utils'
|
||||||
|
// convas 实例
|
||||||
|
let canvasCtx
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'v-sign',
|
||||||
|
props: {
|
||||||
|
// canvas id
|
||||||
|
cid: {
|
||||||
|
type: String,
|
||||||
|
default: `v-sign-${Date.now()}`
|
||||||
|
// required: true
|
||||||
|
},
|
||||||
|
// canvas 宽度
|
||||||
|
width: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '100%'
|
||||||
|
},
|
||||||
|
// canvas 高度
|
||||||
|
height: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 300
|
||||||
|
},
|
||||||
|
// 画笔大小,权重大于 v-sign-pen 组件设置的画笔大小
|
||||||
|
lineWidth: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
// 线颜色
|
||||||
|
lineColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#000'
|
||||||
|
},
|
||||||
|
// canvas自定义样式
|
||||||
|
customStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
provide() {
|
||||||
|
return {
|
||||||
|
getInterface: this.provideInterface
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formatSize,
|
||||||
|
lineData: [],
|
||||||
|
winWidth: 0,
|
||||||
|
winHeight: 0,
|
||||||
|
penLineWidth: null, // v-sign-pen 组件设置的画笔大小
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
canvasCtx = uni.createCanvasContext(this.cid, this)
|
||||||
|
// 初始化完成,向外暴露接口
|
||||||
|
this.$emit('init', this.provideInterface())
|
||||||
|
// 获取窗口宽高
|
||||||
|
uni.getSystemInfo({
|
||||||
|
success: res => {
|
||||||
|
this.winWidth = res.windowWidth
|
||||||
|
this.winHeight = res.windowHeight
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onTouchStart(e) {
|
||||||
|
const pos = e.touches[0]
|
||||||
|
this.lineData.push({
|
||||||
|
style: {
|
||||||
|
color: this.lineColor,
|
||||||
|
width: this.lineWidth || this.penLineWidth || 4
|
||||||
|
},
|
||||||
|
// 屏幕坐标
|
||||||
|
coordinates: [
|
||||||
|
{
|
||||||
|
type: e.type,
|
||||||
|
x: pos.x,
|
||||||
|
y: pos.y
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
this.drawLine()
|
||||||
|
},
|
||||||
|
onTouchMove(e) {
|
||||||
|
const pos = e.touches[0]
|
||||||
|
this.lineData[this.lineData.length - 1].coordinates.push({
|
||||||
|
type: e.type,
|
||||||
|
x: pos.x,
|
||||||
|
y: pos.y
|
||||||
|
})
|
||||||
|
this.drawLine()
|
||||||
|
},
|
||||||
|
onTouchEnd(e) {
|
||||||
|
// console.log(e.type, e)
|
||||||
|
},
|
||||||
|
// 清空画布
|
||||||
|
clear() {
|
||||||
|
this.lineData = []
|
||||||
|
canvasCtx.clearRect(0, 0, this.winWidth, this.winHeight)
|
||||||
|
canvasCtx.draw()
|
||||||
|
},
|
||||||
|
// 撤销
|
||||||
|
revoke() {
|
||||||
|
this.lineData.pop()
|
||||||
|
this.lineData.forEach((item, index) => {
|
||||||
|
canvasCtx.beginPath()
|
||||||
|
canvasCtx.setLineCap('round')
|
||||||
|
canvasCtx.setStrokeStyle(item.style.color)
|
||||||
|
canvasCtx.setLineWidth(item.style.width)
|
||||||
|
item.coordinates.forEach(pos => {
|
||||||
|
if (pos.type == 'touchstart') {
|
||||||
|
canvasCtx.moveTo(pos.x, pos.y)
|
||||||
|
} else {
|
||||||
|
canvasCtx.lineTo(pos.x, pos.y)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
canvasCtx.stroke()
|
||||||
|
})
|
||||||
|
canvasCtx.draw()
|
||||||
|
},
|
||||||
|
// 绘制线条
|
||||||
|
drawLine() {
|
||||||
|
const lineDataLen = this.lineData.length
|
||||||
|
if (!lineDataLen) return
|
||||||
|
const currentLineData = this.lineData[lineDataLen - 1]
|
||||||
|
const coordinates = currentLineData.coordinates
|
||||||
|
const coordinatesLen = coordinates.length
|
||||||
|
if (!coordinatesLen) return
|
||||||
|
let startPos
|
||||||
|
let endPos
|
||||||
|
if (coordinatesLen < 2) {
|
||||||
|
// only start, no move event
|
||||||
|
startPos = coordinates[coordinatesLen - 1]
|
||||||
|
endPos = { x: startPos.x + 1, y: startPos.y }
|
||||||
|
} else {
|
||||||
|
startPos = coordinates[coordinatesLen - 2]
|
||||||
|
endPos = coordinates[coordinatesLen - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const style = currentLineData.style
|
||||||
|
canvasCtx.beginPath()
|
||||||
|
canvasCtx.setLineCap('round')
|
||||||
|
canvasCtx.setStrokeStyle(style.color)
|
||||||
|
canvasCtx.setLineWidth(style.width)
|
||||||
|
canvasCtx.moveTo(startPos.x, startPos.y)
|
||||||
|
canvasCtx.lineTo(endPos.x, endPos.y)
|
||||||
|
// const P1 = this.caculateBezier(startPos, endPos, centerPos)
|
||||||
|
// console.log(P1.x, P1.y)
|
||||||
|
// canvasCtx.moveTo(startPos.x, startPos.y)
|
||||||
|
// canvasCtx.quadraticCurveTo(P1.x, P1.y, endPos.x, endPos.y)
|
||||||
|
canvasCtx.stroke()
|
||||||
|
canvasCtx.draw(true)
|
||||||
|
},
|
||||||
|
canvasToTempFilePath(conf = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.canvasToTempFilePath(
|
||||||
|
{
|
||||||
|
canvasId: this.cid,
|
||||||
|
...conf,
|
||||||
|
success: res => {
|
||||||
|
resolve(res.tempFilePath)
|
||||||
|
},
|
||||||
|
fail: err => {
|
||||||
|
console.log('fail', err)
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setLineWidth(numberVal) {
|
||||||
|
this.penLineWidth = numberVal
|
||||||
|
},
|
||||||
|
provideInterface() {
|
||||||
|
return {
|
||||||
|
cid: this.cid,
|
||||||
|
ctx: canvasCtx,
|
||||||
|
clear: this.clear,
|
||||||
|
revoke: this.revoke,
|
||||||
|
canvasToTempFilePath: this.canvasToTempFilePath,
|
||||||
|
setLineWidth: this.setLineWidth
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 计算二次贝塞尔曲线 控制点 P1
|
||||||
|
* 起点 P0(x0,y0)、控制点P1(x1, y1)、P2(x2, y2)、曲线上任意点B(x, y)
|
||||||
|
* 二次贝塞尔公式:B(t) = (1-t)²P0 + 2t(1-t)P1 + t²P2
|
||||||
|
* 代入坐标得:
|
||||||
|
* x = (1-t)²*x0 + 2t(1-t)*x1 + t²*x2
|
||||||
|
* y = (1-t)²*y0 + 2t(1-t)*y1 + t²*y2
|
||||||
|
*/
|
||||||
|
caculateBezier(P0, P2, B, t = 0.5) {
|
||||||
|
const { x: x0, y: y0 } = P0
|
||||||
|
const { x: x2, y: y2 } = P2
|
||||||
|
const { x, y } = B
|
||||||
|
let x1 = (x - (1 - t) * (1 - t) * x0 - t * t * x2) / (2 * t * (1 - t))
|
||||||
|
let y1 = (y - (1 - t) * (1 - t) * y0 - t * t * y2) / (2 * t * (1 - t))
|
||||||
|
return { x: x1, y: y1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.signature-wrap {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
homepage.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
20
index.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script>
|
||||||
|
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||||
|
CSS.supports('top: constant(a)'))
|
||||||
|
document.write(
|
||||||
|
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||||
|
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||||
|
</script>
|
||||||
|
<title></title>
|
||||||
|
<!--preload-links-->
|
||||||
|
<!--app-context-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"><!--app-html--></div>
|
||||||
|
<script type="module" src="/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
main.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import App from './App'
|
||||||
|
|
||||||
|
// #ifndef VUE3
|
||||||
|
import Vue from 'vue'
|
||||||
|
import uView from "uview-ui";
|
||||||
|
Vue.use(uView);
|
||||||
|
import './uni.promisify.adaptor'
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
App.mpType = 'app'
|
||||||
|
const app = new Vue({
|
||||||
|
...App
|
||||||
|
})
|
||||||
|
app.$mount()
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef VUE3
|
||||||
|
import { createSSRApp } from 'vue'
|
||||||
|
export function createApp() {
|
||||||
|
const app = createSSRApp(App)
|
||||||
|
return {
|
||||||
|
app
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
72
manifest.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name" : "exam-h5",
|
||||||
|
"appid" : "__UNI__254C48E",
|
||||||
|
"description" : "",
|
||||||
|
"versionName" : "1.0.0",
|
||||||
|
"versionCode" : "100",
|
||||||
|
"transformPx" : false,
|
||||||
|
/* 5+App特有相关 */
|
||||||
|
"app-plus" : {
|
||||||
|
"usingComponents" : true,
|
||||||
|
"nvueStyleCompiler" : "uni-app",
|
||||||
|
"compilerVersion" : 3,
|
||||||
|
"splashscreen" : {
|
||||||
|
"alwaysShowBeforeRender" : true,
|
||||||
|
"waiting" : true,
|
||||||
|
"autoclose" : true,
|
||||||
|
"delay" : 0
|
||||||
|
},
|
||||||
|
/* 模块配置 */
|
||||||
|
"modules" : {},
|
||||||
|
/* 应用发布信息 */
|
||||||
|
"distribute" : {
|
||||||
|
/* android打包配置 */
|
||||||
|
"android" : {
|
||||||
|
"permissions" : [
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
/* ios打包配置 */
|
||||||
|
"ios" : {},
|
||||||
|
/* SDK配置 */
|
||||||
|
"sdkConfigs" : {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 快应用特有相关 */
|
||||||
|
"quickapp" : {},
|
||||||
|
/* 小程序特有相关 */
|
||||||
|
"mp-weixin" : {
|
||||||
|
"appid" : "",
|
||||||
|
"setting" : {
|
||||||
|
"urlCheck" : false
|
||||||
|
},
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-alipay" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-baidu" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"mp-toutiao" : {
|
||||||
|
"usingComponents" : true
|
||||||
|
},
|
||||||
|
"uniStatistics" : {
|
||||||
|
"enable" : false
|
||||||
|
},
|
||||||
|
"vueVersion" : "2"
|
||||||
|
}
|
||||||
28
package-lock.json
generated
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "exam-h5",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "exam-h5",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"uview-ui": "^1.8.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/uview-ui": {
|
||||||
|
"version": "1.8.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-1.8.8.tgz",
|
||||||
|
"integrity": "sha512-Osal3yzXiHor0In9OPTZuXTaqTbDglMZ9RGK/MPYDoQQs+y0hrBCUD0Xp5T70C8i2lLu2X6Z11zJhmsQWMR7Jg=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uview-ui": {
|
||||||
|
"version": "1.8.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-1.8.8.tgz",
|
||||||
|
"integrity": "sha512-Osal3yzXiHor0In9OPTZuXTaqTbDglMZ9RGK/MPYDoQQs+y0hrBCUD0Xp5T70C8i2lLu2X6Z11zJhmsQWMR7Jg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "exam-h5",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"uview-ui": "^1.8.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
73
pages.json
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"easycom": {
|
||||||
|
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
||||||
|
},
|
||||||
|
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||||
|
{
|
||||||
|
"path": "pages/login/login",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "登录",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"path": "pages/examlist/examlist",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"onReachBottomDistance": 40, //距离底部多远时触发 单位为px
|
||||||
|
"enablePullDownRefresh": true //设置参数为true
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"path": "pages/user/user",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"path": "pages/register/register",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "注册账号",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"path": "pages/forgotPassword/forgotPassword",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "忘记密码",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"path": "pages/addexam/addexam",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "新增考试",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"globalStyle": {
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"navigationBarTitleText": "",
|
||||||
|
"navigationBarBackgroundColor": "#4C7BC9",
|
||||||
|
"backgroundColor": "#4C7BC9"
|
||||||
|
},
|
||||||
|
"uniIdRouter": {},
|
||||||
|
"tabBar": {
|
||||||
|
"color": "#7A7E83",
|
||||||
|
"selectedColor": "#435950",
|
||||||
|
"borderStyle": "black",
|
||||||
|
"backgroundColor": "#ffffff",
|
||||||
|
"list": [{
|
||||||
|
"pagePath": "pages/examlist/examlist",
|
||||||
|
"iconPath": "static/homepagew.png",
|
||||||
|
"selectedIconPath": "static/homepagews.png",
|
||||||
|
"text": "首页"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/user/user",
|
||||||
|
"iconPath": "static/userw.png",
|
||||||
|
"selectedIconPath": "static/users.png",
|
||||||
|
"text": "我的"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
379
pages/addexam/addexam.scss
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
.app {
|
||||||
|
font-size: 34rpx;
|
||||||
|
padding-top: 10rpx;
|
||||||
|
height: 100%;
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding-bottom: 200rpx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
height: 100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
font-size: 34rpx;
|
||||||
|
margin: 0px auto;
|
||||||
|
width: 100%;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask {
|
||||||
|
.Agreement {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
height: 1000rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 5%;
|
||||||
|
width: 94%;
|
||||||
|
left: 3%;
|
||||||
|
font-size: 30rpx;
|
||||||
|
|
||||||
|
.scroll-Y {
|
||||||
|
width: 98%;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 830rpx;
|
||||||
|
overflow-y: scroll;
|
||||||
|
text-align: left;
|
||||||
|
text-indent: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel {
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
background-color: #F4F5F7;
|
||||||
|
position: absolute;
|
||||||
|
border-top: 1rpx solid #000000;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 50%;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.determine {
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
width: 50%;
|
||||||
|
color: #F4F5F7;
|
||||||
|
background: #4C7BC9;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.addressitem {
|
||||||
|
width: 97%;
|
||||||
|
border-bottom: 1rpx solid #D8D4D4;
|
||||||
|
margin-left: 3%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.leftaddress {
|
||||||
|
width: 15%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addition {
|
||||||
|
color: #666666;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 50rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.money {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #D43953;
|
||||||
|
position: absolute;
|
||||||
|
right: 5%;
|
||||||
|
top: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10rpx;
|
||||||
|
line-height: 93rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
|
||||||
|
.timeyear{
|
||||||
|
.bottomtext{
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
width: 96%;
|
||||||
|
margin: 0 auto;
|
||||||
|
.items{
|
||||||
|
display: flex;
|
||||||
|
justify-content:flex-start;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
text-align: center;
|
||||||
|
.timeitem{
|
||||||
|
width: 21%;
|
||||||
|
margin: 0 2% 20rpx;
|
||||||
|
height: 86rpx;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
line-height: 86rpx;
|
||||||
|
border: 2rpx solid #DADADA;
|
||||||
|
}
|
||||||
|
.timeitemtap{
|
||||||
|
width: 21%;
|
||||||
|
margin: 0 2% 20rpx;
|
||||||
|
height: 86rpx;
|
||||||
|
border: 2rpx solid #F44B2F;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #F44B2F;
|
||||||
|
line-height: 86rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.toptext{
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
padding-top: 10rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content:space-around;
|
||||||
|
height: 50rpx;
|
||||||
|
color: #000000;
|
||||||
|
line-height: 27rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
.Soonerorlater{
|
||||||
|
width: 200rpx;
|
||||||
|
font-size: 36rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
.Soonerorlaterclass{
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #F44B2F;
|
||||||
|
width: 200rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
view:nth-child(2){
|
||||||
|
width: 4rpx;
|
||||||
|
height: 27rpx;
|
||||||
|
background: #C5C3C3;
|
||||||
|
border-radius: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
width: 97%;
|
||||||
|
border-bottom: 1rpx solid #D8D4D4;
|
||||||
|
margin-left: 3%;
|
||||||
|
|
||||||
|
.addition {
|
||||||
|
color: #666666;
|
||||||
|
line-height: 30rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.remarks {
|
||||||
|
width: 94%;
|
||||||
|
margin: 10rpx auto;
|
||||||
|
padding: 3%;
|
||||||
|
font-size: 34rpx;
|
||||||
|
height: 96rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 20%;
|
||||||
|
// overflow: hidden;
|
||||||
|
// text-overflow: ellipsis;
|
||||||
|
// white-space: nowrap;
|
||||||
|
position: absolute;
|
||||||
|
top:50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
.input-placeholder{
|
||||||
|
color: #C5C3C3;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 23%;
|
||||||
|
width: 77%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.priceback {
|
||||||
|
width: 90%;
|
||||||
|
background: #FFFFFF;
|
||||||
|
height: 100rpx;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.queren {
|
||||||
|
width: 100%;
|
||||||
|
height: 90rpx;
|
||||||
|
background: #4C7BC9;
|
||||||
|
border-radius: 26rpx;
|
||||||
|
margin: 105rpx 0 0 15rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-content {
|
||||||
|
margin: 50rpx auto;
|
||||||
|
width: 70%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.agreement {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 20%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #878987;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-right {
|
||||||
|
height: 100rpx;
|
||||||
|
width: 100rpx;
|
||||||
|
|
||||||
|
.radio {
|
||||||
|
display: inline-block;
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
border-radius: 70%;
|
||||||
|
border: 2rpx solid #178ffb;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 5%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
|
||||||
|
.radio-active {
|
||||||
|
width: 16rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #178ffb;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
// margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.Consumablespackage .money {
|
||||||
|
top: 8%;
|
||||||
|
}
|
||||||
|
/* 耗材包 */
|
||||||
|
.Consumablespackage {
|
||||||
|
width: 94%;
|
||||||
|
margin: 10rpx auto;
|
||||||
|
padding: 3% 0 3% 3%;
|
||||||
|
font-size: 34rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: 40rpx;
|
||||||
|
::v-deep .u-checkbox__label{
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.detail {
|
||||||
|
width: 100%;
|
||||||
|
line-height: 100rpx;
|
||||||
|
// padding: 20rpx 0 0 40rpx;
|
||||||
|
position: relative;
|
||||||
|
.itemConsumabletitle{
|
||||||
|
width:55%;
|
||||||
|
position: absolute;
|
||||||
|
top:50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
/deep/ .u-checkbox{
|
||||||
|
margin: 40rpx 0 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
span{
|
||||||
|
width: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #D43953;
|
||||||
|
text-align: right;
|
||||||
|
position: absolute;
|
||||||
|
right:5%;
|
||||||
|
top:50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 套餐 */
|
||||||
|
.Package {
|
||||||
|
width: 97%;
|
||||||
|
height: 500rpx;
|
||||||
|
font-size: 34rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
margin: 20rpx auto 40rpx;
|
||||||
|
position: relative;
|
||||||
|
.uppicture {
|
||||||
|
border: 1rpx dashed #818181;
|
||||||
|
width: 90%;
|
||||||
|
height: 400rpx;
|
||||||
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 35rpx;
|
||||||
|
color: #969394;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkboxs{
|
||||||
|
margin-top: 30rpx;
|
||||||
|
::v-deep .u-checkbox{
|
||||||
|
padding-right: 40rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.detail {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 31rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #666666;
|
||||||
|
line-height: 31rpx;
|
||||||
|
position: absolute;
|
||||||
|
left: 10%;
|
||||||
|
top: 60%;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
width: 94%;
|
||||||
|
background: white;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 96rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
503
pages/addexam/addexam.vue
Normal file
@ -0,0 +1,503 @@
|
|||||||
|
<template>
|
||||||
|
<view class="app">
|
||||||
|
<view class="user">
|
||||||
|
<view class="title">
|
||||||
|
一、个人信息
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>姓名:</span>
|
||||||
|
<span class='addition'>{{personInfo.realName}}</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>手机号:</span>
|
||||||
|
<span class='addition'>{{personInfo.phone}}</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>身份证号:</span>
|
||||||
|
<span class='addition'>{{personInfo.userName}}</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>性别:</span>
|
||||||
|
<span class='addition'>{{personInfo.sex}}</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>出生日期:</span>
|
||||||
|
<span class='addition'>{{personInfo.birthday}}</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>电子邮箱(用于接收考试通知):</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-input type="text" placeholder="请输入电子邮箱" v-model="personInfo.email" />
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>通讯地址:</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-input type="text" placeholder="请输入通讯地址" v-model="personInfo.address" />
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="user">
|
||||||
|
<view class="title">
|
||||||
|
二、教育背景
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>最高学历:</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-radio-group v-model="personInfo.education" @change="">
|
||||||
|
<u-radio @change="" v-for="(item, index) in educationlist" :key="index" :name="item.label"
|
||||||
|
style="padding: 0 15rpx;" :disabled="item.checked">
|
||||||
|
{{item.name}}
|
||||||
|
</u-radio>
|
||||||
|
</u-radio-group>
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>毕业院校:</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-input type="text" placeholder="请输入毕业院校" v-model="personInfo.graduateSchool" />
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>专业(如适用):</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-input type="text" placeholder="请输入专业" v-model="personInfo.major" />
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="user">
|
||||||
|
<view class="title">
|
||||||
|
三、报考信息
|
||||||
|
<span class='addition' @click="examshow=true"
|
||||||
|
style="margin-left:20rpx;padding:6rpx 20rpx;background: #4C7BC9;border-radius: 10rpx;color: #fff;">
|
||||||
|
选择考试
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>考试名称:</span>
|
||||||
|
<span class='addition' v-if="personInfo.title">
|
||||||
|
{{personInfo.title}}
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>考试日期:</span>
|
||||||
|
<span class='addition' v-if="personInfo.title">
|
||||||
|
{{personInfo.startDate}}至{{personInfo.endDate}}
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>考试时间:</span>
|
||||||
|
<span class='addition' v-if="personInfo.title">
|
||||||
|
{{personInfo.startTime}}至{{personInfo.endTime}}
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>考试费用:</span>
|
||||||
|
<span class='addition' v-if="personInfo.title" style="color:red">
|
||||||
|
¥{{personInfo.examFee}}
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>报考类别(可选):</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-radio-group v-model="personInfo.regType" @change="">
|
||||||
|
<u-radio @change="" v-for="(item, index) in regTypelist" :key="index" :name="item.label"
|
||||||
|
style="padding: 15rpx;" :disabled="item.checked">
|
||||||
|
{{item.name}}
|
||||||
|
</u-radio>
|
||||||
|
</u-radio-group>
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>培训经历(如有):</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<view class="item" style="padding: 10rpx 0;">
|
||||||
|
<span>机构名称:</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-input type="text" placeholder="请输入机构名称" v-model="personInfo.trainInstitution" />
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="padding: 10rpx 0;">
|
||||||
|
<span>培训时间:</span>
|
||||||
|
<span class='addition' @click="trainDateshow=true"
|
||||||
|
style="margin-left:50rpx;display: inline-block;padding: 10rpx;background-color: #4C7BC9;border-radius: 10rpx;color: #fff;">
|
||||||
|
选择时间区间
|
||||||
|
</span>
|
||||||
|
<view class="" v-if="personInfo.trainStartDate" style="padding: 16rpx 0;">
|
||||||
|
{{personInfo.trainStartDate+'至'}}{{personInfo.trainEndDate}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="user">
|
||||||
|
<view class="title">
|
||||||
|
四、上传材料
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>身份证正面:</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-upload :action="action" :form-data="{
|
||||||
|
type:'cardFrontUrl'
|
||||||
|
}" :header="header" :file-list="fileList" :max-count="1" @on-uploaded="uploadedcardFront"></u-upload>
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>身份证反面:</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-upload :action="action" :form-data="{
|
||||||
|
type:'cardBackUrl'
|
||||||
|
}" :header="header" :file-list="fileList" :max-count="1" @on-uploaded="uploadedcardBack"></u-upload>
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="line-height: 50rpx;">
|
||||||
|
<span>近期白底免冠证件照(1寸,JPG格式,<20KB):</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-upload :action="action" :form-data="{
|
||||||
|
type:'photoUrl'
|
||||||
|
}" :header="header" :file-list="fileList" :max-count="1" @on-uploaded="uploadedphoto"></u-upload>
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="line-height: 50rpx;">
|
||||||
|
<span>学历证明(毕业证或学信网截图):</span>
|
||||||
|
<span class='addition'>
|
||||||
|
<u-upload :action="action" :form-data="{
|
||||||
|
type:'certificateUrl'
|
||||||
|
}" :header="header" :file-list="fileList" :max-count="1" @on-uploaded="uploadedcertificate"></u-upload>
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="user">
|
||||||
|
<view class="title">
|
||||||
|
五、声明与签字
|
||||||
|
</view>
|
||||||
|
<view style="line-height: 40rpx;font-size: 32rpx;color:red;padding:0 10rpx">
|
||||||
|
本人确认以上信息真实有效,并同意考试机构核实相关信息。
|
||||||
|
</view>
|
||||||
|
<view class="Package">
|
||||||
|
签名:
|
||||||
|
<span style='color:#C5C3C3;padding-left: 10rpx;font-size: 30rpx;'></span>
|
||||||
|
<view class="checkboxs">
|
||||||
|
<view class="uppicture" @tap='signatureshow=true'>
|
||||||
|
<image v-if="!userSignaturePictureUrl" style="width: 36rpx;height: 36rpx;margin:8% 0 0 35%"
|
||||||
|
src="@/static/autograph.png" mode="">
|
||||||
|
</image>
|
||||||
|
<span v-if="!userSignaturePictureUrl">点此签名</span>
|
||||||
|
<image v-else :src="userSignaturePictureUrl" mode=""></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<span>日期:</span>
|
||||||
|
<span class='addition'>
|
||||||
|
{{personInfo.regTime}}
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="priceback">
|
||||||
|
<view class="queren" @tap='updata'>保存</view>
|
||||||
|
</view>
|
||||||
|
<u-toast ref="uToast" />
|
||||||
|
<u-mask :show="signatureshow" @click="signatureshow = false">
|
||||||
|
<view style="position:absolute;bottom:0;height:900rpx;width:100%;background-color: #fff;"
|
||||||
|
v-if='signatureshow'>
|
||||||
|
<signature @userSignaturePictureUrl='userSignaturePicture' @click.native.stop
|
||||||
|
style='background-color: #F4F5F7;width: 100%;height: 900rpx;'></signature>
|
||||||
|
</view>
|
||||||
|
</u-mask>
|
||||||
|
<u-select v-model="examshow" :list="examlist" @confirm="examconfirm" value-name="id"
|
||||||
|
label-name="title"></u-select>
|
||||||
|
<u-calendar v-model="trainDateshow" mode="range" @change="trainDatechange"></u-calendar>
|
||||||
|
<u-toast ref="uToast" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
info
|
||||||
|
} from '@/api/user/index.js'
|
||||||
|
import {
|
||||||
|
getExamList,
|
||||||
|
save
|
||||||
|
} from '@/api/addexam/index.js'
|
||||||
|
import baseurl from '@/api/baseurl.js'
|
||||||
|
import signature from '@/components/signature/signature.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
signature
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
examshow: false,
|
||||||
|
trainDateshow: false,
|
||||||
|
signatureshow: false,
|
||||||
|
userSignaturePictureUrl: null,
|
||||||
|
examlist: [],
|
||||||
|
educationlist: [{
|
||||||
|
name: '初中',
|
||||||
|
label: 1,
|
||||||
|
checked: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '高中/中专',
|
||||||
|
label: 2,
|
||||||
|
checked: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '大专及以上',
|
||||||
|
label: 3,
|
||||||
|
checked: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
regTypelist: [{
|
||||||
|
name: '普通医疗护理员',
|
||||||
|
label: 1,
|
||||||
|
checked: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '老年医疗护理员',
|
||||||
|
label: 2,
|
||||||
|
checked: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '孕产妇和新生儿医疗护理员',
|
||||||
|
label: 3,
|
||||||
|
checked: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
action: baseurl + '/exam/api/file/upload',
|
||||||
|
header: {
|
||||||
|
token: uni.getStorageSync('examh5token')
|
||||||
|
},
|
||||||
|
fileList: [],
|
||||||
|
personInfo: {
|
||||||
|
"address": "",
|
||||||
|
"cardBack": "",
|
||||||
|
"cardCopy": "", // 身份证正反面复印件
|
||||||
|
"cardFront": "",
|
||||||
|
"certificate": "",
|
||||||
|
"education": 0,
|
||||||
|
"email": "",
|
||||||
|
"examId": "",
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
startDate: undefined,
|
||||||
|
endDate: undefined,
|
||||||
|
"graduateSchool": "",
|
||||||
|
"major": "",
|
||||||
|
"phone": "",
|
||||||
|
"photo": "",
|
||||||
|
"physicalReport": "", //健康体检报告
|
||||||
|
"realName": "",
|
||||||
|
"regTime": "",
|
||||||
|
"regType": 0,
|
||||||
|
"signPicture": "",
|
||||||
|
"title": "",
|
||||||
|
"trainEndDate": "",
|
||||||
|
"trainInstitution": "",
|
||||||
|
"trainStartDate": "",
|
||||||
|
"userId": "",
|
||||||
|
"userName": "",
|
||||||
|
examFee: undefined,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShow() {},
|
||||||
|
onLoad() {
|
||||||
|
this.getTodayDate()
|
||||||
|
this.myInfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
uploadedcertificate(res) {
|
||||||
|
this.personInfo.certificate = res[0].response.data.url
|
||||||
|
},
|
||||||
|
uploadedphoto(res) {
|
||||||
|
this.personInfo.photo = res[0].response.data.url
|
||||||
|
},
|
||||||
|
uploadedcardBack(res) {
|
||||||
|
this.personInfo.cardBack = res[0].response.data.url
|
||||||
|
},
|
||||||
|
uploadedcardFront(res) {
|
||||||
|
this.personInfo.cardFront = res[0].response.data.url
|
||||||
|
},
|
||||||
|
examconfirm(e) {
|
||||||
|
let obj = this.examlist.filter(el => el.id == e[0].value)
|
||||||
|
this.personInfo.title = e[0].label
|
||||||
|
this.personInfo.examId = e[0].value
|
||||||
|
this.personInfo.startTime = obj[0].startTime
|
||||||
|
this.personInfo.endTime = obj[0].endTime
|
||||||
|
this.personInfo.startDate = obj[0].startDate
|
||||||
|
this.personInfo.endDate = obj[0].endDate
|
||||||
|
this.personInfo.examFee = obj[0].examFee
|
||||||
|
},
|
||||||
|
trainDatechange(e) {
|
||||||
|
this.personInfo.trainEndDate = e.endDate
|
||||||
|
this.personInfo.trainStartDate = e.startDate
|
||||||
|
},
|
||||||
|
//签名
|
||||||
|
userSignaturePicture(data) {
|
||||||
|
let that = this
|
||||||
|
this.userSignaturePictureUrl = data
|
||||||
|
this.signatureshow = false
|
||||||
|
uni.uploadFile({
|
||||||
|
url: baseurl + '/exam/api/file/upload',
|
||||||
|
filePath: this.userSignaturePictureUrl,
|
||||||
|
name: 'file',
|
||||||
|
header: this.header,
|
||||||
|
formData: {
|
||||||
|
type: 'signPictureUrl'
|
||||||
|
},
|
||||||
|
timeout: 5000,
|
||||||
|
success(res) {
|
||||||
|
that.personInfo.signPicture = JSON.parse(res.data).data.url
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//确认
|
||||||
|
updata() {
|
||||||
|
save(this.personInfo).then(res => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: '报名考试成功!',
|
||||||
|
type: 'success',
|
||||||
|
duration: '1500',
|
||||||
|
back: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
myInfo() {
|
||||||
|
info({
|
||||||
|
token: uni.getStorageSync('examh5token')
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
uni.setStorageSync("examh5token", res.data.token)
|
||||||
|
uni.setStorageSync("examh5user", {
|
||||||
|
id: res.data.id,
|
||||||
|
phone: res.data.phone,
|
||||||
|
name: res.data.realName,
|
||||||
|
cardNo: res.data.userName
|
||||||
|
})
|
||||||
|
this.personInfo.realName = res.data.realName
|
||||||
|
this.personInfo.userId = res.data.id
|
||||||
|
this.personInfo.phone = res.data.phone
|
||||||
|
this.personInfo.userName = res.data.userName
|
||||||
|
this.personInfo.sex = this.getsex(res.data.userName)
|
||||||
|
this.personInfo.birthday = this.getbirthday(res.data.userName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
getExamList().then(res => {
|
||||||
|
this.examlist = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getTodayDate() {
|
||||||
|
const today = new Date();
|
||||||
|
this.personInfo.regTime = today.toISOString().split('T')[0];
|
||||||
|
},
|
||||||
|
getsex(idCard) {
|
||||||
|
// 在Vue组件的方法中
|
||||||
|
if (!idCard || idCard.length !== 18) {
|
||||||
|
return '身份证号码不合法';
|
||||||
|
}
|
||||||
|
// 获取第17位字符
|
||||||
|
const genderChar = idCard.charAt(16);
|
||||||
|
// 判断是否为数字
|
||||||
|
if (isNaN(genderChar)) {
|
||||||
|
return '身份证号码不合法';
|
||||||
|
}
|
||||||
|
// 转换为数字并判断奇偶
|
||||||
|
const genderNum = parseInt(genderChar, 10);
|
||||||
|
return genderNum % 2 === 1 ? '男' : '女';
|
||||||
|
},
|
||||||
|
getbirthday(idCard) {
|
||||||
|
// 在Vue组件的方法中
|
||||||
|
if (!idCard) {
|
||||||
|
return '身份证号码不能为空';
|
||||||
|
}
|
||||||
|
// 处理18位身份证
|
||||||
|
if (idCard.length === 18) {
|
||||||
|
if (!/^\d{17}[\dXx]$/.test(idCard)) {
|
||||||
|
return '身份证号码格式不正确';
|
||||||
|
}
|
||||||
|
// 提取出生年月日 YYYYMMDD
|
||||||
|
const birthdayStr = idCard.substr(6, 8);
|
||||||
|
// 格式化为 YYYY-MM-DD
|
||||||
|
return `${birthdayStr.substr(0, 4)}-${birthdayStr.substr(4, 2)}-${birthdayStr.substr(6, 2)}`;
|
||||||
|
}
|
||||||
|
// 处理15位身份证
|
||||||
|
if (idCard.length === 15) {
|
||||||
|
if (!/^\d{15}$/.test(idCard)) {
|
||||||
|
return '身份证号码格式不正确';
|
||||||
|
}
|
||||||
|
// 提取出生年月日 YYMMDD
|
||||||
|
const birthdayStr = idCard.substr(6, 6);
|
||||||
|
// 格式化为 19YY-MM-DD (15位身份证都是19XX年出生的)
|
||||||
|
return `19${birthdayStr.substr(0, 2)}-${birthdayStr.substr(2, 2)}-${birthdayStr.substr(4, 2)}`;
|
||||||
|
}
|
||||||
|
return '身份证号码长度不正确';
|
||||||
|
},
|
||||||
|
argAdd(arg1, arg2) {
|
||||||
|
// 加法函数
|
||||||
|
var _this = this,
|
||||||
|
r1 = 0,
|
||||||
|
r2 = 0,
|
||||||
|
m = 0;
|
||||||
|
try {
|
||||||
|
r1 = arg1.toString().split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
r2 = arg2.toString().split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
m = Math.pow(10, Math.max(r1, r2))
|
||||||
|
return _this.argDiv((_this.argMul(arg1, m) + _this.argMul(arg2, m)), m)
|
||||||
|
},
|
||||||
|
argSubtr(arg1, arg2) {
|
||||||
|
// 减法函数
|
||||||
|
var _this = this,
|
||||||
|
r1 = 0,
|
||||||
|
r2 = 0,
|
||||||
|
m = 0;
|
||||||
|
try {
|
||||||
|
r1 = arg1.toString().split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
r2 = arg2.toString().split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
m = Math.pow(10, Math.max(r1, r2));
|
||||||
|
return _this.argDiv((_this.argMul(arg1, m) - _this.argMul(arg2, m)), m)
|
||||||
|
},
|
||||||
|
argMul(arg1, arg2) {
|
||||||
|
// 乘法函数
|
||||||
|
var _this = this,
|
||||||
|
m = 0,
|
||||||
|
s1 = arg1.toString(),
|
||||||
|
s2 = arg2.toString();
|
||||||
|
try {
|
||||||
|
m += s1.split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
m += s2.split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
|
||||||
|
},
|
||||||
|
argDiv(arg1, arg2) {
|
||||||
|
// 除法函数
|
||||||
|
var _this = this,
|
||||||
|
t1 = 0,
|
||||||
|
t2 = 0,
|
||||||
|
r1, r2;
|
||||||
|
try {
|
||||||
|
t1 = arg1.toString().split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
try {
|
||||||
|
t2 = arg2.toString().split(".")[1].length
|
||||||
|
} catch (e) {}
|
||||||
|
r1 = Number(arg1.toString().replace(".", ""))
|
||||||
|
r2 = Number(arg2.toString().replace(".", ""))
|
||||||
|
return _this.argMul((r1 / r2), Math.pow(10, t2 - t1));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
@import './addexam.scss'
|
||||||
|
</style>
|
||||||
175
pages/examlist/examlist.vue
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
<template>
|
||||||
|
<view class="">
|
||||||
|
<u-navbar :is-back="false" title="考试列表" :background="background" title-color="white">
|
||||||
|
<view class="navbar-right" slot="right" @click="signup">
|
||||||
|
新增考试
|
||||||
|
</view>
|
||||||
|
</u-navbar>
|
||||||
|
<view class="app">
|
||||||
|
<view class="items" v-if="list.length>0">
|
||||||
|
<view class="item" v-for="(item,index) in list">
|
||||||
|
<view class="title">
|
||||||
|
<view class="text">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
|
<view class="image">
|
||||||
|
<image src="../../static/jinbi.png" mode=""></image>
|
||||||
|
<span v-if="item.examFee&&item.examFee>=0">
|
||||||
|
{{item.examFee}}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
0
|
||||||
|
</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="time" style="margin-top: 20rpx;color: #EA706A;font-weight:600">
|
||||||
|
考试费用:{{item.examFee}}
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
考试日期:{{item.startDate}}至{{item.endDate}}
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
考试时间:{{item.startTime}}至{{item.endTime}}
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
考试时长:{{item.totalTime}}分钟
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
试卷总分:{{item.totalScore}}
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
考试人员:{{user.name}}
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
身份证:{{user.cardNo}}
|
||||||
|
</view>
|
||||||
|
<view class="time">
|
||||||
|
手机号:{{user.phone}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-else class="" style="margin-top: 100rpx;">
|
||||||
|
<u-empty text="暂无工单" mode="list" icon-size='240' font-size='32'></u-empty>
|
||||||
|
</view>
|
||||||
|
<u-toast ref="uToast" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getRegExamList
|
||||||
|
} from '@/api/examlist/index.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
user: uni.getStorageSync('examh5user'),
|
||||||
|
background: {
|
||||||
|
backgroundColor: "#4C7BC9",
|
||||||
|
},
|
||||||
|
list: [], //项目list
|
||||||
|
total: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//考试报名
|
||||||
|
signup() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/addexam/addexam"
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//list请求
|
||||||
|
info() {
|
||||||
|
getRegExamList().then(res => {
|
||||||
|
this.list = res.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onLoad() {},
|
||||||
|
onShow() {
|
||||||
|
this.info();
|
||||||
|
},
|
||||||
|
onReachBottom() { //下滑加载
|
||||||
|
if (this.list.length >= this.total) {} else {}
|
||||||
|
},
|
||||||
|
onPullDownRefresh() { //下拉刷新
|
||||||
|
this.info();
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.navbar-right {
|
||||||
|
color: #fff;
|
||||||
|
padding-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.items {
|
||||||
|
width: 96%;
|
||||||
|
margin: 20rpx auto;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin: 10rpx auto;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0rpx 9rpx 31rpx 9rpx rgba(0, 0, 0, 0.03);
|
||||||
|
border-radius: 5rpx;
|
||||||
|
padding: 10rpx;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 30rpx;
|
||||||
|
padding-bottom: 60rpx;
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
line-height: 100rpx;
|
||||||
|
border-bottom: 1rpx solid #E6E6E6;
|
||||||
|
font-size: 38rpx;
|
||||||
|
color: #333333;
|
||||||
|
position: relative;
|
||||||
|
height: 100rpx;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden; //超出的文本隐藏
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 1; // 超出多少行
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
width: calc(100% - 170rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
position: absolute;
|
||||||
|
right: 0%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #EA706A;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
transform: translateY(20%);
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
padding-right: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
74
pages/forgotPassword/forgotPassword.scss
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
.app {
|
||||||
|
height: calc(100vh - 44px);
|
||||||
|
padding: 20rpx 0;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
font-size: 34rpx;
|
||||||
|
margin: 0 auto 20rpx;
|
||||||
|
width: 94%;
|
||||||
|
height: 100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0px 9rpx 31rpx 9rpx rgba(0, 0, 0, 0.03);
|
||||||
|
border-radius: 20rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.lefttext {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
left: 3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.righttext {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
left: 18%;
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lefttext,
|
||||||
|
.righttext {
|
||||||
|
::v-deep .uni-input-input {
|
||||||
|
font-size: 34rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .uni-input-wrapper {
|
||||||
|
height: 100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .uni-input-placeholder {
|
||||||
|
line-height: 100rpx;
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #C3C1C1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.obtaincode {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #4C7BC9;
|
||||||
|
line-height: 100rpx;
|
||||||
|
position: absolute;
|
||||||
|
right: 5%;
|
||||||
|
top: 0%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginbtn {
|
||||||
|
width: 80%;
|
||||||
|
height: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100rpx;
|
||||||
|
background: #4C7BC9;
|
||||||
|
border-radius: 51rpx;
|
||||||
|
font-size: 41rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
position: absolute;
|
||||||
|
top: 60%;
|
||||||
|
left: 10%;
|
||||||
|
}
|
||||||
|
}
|
||||||
158
pages/forgotPassword/forgotPassword.vue
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<template>
|
||||||
|
<view class="app">
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
姓名
|
||||||
|
</view>
|
||||||
|
<u-input class="righttext" style='left:23%' type="text" placeholder="请输入" maxlength="11"
|
||||||
|
v-model="phonenumber" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
身份证号
|
||||||
|
</view>
|
||||||
|
<u-input class="righttext" style='left:30%' type="text" placeholder="请输入" maxlength="11"
|
||||||
|
v-model="phonenumber" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
手机号
|
||||||
|
</view>
|
||||||
|
<u-input class="righttext" style='left:23%' type="text" placeholder="请输入" maxlength="11"
|
||||||
|
v-model="phonenumber" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
输入新密码
|
||||||
|
</view>
|
||||||
|
<u-input class='righttext' style='left:30%' placeholder="请输入密码" maxlength="10" type="password"
|
||||||
|
:border="false" :password-icon="true" v-model="newpassword" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
重复新密码
|
||||||
|
</view>
|
||||||
|
<u-input class='righttext' style='left:30%' placeholder="请再次输入密码" maxlength="10" type="password"
|
||||||
|
:border="false" :password-icon="true" v-model="password" />
|
||||||
|
</view>
|
||||||
|
<!-- <view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
验证码
|
||||||
|
</view>
|
||||||
|
<input class="righttext" style='left:23%' type="text" placeholder="" maxlength="6" v-model="verification" />
|
||||||
|
<view class="obtaincode" :style="{'color':getCodeBtnColor}" @click.stop="getCode()">
|
||||||
|
{{getCodeText}}
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
<view class="loginbtn" @tap='pwdlogin'>
|
||||||
|
确定
|
||||||
|
</view>
|
||||||
|
<u-toast ref="uToast" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
// import {
|
||||||
|
// updatePassword
|
||||||
|
// } from '@/api/forgotPassword/forgotPassword.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
phonenumber: '',
|
||||||
|
password: '',
|
||||||
|
newpassword: '',
|
||||||
|
getCodeText: '获取验证码', //获取验证码的文字
|
||||||
|
getCodeBtnColor: "#4C7BC9", //获取验证码的color
|
||||||
|
timer: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(options) {
|
||||||
|
if (options.phonenumber) {
|
||||||
|
this.phonenumber = options.phonenumber
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
pwdlogin() {
|
||||||
|
var that = this
|
||||||
|
if (this.password !== this.newpassword) {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: '密码输入不一致,请重新输入',
|
||||||
|
type: 'error',
|
||||||
|
duration: '1500'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
updatePassword(this.phonenumber, this.password, this.verification).then(res => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: '密码修改成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: '1500'
|
||||||
|
})
|
||||||
|
if (that.timer) {
|
||||||
|
clearTimeout(that.timer)
|
||||||
|
}
|
||||||
|
that.timer = setTimeout(e => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/login/login?phonenumber=${this.phonenumber}&password=${this.password}`
|
||||||
|
})
|
||||||
|
}, 1500)
|
||||||
|
} else {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: res.msg,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//点击获取验证码
|
||||||
|
getCode() {
|
||||||
|
uni.hideKeyboard() //隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作。
|
||||||
|
if (this.getCodeisWaiting) { //是否在倒计时中
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(this.phonenumber))) { //校验手机号码是否有误
|
||||||
|
uni.showToast({
|
||||||
|
title: '请填写正确手机号码',
|
||||||
|
icon: "none"
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.getCodeText = "发送中..." //发送验证码
|
||||||
|
this.getCodeisWaiting = true;
|
||||||
|
this.getCodeBtnColor = "rgba(138,139,133,1)" //追加样式,修改颜色
|
||||||
|
//示例用定时器模拟请求效果
|
||||||
|
//setTimeout(()用于在指定的毫秒数后调用函数或计算表达式
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '验证码已发送',
|
||||||
|
icon: "none"
|
||||||
|
}); //弹出提示框
|
||||||
|
// this.code = '1234'; //发送验证码,进行填入 示例默认1234,生产中请删除这一句。
|
||||||
|
this.setTimer(); //调用定时器方法
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
//获取验证码的倒计时 setTimer: 需要每隔一段时间执行一件事的的时候就需要使用SetTimer函数
|
||||||
|
setTimer() {
|
||||||
|
let holdTime = 60; //定义变量并赋值
|
||||||
|
this.getCodeText = "重新获取(60)"
|
||||||
|
//setInterval()是一个实现定时调用的函数,可按照指定的周期(以毫秒计)来调用函数或计算表达式。
|
||||||
|
//setInterval方法会不停地调用函数,直到 clearInterval被调用或窗口被关闭。
|
||||||
|
this.Timer = setInterval(() => {
|
||||||
|
if (holdTime <= 0) {
|
||||||
|
this.getCodeisWaiting = false;
|
||||||
|
this.getCodeBtnColor = "#4C7BC9";
|
||||||
|
this.getCodeText = "获取验证码"
|
||||||
|
clearInterval(this.Timer); //清除该函数
|
||||||
|
return; //返回前面
|
||||||
|
}
|
||||||
|
this.getCodeText = "重新获取(" + holdTime + ")"
|
||||||
|
holdTime--;
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "./forgotPassword.scss";
|
||||||
|
</style>
|
||||||
89
pages/login/login.scss
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
.app {
|
||||||
|
font-family: DengXian;
|
||||||
|
color: #C3C1C1;
|
||||||
|
font-weight: 400;
|
||||||
|
height:calc(100vh - 44px);
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
text-align: center;
|
||||||
|
height: 100rpx;
|
||||||
|
color: #46ABD7;
|
||||||
|
position: absolute;
|
||||||
|
top: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginbtn {
|
||||||
|
width: 80%;
|
||||||
|
height: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100rpx;
|
||||||
|
background: #4C7BC9;
|
||||||
|
border-radius: 51rpx;
|
||||||
|
font-size: 41rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
position: absolute;
|
||||||
|
top: 57%;
|
||||||
|
left: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginphone {
|
||||||
|
background-color: #fff;
|
||||||
|
width: 80%;
|
||||||
|
height: 120rpx;
|
||||||
|
position: absolute;
|
||||||
|
left: 10%;
|
||||||
|
top: 23%;
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-size: 45rpx;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .uni-input-placeholder {
|
||||||
|
padding-left: 40rpx;
|
||||||
|
font-size: 41rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #C3C1C1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone {
|
||||||
|
padding-left: 40rpx;
|
||||||
|
height: 100%;
|
||||||
|
box-shadow: 0px 9px 31px 9px rgba(0, 0, 0, 0.03);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logincode {
|
||||||
|
position: absolute;
|
||||||
|
left: 10%;
|
||||||
|
|
||||||
|
.obtaincode {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 37rpx;
|
||||||
|
color: #4C7BC9;
|
||||||
|
line-height: 162rpx;
|
||||||
|
position: absolute;
|
||||||
|
left: 65%;
|
||||||
|
top: 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .u-input__input {
|
||||||
|
padding-left: 20rpx;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 42rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
height: 50rpx;
|
||||||
|
font-size: 52rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #000000;
|
||||||
|
line-height: 44rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 13%;
|
||||||
|
left: 13%;
|
||||||
|
}
|
||||||
|
}
|
||||||
116
pages/login/login.vue
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<view class="app">
|
||||||
|
<view class="title">
|
||||||
|
账号登录
|
||||||
|
</view>
|
||||||
|
<view class="loginphone logincode">
|
||||||
|
<u-input class="code phone" type="text" placeholder="身份证号" maxlength="18" v-model="phone" />
|
||||||
|
</view>
|
||||||
|
<view class="logincode loginphone" style="top: 40%;">
|
||||||
|
<u-input class='code phone' placeholder="密码" maxlength="20" v-model="password" type="password"
|
||||||
|
:password-icon="true" />
|
||||||
|
</view>
|
||||||
|
<view class="loginbtn" @tap='pwdlogin'>
|
||||||
|
登录
|
||||||
|
</view>
|
||||||
|
<!-- <view class="switch" @tap='goforgotPassword' style="left:10%">
|
||||||
|
忘记密码
|
||||||
|
</view> -->
|
||||||
|
<view class="switch" @tap='goregister' style="right:10%">
|
||||||
|
没有账号,请先注册
|
||||||
|
</view>
|
||||||
|
<u-toast ref="uToast" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
info
|
||||||
|
} from '@/api/user/index.js'
|
||||||
|
import {
|
||||||
|
login
|
||||||
|
} from '../../api/login/index.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
phone: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
//获取到传值
|
||||||
|
onLoad(options) {
|
||||||
|
if (options.phone && options.password) {
|
||||||
|
this.phone = options.phone
|
||||||
|
this.password = options.password
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
if (uni.getStorageSync('examh5token')) {
|
||||||
|
uni.switchTab({
|
||||||
|
url: "/pages/examlist/examlist"
|
||||||
|
})
|
||||||
|
// info({
|
||||||
|
// token: uni.getStorageSync('examh5token')
|
||||||
|
// }).then(res => {
|
||||||
|
// if (res.code == 0) {
|
||||||
|
// uni.setStorageSync("examh5token", res.data.token)
|
||||||
|
// uni.setStorageSync("examh5user", {
|
||||||
|
// id: res.data.id,
|
||||||
|
// phone: res.data.phone,
|
||||||
|
// name: res.data.realName,
|
||||||
|
// cardNo: res.data.userName
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
pwdlogin() {
|
||||||
|
login({
|
||||||
|
username: this.phone,
|
||||||
|
password: this.password
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
uni.setStorageSync("examh5token", res.data.token)
|
||||||
|
uni.setStorageSync("examh5user", {
|
||||||
|
id: res.data.id,
|
||||||
|
phone: res.data.phone,
|
||||||
|
name: res.data.realName,
|
||||||
|
cardNo: res.data.userName
|
||||||
|
})
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: "登录成功!",
|
||||||
|
type: 'success',
|
||||||
|
duration: '1500'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/examlist/examlist',
|
||||||
|
})
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: res.msg,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//跳转注册页
|
||||||
|
goregister() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/register/register'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//跳转忘记密码页面
|
||||||
|
goforgotPassword() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/forgotPassword/forgotPassword?phone=${this.phone}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "./login.scss";
|
||||||
|
</style>
|
||||||
162
pages/register/register.scss
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
.app {
|
||||||
|
height:calc(100vh - 44px);
|
||||||
|
padding:20rpx 0;
|
||||||
|
|
||||||
|
.Agreement{
|
||||||
|
width: 100%;
|
||||||
|
background-color: #F4F5F7;
|
||||||
|
text-align: center;
|
||||||
|
height: 1000rpx;
|
||||||
|
position: absolute;
|
||||||
|
top:5%;
|
||||||
|
font-size: 30rpx;
|
||||||
|
.title{
|
||||||
|
height: 100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
border-bottom: 1px solid #eeeeee;
|
||||||
|
font-size: 34rpx;
|
||||||
|
margin: 0px auto;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.scroll-Y{
|
||||||
|
height:830rpx ;
|
||||||
|
overflow-y:scroll;
|
||||||
|
text-align: left;
|
||||||
|
text-indent: 2em;
|
||||||
|
}
|
||||||
|
.cancel {
|
||||||
|
height:70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
background-color: #F4F5F7;
|
||||||
|
position: absolute;
|
||||||
|
border-top: 1rpx solid #000000;
|
||||||
|
bottom:0;
|
||||||
|
right:0;
|
||||||
|
width: 50%;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
.determine {
|
||||||
|
height:70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
width: 50%;
|
||||||
|
color: #F4F5F7;
|
||||||
|
background: #4C7BC9;
|
||||||
|
position: absolute;
|
||||||
|
bottom:0;
|
||||||
|
left:0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item{
|
||||||
|
font-size: 34rpx;
|
||||||
|
margin: 0 auto 20rpx;
|
||||||
|
width: 94%;
|
||||||
|
height:100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0px 9rpx 31rpx 9rpx rgba(0,0,0,0.03);
|
||||||
|
border-radius: 20rpx;
|
||||||
|
position: relative;
|
||||||
|
.lefttext{
|
||||||
|
position: absolute;
|
||||||
|
top:50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
left:3%;
|
||||||
|
}
|
||||||
|
.righttext{
|
||||||
|
position: absolute;
|
||||||
|
top:50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 68%;
|
||||||
|
left:18%;
|
||||||
|
height:100rpx;
|
||||||
|
}
|
||||||
|
.lefttext,.righttext{
|
||||||
|
::v-deep .uni-input-input{
|
||||||
|
font-size: 34rpx;
|
||||||
|
}
|
||||||
|
::v-deep .uni-input-wrapper{
|
||||||
|
height:100rpx;
|
||||||
|
line-height: 100rpx;
|
||||||
|
}
|
||||||
|
::v-deep .uni-input-placeholder {
|
||||||
|
line-height: 100rpx;
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #C3C1C1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.obtaincode {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #4C7BC9;
|
||||||
|
line-height: 100rpx;
|
||||||
|
position: absolute;
|
||||||
|
right:5%;
|
||||||
|
top: 0%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.radio-content {
|
||||||
|
margin: 50rpx auto;
|
||||||
|
width: 70%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
position: relative;
|
||||||
|
.agreement {
|
||||||
|
position: absolute;
|
||||||
|
top:50%;
|
||||||
|
left:20%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #878987;
|
||||||
|
}
|
||||||
|
.radio-right {
|
||||||
|
height: 100rpx;
|
||||||
|
|
||||||
|
.radio {
|
||||||
|
display: inline-block;
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
border-radius: 70%;
|
||||||
|
border: 2rpx solid #178ffb;
|
||||||
|
position: absolute;
|
||||||
|
top:50%;
|
||||||
|
left:5%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
.radio-active {
|
||||||
|
width: 16rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #178ffb;
|
||||||
|
position: absolute;
|
||||||
|
top:50%;
|
||||||
|
left:50%;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.switch {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 60rpx;
|
||||||
|
color: #46ABD7;
|
||||||
|
position: absolute;
|
||||||
|
top: 73%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginbtn {
|
||||||
|
width: 70%;
|
||||||
|
height: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100rpx;
|
||||||
|
background: #4C7BC9;
|
||||||
|
border-radius: 51rpx;
|
||||||
|
font-size: 41rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
position: absolute;
|
||||||
|
top: 62%;
|
||||||
|
left: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
247
pages/register/register.vue
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
<template>
|
||||||
|
<view class="app">
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
姓名
|
||||||
|
</view>
|
||||||
|
<u-input class="righttext" style="width: 80%;" type="text" placeholder="请输入" maxlength="10"
|
||||||
|
v-model="realName" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
身份证号
|
||||||
|
</view>
|
||||||
|
<u-input class="righttext" style='left:30%' type="text" placeholder="请输入" maxlength="18"
|
||||||
|
v-model="patientName" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
手机号
|
||||||
|
</view>
|
||||||
|
<u-input class="righttext" style='left:23%;width: 77%;' type="text" placeholder="请输入" maxlength="11"
|
||||||
|
v-model="phone" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
输入密码
|
||||||
|
</view>
|
||||||
|
<u-input class='righttext' style='left:30%' placeholder="请输入密码" maxlength="20" v-model="password"
|
||||||
|
type="password" :border="false" :password-icon="true" />
|
||||||
|
</view>
|
||||||
|
<view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
重复密码
|
||||||
|
</view>
|
||||||
|
<u-input class='righttext' style='left:30%' placeholder="请再次输入密码" maxlength="20" v-model="newpassword"
|
||||||
|
type="password" :border="false" :password-icon="true" />
|
||||||
|
</view>
|
||||||
|
<!-- <view class="item">
|
||||||
|
<view class="lefttext">
|
||||||
|
验证码
|
||||||
|
</view>
|
||||||
|
<input class="righttext" style='left:23%' type="text" placeholder="" maxlength="6" v-model="verification" />
|
||||||
|
<view class="obtaincode" :style="{'color':getCodeBtnColor}" @click.stop="getCode()">
|
||||||
|
{{getCodeText}}
|
||||||
|
</view>
|
||||||
|
</view> -->
|
||||||
|
<view class="loginbtn" @tap='register'>
|
||||||
|
注册
|
||||||
|
</view>
|
||||||
|
<view class="switch" style="right:5%" @tap='gologin'>
|
||||||
|
已有账号,去登录
|
||||||
|
</view>
|
||||||
|
<u-toast ref="uToast" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
reg
|
||||||
|
} from '@/api/register/index.js'
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
patientName: '',
|
||||||
|
realName: "",
|
||||||
|
phone: '',
|
||||||
|
password: '',
|
||||||
|
newpassword: '',
|
||||||
|
verification: '',
|
||||||
|
getCodeText: '获取验证码', //获取验证码的文字
|
||||||
|
getCodeBtnColor: "#4C7BC9", //获取验证码的color
|
||||||
|
getCodeisWaiting: false, //判断是否在倒计时中
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//注册功能
|
||||||
|
register() {
|
||||||
|
if (this.password !== this.newpassword) {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: '密码输入不一致,请重新输入',
|
||||||
|
type: 'error',
|
||||||
|
duration: '1500'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
reg({
|
||||||
|
password: this.password,
|
||||||
|
realName: this.realName,
|
||||||
|
userName: this.patientName,
|
||||||
|
phone: this.phone
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
uni.setStorageSync("examh5token", res.data.token)
|
||||||
|
uni.setStorageSync("examh5user", {
|
||||||
|
id: res.data.id,
|
||||||
|
phone: res.data.phone,
|
||||||
|
name: res.data.realName,
|
||||||
|
cardNo: res.data.userName
|
||||||
|
})
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: '注册成功,前往登录',
|
||||||
|
type: 'success',
|
||||||
|
duration: '1500'
|
||||||
|
})
|
||||||
|
setTimeout(e => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: `/pages/login/login?phone=${this.patientName}&password=${this.password}`
|
||||||
|
})
|
||||||
|
}, 1500)
|
||||||
|
} else {
|
||||||
|
this.$refs.uToast.show({
|
||||||
|
title: res.msg,
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//跳转登录页
|
||||||
|
gologin() {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: `/pages/login/login`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//点击获取验证码
|
||||||
|
getCode() {
|
||||||
|
uni.hideKeyboard() //隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作。
|
||||||
|
if (this.getCodeisWaiting) { //是否在倒计时中
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(this.phone))) { //校验手机号码是否有误
|
||||||
|
uni.showToast({
|
||||||
|
title: '请填写正确手机号码',
|
||||||
|
icon: "none"
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.getCodeText = "发送中..." //发送验证码
|
||||||
|
this.getCodeisWaiting = true;
|
||||||
|
this.getCodeBtnColor = "rgba(138,139,133,1)" //追加样式,修改颜色
|
||||||
|
//示例用定时器模拟请求效果
|
||||||
|
//setTimeout(()用于在指定的毫秒数后调用函数或计算表达式
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '验证码已发送',
|
||||||
|
icon: "none"
|
||||||
|
}); //弹出提示框
|
||||||
|
// this.code = '1234'; //发送验证码,进行填入 示例默认1234,生产中请删除这一句。
|
||||||
|
this.setTimer(); //调用定时器方法
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
//获取验证码的倒计时 setTimer: 需要每隔一段时间执行一件事的的时候就需要使用SetTimer函数
|
||||||
|
setTimer() {
|
||||||
|
let holdTime = 60; //定义变量并赋值
|
||||||
|
this.getCodeText = "重新获取(60)"
|
||||||
|
//setInterval()是一个实现定时调用的函数,可按照指定的周期(以毫秒计)来调用函数或计算表达式。
|
||||||
|
//setInterval方法会不停地调用函数,直到 clearInterval被调用或窗口被关闭。
|
||||||
|
this.Timer = setInterval(() => {
|
||||||
|
if (holdTime <= 0) {
|
||||||
|
this.getCodeisWaiting = false;
|
||||||
|
this.getCodeBtnColor = "#4C7BC9";
|
||||||
|
this.getCodeText = "获取验证码"
|
||||||
|
clearInterval(this.Timer); //清除该函数
|
||||||
|
return; //返回前面
|
||||||
|
}
|
||||||
|
this.getCodeText = "重新获取(" + holdTime + ")"
|
||||||
|
holdTime--;
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
doReg() {
|
||||||
|
// uni.hideKeyboard() //隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作。
|
||||||
|
// //模板示例部分验证规则
|
||||||
|
// if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(this.phoneNumber))) { //校验手机号码
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '请填写正确手机号码',
|
||||||
|
// icon: "none"
|
||||||
|
// });
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// //示例验证码,实际使用中应为请求服务器比对验证码是否正确。
|
||||||
|
// if (this.code != 1234) {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '验证码不正确',
|
||||||
|
// icon: "none"
|
||||||
|
// });
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// uni.showLoading({
|
||||||
|
// title: '提交中...'
|
||||||
|
// })
|
||||||
|
// //模板示例把用户注册信息储存在本地,实际使用中请替换为上传服务器。
|
||||||
|
// setTimeout(() => {
|
||||||
|
// uni.getStorage({
|
||||||
|
// key: 'UserList',
|
||||||
|
// success: (res) => {
|
||||||
|
// //增加记录,密码md5
|
||||||
|
// res.data.push({
|
||||||
|
// username: this.phoneNumber,
|
||||||
|
// passwd: md5(this.passwd)
|
||||||
|
// })
|
||||||
|
// uni.setStorage({
|
||||||
|
// key: 'UserList',
|
||||||
|
// data: res.data,
|
||||||
|
// success: function() {
|
||||||
|
// uni.hideLoading()
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '注册成功',
|
||||||
|
// icon: "success"
|
||||||
|
// });
|
||||||
|
// setTimeout(function() {
|
||||||
|
// uni.navigateBack();
|
||||||
|
// }, 1000)
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// fail: (e) => {
|
||||||
|
// uni.hideLoading()
|
||||||
|
// //新建UserList
|
||||||
|
// uni.setStorage({
|
||||||
|
// key: 'UserList',
|
||||||
|
// data: [{
|
||||||
|
// username: this.phoneNumber,
|
||||||
|
// passwd: md5(this.passwd)
|
||||||
|
// }],
|
||||||
|
// success: function() {
|
||||||
|
// uni.hideLoading()
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '注册成功',
|
||||||
|
// icon: "success"
|
||||||
|
// });
|
||||||
|
// setTimeout(function() {
|
||||||
|
// uni.navigateBack();
|
||||||
|
// }, 1000)
|
||||||
|
// },
|
||||||
|
// fail: function(e) {
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }, 1000)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "./register.scss";
|
||||||
|
</style>
|
||||||
240
pages/user/user.vue
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
<template>
|
||||||
|
<view class="app">
|
||||||
|
<image class="circular" src="../../static/homepage.png" mode=""></image>
|
||||||
|
<view class="user" v-if="Personallist">
|
||||||
|
<image class="img" src="../../static/user2.png" mode=""></image>
|
||||||
|
<view class="phone" v-if="Personallist.realName">
|
||||||
|
{{Personallist.realName}}
|
||||||
|
</view>
|
||||||
|
<view class="nickname" v-if="Personallist.userName">
|
||||||
|
{{Personallist.userName}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="user" v-else>
|
||||||
|
<image class="img" src="../../static/user2.png" mode=""></image>
|
||||||
|
<view class="login" @tap='gologin'>
|
||||||
|
登录
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="bottomitems">
|
||||||
|
<view class="bottomitem" @tap='goremove'>
|
||||||
|
<image src="../../static/shezhi.png" mode=""></image>
|
||||||
|
<view class="">
|
||||||
|
退出账号
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<u-toast ref="uToast" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
info
|
||||||
|
} from '@/api/user/index.js'
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
Personallist: undefined,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
if (uni.getStorageSync('examh5token')) {
|
||||||
|
this.myInfo()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
myInfo() {
|
||||||
|
info({
|
||||||
|
token: uni.getStorageSync('examh5token')
|
||||||
|
}).then(res => {
|
||||||
|
if (res.code == 0) {
|
||||||
|
uni.setStorageSync("examh5token", res.data.token)
|
||||||
|
uni.setStorageSync("examh5user", {
|
||||||
|
id: res.data.id,
|
||||||
|
phone: res.data.phone,
|
||||||
|
name: res.data.realName,
|
||||||
|
cardNo: res.data.userName
|
||||||
|
})
|
||||||
|
this.Personallist = res.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//跳登录
|
||||||
|
gologin() {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//退出账号
|
||||||
|
goremove() {
|
||||||
|
let that = this
|
||||||
|
const value = uni.getStorageSync('examh5token');
|
||||||
|
if (value) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '确认要退出此账号吗',
|
||||||
|
success: function(res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
uni.clearStorageSync();
|
||||||
|
that.Personallist = undefined
|
||||||
|
that.$refs.uToast.show({
|
||||||
|
title: '退出账号成功!',
|
||||||
|
type: 'success',
|
||||||
|
duration: '1000'
|
||||||
|
})
|
||||||
|
if (that.timer) {
|
||||||
|
clearTimeout(that.timer)
|
||||||
|
}
|
||||||
|
that.timer = setTimeout(e => {
|
||||||
|
that.gologin();
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
that.$refs.uToast.show({
|
||||||
|
title: '您未登录',
|
||||||
|
type: 'error',
|
||||||
|
duration: '1000'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
padding: 0;
|
||||||
|
font-size: 32rpx;
|
||||||
|
height: calc(100vh - 100rpx);
|
||||||
|
|
||||||
|
.bottomitems {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 50rpx;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.bottomitem {
|
||||||
|
width: 85%;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 120rpx;
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1rpx solid #F3F3F3;
|
||||||
|
|
||||||
|
view {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 35rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 120rpx;
|
||||||
|
margin-left: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
display: inline-block;
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.topitems {
|
||||||
|
z-index: 999;
|
||||||
|
padding: 45rpx 0 35rpx;
|
||||||
|
width: 94%;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0rpx 3rpx 18rpx 0rpx rgba(79, 108, 254, 0.43);
|
||||||
|
border-radius: 5rpx;
|
||||||
|
justify-content: space-around;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.topitem {
|
||||||
|
view {
|
||||||
|
font-size: 32rpx;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 90rpx;
|
||||||
|
height: 90rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user {
|
||||||
|
width: 100%;
|
||||||
|
height: 500rpx;
|
||||||
|
position: relative;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 38rpx;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
.modify {
|
||||||
|
position: absolute;
|
||||||
|
right: 3%;
|
||||||
|
top: 250rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 23rpx;
|
||||||
|
height: 23rpx;
|
||||||
|
padding-left: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login {
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 220rpx;
|
||||||
|
left: 35%;
|
||||||
|
font-size: 36rpx;
|
||||||
|
width: 180rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
border: 1rpx solid #fff;
|
||||||
|
height: 70rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nickname {
|
||||||
|
position: absolute;
|
||||||
|
top: 260rpx;
|
||||||
|
left: 35%;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone {
|
||||||
|
position: absolute;
|
||||||
|
top: 180rpx;
|
||||||
|
left: 35%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #F6F6F6;
|
||||||
|
position: absolute;
|
||||||
|
top: 170rpx;
|
||||||
|
left: 8%;
|
||||||
|
// border: 4rpx solid #6DD8FC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.circular {
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 500rpx;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
static/autograph.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
static/homepage.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
static/homepagew.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
static/homepagews.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
static/jinbi.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
static/shezhi.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
static/user2.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
static/users.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
static/userw.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
13
uni.promisify.adaptor.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
uni.addInterceptor({
|
||||||
|
returnValue (res) {
|
||||||
|
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
res.then((res) => {
|
||||||
|
if (!res) return resolve(res)
|
||||||
|
return res[0] ? reject(res[0]) : resolve(res[1])
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
77
uni.scss
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* 这里是uni-app内置的常用样式变量
|
||||||
|
*
|
||||||
|
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||||
|
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||||
|
*
|
||||||
|
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||||
|
*/
|
||||||
|
/* uni.scss */
|
||||||
|
@import 'uview-ui/theme.scss';
|
||||||
|
/* 颜色变量 */
|
||||||
|
|
||||||
|
/* 行为相关颜色 */
|
||||||
|
$uni-color-primary: #007aff;
|
||||||
|
$uni-color-success: #4cd964;
|
||||||
|
$uni-color-warning: #f0ad4e;
|
||||||
|
$uni-color-error: #dd524d;
|
||||||
|
|
||||||
|
/* 文字基本颜色 */
|
||||||
|
$uni-text-color:#333;//基本色
|
||||||
|
$uni-text-color-inverse:#fff;//反色
|
||||||
|
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
|
||||||
|
$uni-text-color-placeholder: #808080;
|
||||||
|
$uni-text-color-disable:#c0c0c0;
|
||||||
|
|
||||||
|
/* 背景颜色 */
|
||||||
|
$uni-bg-color:#ffffff;
|
||||||
|
$uni-bg-color-grey:#f8f8f8;
|
||||||
|
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
|
||||||
|
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
|
||||||
|
|
||||||
|
/* 边框颜色 */
|
||||||
|
$uni-border-color:#c8c7cc;
|
||||||
|
|
||||||
|
/* 尺寸变量 */
|
||||||
|
|
||||||
|
/* 文字尺寸 */
|
||||||
|
$uni-font-size-sm:12px;
|
||||||
|
$uni-font-size-base:14px;
|
||||||
|
$uni-font-size-lg:16px;
|
||||||
|
|
||||||
|
/* 图片尺寸 */
|
||||||
|
$uni-img-size-sm:20px;
|
||||||
|
$uni-img-size-base:26px;
|
||||||
|
$uni-img-size-lg:40px;
|
||||||
|
|
||||||
|
/* Border Radius */
|
||||||
|
$uni-border-radius-sm: 2px;
|
||||||
|
$uni-border-radius-base: 3px;
|
||||||
|
$uni-border-radius-lg: 6px;
|
||||||
|
$uni-border-radius-circle: 50%;
|
||||||
|
|
||||||
|
/* 水平间距 */
|
||||||
|
$uni-spacing-row-sm: 5px;
|
||||||
|
$uni-spacing-row-base: 10px;
|
||||||
|
$uni-spacing-row-lg: 15px;
|
||||||
|
|
||||||
|
/* 垂直间距 */
|
||||||
|
$uni-spacing-col-sm: 4px;
|
||||||
|
$uni-spacing-col-base: 8px;
|
||||||
|
$uni-spacing-col-lg: 12px;
|
||||||
|
|
||||||
|
/* 透明度 */
|
||||||
|
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
|
||||||
|
|
||||||
|
/* 文章场景相关 */
|
||||||
|
$uni-color-title: #2C405A; // 文章标题颜色
|
||||||
|
$uni-font-size-title:20px;
|
||||||
|
$uni-color-subtitle: #555555; // 二级标题颜色
|
||||||
|
$uni-font-size-subtitle:26px;
|
||||||
|
$uni-color-paragraph: #3F536E; // 文章段落颜色
|
||||||
|
$uni-font-size-paragraph:15px;
|
||||||