first commit

main
zhangyanli 2026-04-17 16:26:28 +08:00
commit 74e2ef8999
106 changed files with 4570 additions and 0 deletions

24
api/index.js Normal file
View File

@ -0,0 +1,24 @@
import {post, upload} from "../utils/request";
export const login = (params) => post('/admin/check', params) //登录
export const setChangePassword = (params) => post('/app/user/editUserPwd', params) //修改密码
export const getExamListTaskByUser = (params) => post('/App/wx/getExamListTaskByUser', params) //应考试的班级列表
export const getPaperListByCidAndUser = (params) => post('/App/wx/getPaperListByCidAndUser', params) //班级学员试卷信息
export const submitExamByUser = (params) => post('/App/wx/submitExamByUser', params) //班级学员试卷信息
export const updateUserIdFile = (params) => upload('/App/wx/headPhoto', params) //上传头像
export const updStuStartTime = (params) => post('/App/wx/updStuStartTime', params) //考试前更新学员的学习时间
export const updStuSign = (params) => upload('/App/wx/updStuSign', params) //考试前更新学员的签字
export const updUserSign = (params) => upload('/App/wx/updUserSign', params) //考试前更新学员的签字
export const faceRecognition = (params) => upload('/App/wx/faceRecognition', params) //人脸识别
export const getHeadPhoto = (params) => post('/App/wx/getHeadPhoto', params) //获取基础信息
// 单次考试成绩
export const getExamRecordByUser = (params) => post('/App/wx/getExamRecordByUser', params)
// 所有考试记录
export const getExamRecordListByUser = (params) => post('/App/wx/getExamRecordListByUser', params)
// 所有调查问卷
export const getUserSurveyListPage = (params) => post('/App/wx/getUserSurveyListPage', params)
// 单个调查问卷
export const getUserSurveyInfo = (params) => post('/App/wx/getUserSurveyInfo', params)
// 提交调查问卷
export const surveySubmit = (params) => post('/App/wx/surveySubmit', params)

16
app.js Normal file
View File

@ -0,0 +1,16 @@
App({
onLaunch() {
if (!this.globalData.userInfo.USER_ID) {
wx.reLaunch({
url: 'pages/login/login'
})
} else {
wx.switchTab({
url: '/pages/index/index'
})
}
},
globalData: {
userInfo: {}, // 用户信息
}
})

46
app.json Normal file
View File

@ -0,0 +1,46 @@
{
"pages": [
"pages/login/login",
"pages/index/index",
"pages/exam/online/online",
"pages/exam/examination/examination",
"pages/exam/imitate/imitate",
"pages/exam/record/record",
"pages/exam/results/results",
"pages/photo/collection",
"pages/mine/index/index",
"pages/mine/aboutus/aboutus",
"pages/mine/survey/survey",
"pages/mine/survey/question",
"pages/mine/changePassword/changePassword",
"pages/sign/sign"
],
"usingComponents": {
"line": "/components/line/line"
},
"tabBar": {
"color": "#898993",
"selectedColor": "#3676f2",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/assets/images/tabbar/i1.png",
"selectedIconPath": "/assets/images/tabbar/i1_on.png"
},
{
"pagePath": "pages/mine/index/index",
"text": "我的",
"iconPath": "/assets/images/tabbar/i4.png",
"selectedIconPath": "/assets/images/tabbar/i4_on.png"
}
]
},
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#0189fa",
"navigationBarTitleText": "联安考",
"navigationBarTextStyle": "white"
},
"sitemapLocation": "sitemap.json"
}

7
app.wxss Normal file
View File

@ -0,0 +1,7 @@
@import "/assets/styles/common.wxss";
page{
background-color: #eee !important;
min-height: 100vh;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/images/fenlei.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
assets/images/mine/ico1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
assets/images/mine/ico2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
assets/images/mine/ico3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
assets/images/mine/ico5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/images/mine/mybg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
assets/images/photo/rx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
assets/images/tabbar/i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
assets/images/tabbar/i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

70
assets/styles/common.wxss Normal file
View File

@ -0,0 +1,70 @@
.line-1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.line-2 {
-webkit-line-clamp: 2;
}
.line-2,
.line-3 {
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
}
.line-3 {
-webkit-line-clamp: 3;
}
.placeholder {
height: 100rpx;
}
.text-blue {
color: #3676f2;
}
.text-red {
color: #cb4238;
}
.text-white {
color: #fff;
}
.text-grey {
color: #979799;
}
.text-green {
color: #23b576;
}
.text-yellow {
color: #ffae00;
}
.mt-10 {
margin-top: 20rpx;
}
.ml-10 {
margin-left: 20rpx;
}
.flex-end {
display: flex;
justify-content: flex-end;
}
.flex-space .van-cell {
justify-content: space-between;
}
.flex-space .van-cell__title, .flex-space .van-cell__value {
flex: unset !important;
}

23
components/line/line.js Normal file
View File

@ -0,0 +1,23 @@
// components/line/line.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -0,0 +1 @@
<view class="line"></view>

View File

@ -0,0 +1,4 @@
.line {
background-color: #f4f4f4;
height: 10rpx;
}

475
components/sign/sign.js Normal file
View File

@ -0,0 +1,475 @@
import Toast from '@vant/weapp/toast/toast';
Component({
/**
* 组件的属性列表
*/
properties: {
show: false
},
/**
* 组件的初始数据
*/
data: {
imgList: [],
//签名
canvasName: 'handWriting',
ctx: '',
canvasWidth: 0,
canvasHeight: 0,
transparent: 1, // 透明度
selectColor: '#fff',
lineColor: '#1A1A1A', // 颜色
lineSize: 1.5, // 笔记倍数
lineMin: 0.5, // 最小笔画半径
lineMax: 4, // 最大笔画半径
pressure: 1, // 默认压力
smoothness: 60, //顺滑度用60的距离来计算速度
currentPoint: {},
currentLine: [], // 当前线条
firstTouch: true, // 第一次触发
radius: 1, //画圆的半径
cutArea: {
top: 0,
right: 0,
bottom: 0,
left: 0
}, //裁剪区域
bethelPoint: [], //保存所有线条 生成的贝塞尔点;
lastPoint: 0,
chirography: [], //笔迹
currentChirography: {}, //当前笔迹
linePrack: [] //划线轨迹 , 生成线条的实际点
},
attached() {
let canvasName = this.data.canvasName
let ctx = wx.createCanvasContext(canvasName, this)
this.setData({
ctx: ctx
})
var query = this.createSelectorQuery();
query.select('.container').boundingClientRect(rect => {
this.setData({
canvasWidth: rect.width,
canvasHeight: rect.height
})
}).exec();
},
/**
* 组件的方法列表
*/
methods: {
ViewImage(e) {
let files = [];
files.push(e.currentTarget.dataset.url)
wx.previewImage({
urls: files,
current: e.currentTarget.dataset.url
});
},
// 笔迹开始
uploadScaleStart(e) {
if (e.type != 'touchstart') return false;
let ctx = this.data.ctx;
ctx.setFillStyle(this.data.lineColor); // 初始线条设置颜色
ctx.setGlobalAlpha(this.data.transparent); // 设置半透明
let currentPoint = {
x: e.touches[0].x,
y: e.touches[0].y
}
let currentLine = this.data.currentLine;
currentLine.unshift({
time: new Date().getTime(),
dis: 0,
x: currentPoint.x,
y: currentPoint.y
})
this.setData({
currentPoint,
// currentLine
})
if (this.data.firstTouch) {
this.setData({
cutArea: {
top: currentPoint.y,
right: currentPoint.x,
bottom: currentPoint.y,
left: currentPoint.x
},
firstTouch: false
})
}
this.pointToLine(currentLine);
},
// 笔迹移动
uploadScaleMove(e) {
if (e.type != 'touchmove') return false;
if (e.cancelable) {
// 判断默认行为是否已经被禁用
if (!e.defaultPrevented) {
e.preventDefault();
}
}
let point = {
x: e.touches[0].x,
y: e.touches[0].y
}
//测试裁剪
if (point.y < this.data.cutArea.top) {
this.data.cutArea.top = point.y;
}
if (point.y < 0) this.data.cutArea.top = 0;
if (point.x > this.data.cutArea.right) {
this.data.cutArea.right = point.x;
}
if (this.data.canvasWidth - point.x <= 0) {
this.data.cutArea.right = this.data.canvasWidth;
}
if (point.y > this.data.cutArea.bottom) {
this.data.cutArea.bottom = point.y;
}
if (this.data.canvasHeight - point.y <= 0) {
this.data.cutArea.bottom = this.data.canvasHeight;
}
if (point.x < this.data.cutArea.left) {
this.data.cutArea.left = point.x;
}
if (point.x < 0) this.data.cutArea.left = 0;
this.setData({
lastPoint: this.data.currentPoint,
currentPoint: point
})
let currentLine = this.data.currentLine
currentLine.unshift({
time: new Date().getTime(),
dis: this.distance(this.data.currentPoint, this.data.lastPoint),
x: point.x,
y: point.y
})
// this.setData({
// currentLine
// })
this.pointToLine(currentLine);
},
// 笔迹结束
uploadScaleEnd(e) {
if (e.type != 'touchend') return 0;
let point = {
x: e.changedTouches[0].x,
y: e.changedTouches[0].y
}
this.setData({
lastPoint: this.data.currentPoint,
currentPoint: point
})
let currentLine = this.data.currentLine
currentLine.unshift({
time: new Date().getTime(),
dis: this.distance(this.data.currentPoint, this.data.lastPoint),
x: point.x,
y: point.y
})
// this.setData({
// currentLine
// })
if (currentLine.length > 2) {
var info = (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;
//$("#info").text(info.toFixed(2));
}
//一笔结束,保存笔迹的坐标点,清空,当前笔迹
//增加判断是否在手写区域;
this.pointToLine(currentLine);
var currentChirography = {
lineSize: this.data.lineSize,
lineColor: this.data.lineColor
};
var chirography = this.data.chirography
chirography.unshift(currentChirography);
this.setData({
chirography
})
var linePrack = this.data.linePrack
linePrack.unshift(this.data.currentLine);
this.setData({
linePrack,
currentLine: []
})
},
retDraw() {
this.data.linePrack = []
this.data.chirography = []
this.data.ctx.clearRect(0, 0, 680, 300)
this.data.ctx.draw()
this.hideModal()
},
//画两点之间的线条;参数为:line会绘制最近的开始的两个点
pointToLine(line) {
this.calcBethelLine(line);
return;
},
//计算插值的方式;
calcBethelLine(line) {
if (line.length <= 1) {
line[0].r = this.data.radius;
return;
}
let x0, x1, x2, y0, y1, y2, r0, r1, r2, len, lastRadius, dis = 0,
time = 0,
curveValue = 0.5;
if (line.length <= 2) {
x0 = line[1].x
y0 = line[1].y
x2 = line[1].x + (line[0].x - line[1].x) * curveValue;
y2 = line[1].y + (line[0].y - line[1].y) * curveValue;
//x2 = line[1].x;
//y2 = line[1].y;
x1 = x0 + (x2 - x0) * curveValue;
y1 = y0 + (y2 - y0) * curveValue;;
} else {
x0 = line[2].x + (line[1].x - line[2].x) * curveValue;
y0 = line[2].y + (line[1].y - line[2].y) * curveValue;
x1 = line[1].x;
y1 = line[1].y;
x2 = x1 + (line[0].x - x1) * curveValue;
y2 = y1 + (line[0].y - y1) * curveValue;
}
//从计算公式看,三个点分别是(x0,y0),(x1,y1),(x2,y2) (x1,y1)这个是控制点,控制点不会落在曲线上;实际上,这个点还会手写获取的实际点,却落在曲线上
len = this.distance({
x: x2,
y: y2
}, {
x: x0,
y: y0
});
lastRadius = this.data.radius;
for (let n = 0; n < line.length - 1; n++) {
dis += line[n].dis;
time += line[n].time - line[n + 1].time;
if (dis > this.data.smoothness) break;
}
this.setData({
radius: Math.min(time / len * this.data.pressure + this.data.lineMin, this.data.lineMax) * this.data.lineSize
});
line[0].r = this.data.radius;
//计算笔迹半径;
if (line.length <= 2) {
r0 = (lastRadius + this.data.radius) / 2;
r1 = r0;
r2 = r1;
//return;
} else {
r0 = (line[2].r + line[1].r) / 2;
r1 = line[1].r;
r2 = (line[1].r + line[0].r) / 2;
}
let n = 5;
let point = [];
for (let i = 0; i < n; i++) {
let t = i / (n - 1);
let x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2;
let y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2;
let r = lastRadius + (this.data.radius - lastRadius) / n * i;
point.push({
x: x,
y: y,
r: r
});
if (point.length == 3) {
let a = this.ctaCalc(point[0].x, point[0].y, point[0].r, point[1].x, point[1].y, point[1].r, point[2].x, point[2].y, point[2].r);
a[0].color = this.data.lineColor;
// let bethelPoint = this.data.bethelPoint;
// bethelPoint = bethelPoint.push(a);
this.bethelDraw(a, 1);
point = [{
x: x,
y: y,
r: r
}];
}
}
this.setData({
currentLine: line
})
},
//求两点之间距离
distance(a, b) {
let x = b.x - a.x;
let y = b.y - a.y;
return Math.sqrt(x * x + y * y);
},
ctaCalc(x0, y0, r0, x1, y1, r1, x2, y2, r2) {
let a = [],
vx01, vy01, norm, n_x0, n_y0, vx21, vy21, n_x2, n_y2;
vx01 = x1 - x0;
vy01 = y1 - y0;
norm = Math.sqrt(vx01 * vx01 + vy01 * vy01 + 0.0001) * 2;
vx01 = vx01 / norm * r0;
vy01 = vy01 / norm * r0;
n_x0 = vy01;
n_y0 = -vx01;
vx21 = x1 - x2;
vy21 = y1 - y2;
norm = Math.sqrt(vx21 * vx21 + vy21 * vy21 + 0.0001) * 2;
vx21 = vx21 / norm * r2;
vy21 = vy21 / norm * r2;
n_x2 = -vy21;
n_y2 = vx21;
a.push({
mx: x0 + n_x0,
my: y0 + n_y0,
color: "#1A1A1A"
});
a.push({
c1x: x1 + n_x0,
c1y: y1 + n_y0,
c2x: x1 + n_x2,
c2y: y1 + n_y2,
ex: x2 + n_x2,
ey: y2 + n_y2
});
a.push({
c1x: x2 + n_x2 - vx21,
c1y: y2 + n_y2 - vy21,
c2x: x2 - n_x2 - vx21,
c2y: y2 - n_y2 - vy21,
ex: x2 - n_x2,
ey: y2 - n_y2
});
a.push({
c1x: x1 - n_x2,
c1y: y1 - n_y2,
c2x: x1 - n_x0,
c2y: y1 - n_y0,
ex: x0 - n_x0,
ey: y0 - n_y0
});
a.push({
c1x: x0 - n_x0 - vx01,
c1y: y0 - n_y0 - vy01,
c2x: x0 + n_x0 - vx01,
c2y: y0 + n_y0 - vy01,
ex: x0 + n_x0,
ey: y0 + n_y0
});
a[0].mx = a[0].mx.toFixed(1);
a[0].mx = parseFloat(a[0].mx);
a[0].my = a[0].my.toFixed(1);
a[0].my = parseFloat(a[0].my);
for (let i = 1; i < a.length; i++) {
a[i].c1x = a[i].c1x.toFixed(1);
a[i].c1x = parseFloat(a[i].c1x);
a[i].c1y = a[i].c1y.toFixed(1);
a[i].c1y = parseFloat(a[i].c1y);
a[i].c2x = a[i].c2x.toFixed(1);
a[i].c2x = parseFloat(a[i].c2x);
a[i].c2y = a[i].c2y.toFixed(1);
a[i].c2y = parseFloat(a[i].c2y);
a[i].ex = a[i].ex.toFixed(1);
a[i].ex = parseFloat(a[i].ex);
a[i].ey = a[i].ey.toFixed(1);
a[i].ey = parseFloat(a[i].ey);
}
return a;
},
bethelDraw(point, is_fill, color) {
let ctx = this.data.ctx;
ctx.beginPath();
ctx.moveTo(point[0].mx, point[0].my);
if (undefined != color) {
ctx.setFillStyle(color);
ctx.setStrokeStyle(color);
} else {
ctx.setFillStyle(point[0].color);
ctx.setStrokeStyle(point[0].color);
}
for (let i = 1; i < point.length; i++) {
ctx.bezierCurveTo(point[i].c1x, point[i].c1y, point[i].c2x, point[i].c2y, point[i].ex, point[i].ey);
}
ctx.stroke();
if (undefined != is_fill) {
ctx.fill(); //填充图形 ( 后绘制的图形会覆盖前面的图形, 绘制时注意先后顺序 )
}
ctx.draw(true)
},
selectColorEvent(event) {
var color = event.currentTarget.dataset.colorValue;
var colorSelected = event.currentTarget.dataset.color;
this.setData({
selectColor: colorSelected,
lineColor: color
})
},
subCanvas() {
var _this = this;
// let ctx = this.data.ctx;
// ctx.fillStyle='#FFFFFF';
// ctx.fillRect(0, 0, 680, 300)
// this.data.ctx.draw(true, function () {
wx.canvasToTempFilePath({
canvasId: 'handWriting',
fileType: 'png',
quality: 1,
destWidth: this.data.canvasHeight,
destHeight: this.data.canvasWidth,
success(res) {
if (_this.data.linePrack.length == 0) {
Toast.loading({
type: 'fail',
message: '签名无效',
selector: '#van-toast',
zIndex: 99999999,
});
return
}
wx.getImageInfo({
src: res.tempFilePath,
success: (msg) => {
let height = msg.height / 2
let width = msg.width / 2
let canvas = wx.createCanvasContext('handWriting1', _this);
canvas.translate(height / 2, width / 2)
canvas.rotate(270 * Math.PI / 180)
canvas.drawImage(res.tempFilePath, -width / 2, -height / 2, width, height);
canvas.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'handWriting1',
fileType: 'png',
quality: 1,
destWidth: _this.data.canvasWidth,
destHeight: _this.data.canvasHeight,
success(vas) {
let imgList = _this.data.imgList;
imgList.splice(0, _this.data.imgList.length);
let img = {};
img.id = '';
img.filePath = vas.tempFilePath;
imgList.push(img)
_this.setData({
imgList: [...imgList]
})
_this.triggerEvent('subCanvas', imgList[0].filePath)
_this.retDraw();
}
}, _this)
})
}
})
}
}, _this);
// });
},
hideModal(e) {
this.triggerEvent('hideModal')
},
}
})

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"van-dialog": "@vant/weapp/dialog/index",
"van-button": "@vant/weapp/button/index",
"van-icon": "@vant/weapp/icon/index"
}
}

31
components/sign/sign.wxml Normal file
View File

@ -0,0 +1,31 @@
<van-dialog use-slot show="{{ show }}" show-confirm-button="{{false}}" custom-style="top:50% !important;" custom-class="sign_dialog">
<view class="content">
<view class="footer">
<view style="flex: 1;display: flex;">
<van-button custom-style="border: 0;border-radius: 0;border-top: 1px solid #ccc;height:100%;" bind:click="retDraw">
<view wx:for="{{'关闭/重签'}}" wx:key="index" class="title">{{item}}</view>
</van-button>
</view>
<view style="flex: 1;display: flex;">
<van-button type="info" custom-style="border: 0;border-radius: 0;flex: 1;border-top: 1px solid #ccc;height:100%;" bind:click="subCanvas">
<view wx:for="{{'完成'}}" wx:key="index" class="title">{{item}}</view>
</van-button>
</view>
</view>
<view class="container">
<canvas class="handWriting" disable-scroll="true" bindtouchstart="uploadScaleStart" bindtouchmove="uploadScaleMove" bindtouchend="uploadScaleEnd" canvas-id="handWriting">
</canvas>
<!-- 旋转图片canvas -->
<canvas canvas-id="handWriting1" style="width:2200rpx;height:870rpx;position:absolute;top:-2000%;"></canvas>
</view>
<view class="header">
<view></view>
<view>
<view wx:for="{{'签字'}}" wx:key="index" class="title">{{item}}</view>
</view>
<view>
<van-icon name="cross" bind:click="retDraw" />
</view>
</view>
</view>
</van-dialog>

52
components/sign/sign.wxss Normal file
View File

@ -0,0 +1,52 @@
.sign_dialog {
width: 100vw !important;
max-width: 100vw;
height: 100vh;
max-height: 100vh !important;
border-radius: 0 !important;
}
.content {
display: flex;
height: 100vh;
}
.header {
padding: 50rpx 0;
width: 80rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
text-align: center;
font-size: 40rpx;
color: #000;
}
.header .title {
margin-top: 10rpx;
transform: rotate(90deg);
}
.container {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.handWriting {
border: 1px dashed #ccc;
height: 98%;
width: auto;
flex: 1;
}
.footer {
display: flex;
flex-direction: column;
}
.footer .title {
transform: rotate(90deg);
}

24
package-lock.json generated Normal file
View File

@ -0,0 +1,24 @@
{
"name": "qa-education-exam-weapp",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"@vant/weapp": "^1.10.20"
}
},
"node_modules/@vant/weapp": {
"version": "1.10.20",
"resolved": "https://registry.npmjs.org/@vant/weapp/-/weapp-1.10.20.tgz",
"integrity": "sha512-smztfdwNhS9i8+QrEzD293LJCHy6q+WlDcy1dZCrfW09gf5dY5XGMHK3UsPJ+hNahZh0KPQ/jkN0NiXb5v+HjA=="
}
},
"dependencies": {
"@vant/weapp": {
"version": "1.10.20",
"resolved": "https://registry.npmjs.org/@vant/weapp/-/weapp-1.10.20.tgz",
"integrity": "sha512-smztfdwNhS9i8+QrEzD293LJCHy6q+WlDcy1dZCrfW09gf5dY5XGMHK3UsPJ+hNahZh0KPQ/jkN0NiXb5v+HjA=="
}
}
}

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"dependencies": {
"@vant/weapp": "^1.10.20"
}
}

View File

@ -0,0 +1,268 @@
// pages/exam/examination/examination.js
import debounce from '../../../utils/debounce'
import Dialog from '@vant/weapp/dialog/dialog'
import {
formatTime,
getNowDate
} from "../../../utils/util";
import {
getPaperListByCidAndUser,
submitExamByUser
} from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
EXAMNAME: '',
time: 0,
EXAMSCORE: '',
count: 0,
// 当前题数
current: 0,
CLASS_ID: '',
STUDENT_ID: '',
SIMULATION: '',
STAGEEXAMPAPERINPUT_ID: '',
timeData: {},
type: '',
current: 0,
topic: [],
testStartTime: formatTime(new Date()),
},
chooseTopic(e) {
const {
type,
check
} = e.currentTarget.dataset
let topic = this.data.topic
let current = this.data.current
if (type === 'judge' || type === 'radio') {
if (topic[current].CHECK === check) {
topic[current].CHECK = ''
} else {
topic[current].CHECK = check
}
this.setData({
topic: [...topic]
})
}
if (type === 'multiple') {
if (topic[current].CHECK) {
let checkedArr = topic[current].CHECK.split(',')
if (checkedArr.includes(check)) {
checkedArr.splice(checkedArr.indexOf(check), 1)
topic[current].CHECK = checkedArr.join(',')
} else {
checkedArr.push(check)
checkedArr.sort()
topic[current].CHECK = checkedArr.join(',')
}
} else {
topic[current].CHECK = check
}
this.setData({
topic: [...topic]
})
}
},
viewAnswers() {
let topic = this.data.topic
let current = this.data.current
topic[current].ANSWER = topic[current].CHECK || '没有作答'
this.setData({
topic: [...topic]
})
},
countDownChange(e) {
this.setData({
timeData: e.detail,
});
},
previousQuestion() {
this.setData({
current: --this.data.current
})
},
nextQuestion() {
this.setData({
current: ++this.data.current
})
},
async getData() {
let resData = {}
resData = await getPaperListByCidAndUser({
CLASS_ID: this.data.CLASS_ID,
SIMULATION: this.data.SIMULATION,
STUDENT_ID: this.data.STUDENT_ID,
STAGEEXAMPAPERINPUT_ID: this.data.STAGEEXAMPAPERINPUT_ID
})
for (let i = 0; i < resData.varList.length; i++) {
resData.varList[i].CHECK = ''
resData.varList[i].ANSWERRIGHT = resData.varList[i].ANSWER
resData.varList[i].ANSWER = ''
}
this.setData({
topic: resData.varList
})
},
submitPapers() {
Dialog.confirm({
title: '确定要交卷吗?',
selector: '#nation',
})
.then(() => {
debounce(async () => {
let varList = this.data.topic
for (let i = 0; i < varList.length; i++) {
varList[i].ANSWER = varList[i].CHECK
}
let resData = await submitExamByUser({
options: JSON.stringify(varList),
CLASS_ID: this.data.CLASS_ID,
STUDENT_ID: this.data.STUDENT_ID,
PASSSCORE: this.data.PASSSCORE,
EXAMSCORE: this.data.EXAMSCORE,
NUMBEROFEXAMS:this.data.NUMBEROFEXAMS,
EXAMTIMEBEGIN: this.data.EXAMTIMEBEGIN,
STAGEEXAMPAPERINPUT_ID: this.data.STAGEEXAMPAPERINPUT_ID
})
wx.showToast({
title: '交卷成功',
mask: true
})
setTimeout(() => {
wx.redirectTo({
url: '/pages/exam/results/results?STAGEEXAM_ID=' + resData.STAGEEXAM_ID +
'&EXAMRESULT=' + resData.examResult +
'&EXAMSCORE=' + resData.examScore +
'&PASSSCORE=' + resData.PASSSCORE +
'&PAPER_EXAMSCORE=' + resData.PAPER_EXAMSCORE,
})
}, 1500)
})
}).catch((e) =>{
})
},
fnCountDownFinish() {
Dialog.alert({
title: '考试时间到了',
selector: '#nation',
})
.then(() => {
debounce(async () => {
let varList = this.data.topic
for (let i = 0; i < varList.length; i++) {
varList[i].ANSWER = varList[i].CHECK
}
let resData = await submitExamByUser({
options: JSON.stringify(varList),
CLASS_ID: this.data.CLASS_ID,
STUDENT_ID: this.data.STUDENT_ID,
PASSSCORE: this.data.PASSSCORE,
EXAMSCORE: this.data.EXAMSCORE,
EXAMTIMEBEGIN: this.data.EXAMTIMEBEGIN,
STAGEEXAMPAPERINPUT_ID: this.data.STAGEEXAMPAPERINPUT_ID
})
wx.showToast({
title: '交卷成功',
mask: true
})
setTimeout(() => {
wx.redirectTo({
url: '/pages/exam/results/results?STAGEEXAM_ID=' + resData.STAGEEXAM_ID +
'&EXAMRESULT=' + resData.examResult +
'&EXAMSCORE=' + resData.examScore +
'&PASSSCORE=' + resData.PASSSCORE +
'&PAPER_EXAMSCORE=' + resData.PAPER_EXAMSCORE,
})
}, 1500)
})
});
},
/**
* 生命周期函数--监听页面加载
*/
onChange(event) {
let topic = this.data.topic
let current = this.data.current
topic[current].CHECK = event.detail
this.setData({
topic: [...topic]
})
},
onLoad(options) {
this.setData({
CLASS_ID: options.CLASS_ID,
SIMULATION: options.SIMULATION,
STAGEEXAMPAPERINPUT_ID: options.STAGEEXAMPAPERINPUT_ID,
EXAMNAME: options.EXAMNAME,
STUDENT_ID: options.STUDENT_ID,
PASSSCORE: options.PASSSCORE,
NUMBEROFEXAMS: options.NUMBEROFEXAMS,
EXAMSCORE: options.EXAMSCORE,
EXAMTIMEBEGIN: getNowDate(),
type: options.type,
time: options.ANSWERSHEETTIME * 60 * 1000
})
// 模拟考
if (this.data.SIMULATION == 1) {
this.setData({
time: 60 * 60 * 24 * 1000
})
}
this.getData()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

View File

@ -0,0 +1,13 @@
{
"usingComponents": {
"van-tag": "@vant/weapp/tag/index",
"van-image": "@vant/weapp/image/index",
"van-count-down": "@vant/weapp/count-down/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-icon": "@vant/weapp/icon/index",
"van-field": "@vant/weapp/field/index",
"van-sticky": "@vant/weapp/sticky/index",
"van-button": "@vant/weapp/button/index",
"van-empty": "@vant/weapp/empty/index"
}
}

View File

@ -0,0 +1,121 @@
<wxs module="tool" src="../../../utils/util.wxs"></wxs>
<view class="content">
<view class="top">
<view class="option" style="height:350rpx;">
<van-image width="700rpx" height="330rpx" src="/assets/images/exam/examination/bgimg1.png" />
<view class="head-text">
考试科目:{{ EXAMNAME }}
</view>
<view class="questions">
<view>当前试题{{ current+1 }}/{{ topic.length }}</view>
</view>
<view class="time" wx:if="{{ SIMULATION == 0 }}">
<view style="display: flex;font-size: 28rpx;">
剩余考试时间:
<van-count-down bind:finish="fnCountDownFinish" time="{{ time }}" format="HH时mm分ss秒" />
<!-- <van-count-down use-slot time="{{ time }}" bind:change="countDownChange">
<text class="text-white ml-10">剩余时间:</text>
<text class="text-white">{{ timeData.minutes }}:</text>
<text class="text-white">{{ timeData.seconds }}</text>
</van-count-down> -->
</view>
</view>
</view>
</view>
<view class="question-info">
<view class="container">
<van-tag type="primary" size="small">
<block wx:if="{{topic[current].QUESTIONTYPE === '1'}}">单选题</block>
<block wx:if="{{topic[current].QUESTIONTYPE === '2'}}">多选题</block>
<block wx:if="{{topic[current].QUESTIONTYPE === '3'}}">判断题</block>
<block wx:if="{{topic[current].QUESTIONTYPE === '4'}}">填空题</block>
</van-tag>
<text class="index">{{current + 1}}.</text>
<text class="stem">{{topic[current].QUESTIONDRY}}</text>
<view class="options" wx:if="{{topic[current].QUESTIONTYPE === '1'}}">
<view class="option" bind:tap="chooseTopic" data-type="radio" data-check="A">
<text class="choice {{topic[current].CHECK === 'A' ? 'check' : ''}} {{topic[current].ANSWER === 'A' ? (topic[current].ANSWERRIGHT === 'A' ? 'success' : 'error') : ''}}">A</text>
<text class="title">{{topic[current].OPTIONA}}</text>
</view>
<view class="option" bind:tap="chooseTopic" data-type="radio" data-check="B">
<text class="choice {{topic[current].CHECK === 'B' ? 'check' : ''}} {{topic[current].ANSWER === 'B' ? (topic[current].ANSWERRIGHT === 'B' ? 'success' : 'error') : ''}}">B</text>
<text class="title">{{topic[current].OPTIONB}}</text>
</view>
<view class="option" bind:tap="chooseTopic" data-type="radio" data-check="C">
<text class="choice {{topic[current].CHECK === 'C' ? 'check' : ''}} {{topic[current].ANSWER === 'C' ? (topic[current].ANSWERRIGHT === 'C' ? 'success' : 'error') : ''}}">C</text>
<text class="title">{{topic[current].OPTIONC}}</text>
</view>
<view class="option" bind:tap="chooseTopic" data-type="radio" data-check="D">
<text class="choice {{topic[current].CHECK === 'D' ? 'check' : ''}} {{topic[current].ANSWER === 'D' ? (topic[current].ANSWERRIGHT === 'D' ? 'success' : 'error') : ''}}">D</text>
<text class="title">{{topic[current].OPTIOND}}</text>
</view>
</view>
<view class="options" wx:if="{{topic[current].QUESTIONTYPE === '2'}}">
<view class="option" bind:tap="chooseTopic" data-type="multiple" data-check="A">
<text class="choice {{tool.indexOf(topic[current].CHECK,'A') !== -1 ? 'check' : ''}} {{tool.indexOf(topic[current].ANSWER,'A') !== -1 ? (tool.indexOf(topic[current].ANSWERRIGHT,'A') !== -1 ? 'success' : 'error') : ''}}">A</text>
<text class="title">{{topic[current].OPTIONA}}</text>
</view>
<view class="option" bind:tap="chooseTopic" data-type="multiple" data-check="B">
<text class="choice {{tool.indexOf(topic[current].CHECK,'B') !== -1 ? 'check' : ''}} {{tool.indexOf(topic[current].ANSWER,'B') !== -1 ? (tool.indexOf(topic[current].ANSWERRIGHT,'B') !== -1 ? 'success' : 'error') : ''}}">B</text>
<text class="title">{{topic[current].OPTIONB}}</text>
</view>
<view class="option" bind:tap="chooseTopic" data-type="multiple" data-check="C">
<text class="choice {{tool.indexOf(topic[current].CHECK,'C') !== -1 ? 'check' : ''}} {{tool.indexOf(topic[current].ANSWER,'C') !== -1 ? (tool.indexOf(topic[current].ANSWERRIGHT,'C') !== -1 ? 'success' : 'error') : ''}}">C</text>
<text class="title">{{topic[current].OPTIONC}}</text>
</view>
<view class="option" bind:tap="chooseTopic" data-type="multiple" data-check="D">
<text class="choice {{tool.indexOf(topic[current].CHECK,'D') !== -1 ? 'check' : ''}} {{tool.indexOf(topic[current].ANSWER,'D') !== -1 ? (tool.indexOf(topic[current].ANSWERRIGHT,'D') !== -1 ? 'success' : 'error') : ''}}">D</text>
<text class="title">{{topic[current].OPTIOND}}</text>
</view>
</view>
<view class="options" wx:if="{{topic[current].QUESTIONTYPE === '3'}}">
<view class="option" bind:tap="chooseTopic" data-type="judge" data-check="A">
<text class="choice {{topic[current].CHECK === 'A' ? 'check' : ''}} {{topic[current].ANSWER === 'A' ? (topic[current].ANSWERRIGHT === 'A' ? 'success' : 'error') : ''}}">A</text>
<text class="title">{{topic[current].OPTIONA}}</text>
</view>
<view class="option" bind:tap="chooseTopic" data-type="judge" data-check="B">
<text class="choice {{topic[current].CHECK === 'B' ? 'check' : ''}} {{topic[current].ANSWER === 'B' ? (topic[current].ANSWERRIGHT === 'B' ? 'success' : 'error') : ''}}">B</text>
<text class="title">{{topic[current].OPTIONB}}</text>
</view>
</view>
<view class="options" wx:if="{{topic[current].QUESTIONTYPE === '4'}}">
<view class="option">
<van-field value="{{ topic[current].CHECK }}" placeholder="请输入答案" border="{{ true }} " bind:change="onChange" />
</view>
</view>
<view class="answer" wx:if="{{type === 'practice' && topic[current].ANSWER}}">
正确答案:{{topic[current].ANSWERRIGHT}}
</view>
<view class="answer" wx:if="{{type === 'practice' && topic[current].ANSWER && topic[current].DESCR}}">
答案解析:{{topic[current].DESCR}}
</view>
</view>
<view class="button">
<van-button color="#d0d0d2" custom-style="color:#000;border-radius: 10rpx;width:{{current === topic.length - 1 ? 630 : 280}}rpx;" size="large" wx:if="{{current !== 0}}" bind:click="previousQuestion">
上一题
</van-button>
<van-button type="info" custom-style="border-radius: 10rpx;width:{{current === 0 ? 630 : 280}}rpx;" size="large" wx:if="{{current !== topic.length - 1}}" bind:click="nextQuestion">
下一题
</van-button>
</view>
</view>
<view class="footer">
<van-button color="linear-gradient(to right, #00ccff, #3676f2)" round size="small" wx:if="{{type !== 'practice'}}" bind:click="submitPapers">
交卷
</van-button>
<van-button color="linear-gradient(to right, #00ccff, #3676f2)" round size="small" wx:if="{{type === 'practice'}}" bind:click="viewAnswers">
查看答案
</van-button>
<view class="surplus">
<!-- <van-icon name="../../../assets/images/fenlei.png" /> -->
<view class="ml-10">
<text class="text-blue">{{current + 1}} </text>
<text>/ {{topic.length}}</text>
</view>
</view>
</view>
<van-dialog id="nation"></van-dialog>
</view>
<!-- 引入.wxs文件 src为相对路径module指定当前模块的名称 -->
<wxs module="filter" src="./func.wxs"></wxs>

View File

@ -0,0 +1,159 @@
.content{
padding: 20rpx;
}
.top {
border-radius: 20px;
text-align: center;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.van-count-down{
color: #eeecec !important;
font-size: 30rpx !important;
}
.head-text {
position: relative;
z-index: 99;
text-align: center;
font-size: 36rpx;
/* color: whitesmoke; */
bottom: 285rpx;
color: #fff;
font-weight: bold;
}
.question-info {
background-color: white;
padding: 20rpx;
border-radius: 20rpx;
}
.questions {
position: relative;
z-index: 99;
text-align: center;
font-size: 30rpx;
/* color: whitesmoke; */
bottom: 250rpx;
color: #eeecec;
}
.time {
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
z-index: 99;
text-align: center;
font-size: 25rpx;
/* color: whitesmoke; */
bottom: 220rpx;
color: #eeecec;
}
.van-count-down {
color: #eeecec;
font-size: 30rpx;
line-height: normal;
}
.question {
width: 100%;
padding: 20rpx 20rpx;
background: #ffffff;
border-radius: 10rpx;
box-sizing: border-box;
}
.count-down {
display: flex;
align-items: center;
justify-content: center;
background-color: #3676f2;
padding: 20rpx;
border-top: 1px solid rgba(248, 248, 248, 0.2);
text-align: center;
}
.container {
padding: 20rpx 20rpx;
}
.container .index {
padding-left: 10rpx;
}
.container .stem {
padding-left: 10rpx;
line-height: 55rpx;
}
.container .options .option {
margin-top: 50rpx;
}
.container .options .option .choice {
display: inline-block;
border-radius: 50%;
border: 1px solid #f1f1f1;
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
box-shadow: #f1f1f1;
}
.container .options .option .choice.check {
background-color: #cbcbcd;
color: #fff;
}
.container .options .option .choice.error {
background-color: #f65a4b;
color: #fff;
}
.container .options .option .choice.success {
background-color: #3676f2;
color: #fff;
}
.container .options .option .title {
margin-left: 20rpx;
}
.container .answer {
background-color: #ecf2fe;
padding: 20rpx;
margin-top: 50rpx;
border-radius: 10rpx;
}
.button {
padding: 40rpx 20rpx;
display: flex;
justify-content: space-between;
}
.footer {
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0 -2px 0 0 #f4f4f4;
background-color: #fff;
padding: 15rpx 30rpx;
}
.footer .surplus {
display: flex;
align-items: center;
color: #d5d5d5;
}

View File

@ -0,0 +1,13 @@
// 支持es4语法
var filter = {
totranType: function(value){
if(value == '1') return '单选'
if(value == '1') return '多选'
if(value == '1') return '判断'
if(value == '1') return '填空'
}
}
// 导出对外暴露的属性
module.exports = {
totranType: filter.totranType
}

View File

@ -0,0 +1,77 @@
// pages/exam/online/online.js
import Dialog from '@vant/weapp/dialog/dialog';
import Toast from '@vant/weapp/toast/toast';
import {
getExamListTaskByUser
} from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
showCount: 10,
timesOfexamination: 0,
currentPage: 1,
totalPage: 0,
varList: [],
},
goExam(item) {
let dataInfo = item.currentTarget.dataset.item
wx.navigateTo({
url: '/pages/exam/examination/examination' +
'?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
'&CLASS_ID=' + dataInfo.CLASS_ID +
'&EXAMNAME=' + dataInfo.EXAMNAME +
'&STUDENT_ID=' + dataInfo.STUDENT_ID +
'&PASSSCORE=' + dataInfo.PASSSCORE +
'&EXAMSCORE=' + dataInfo.EXAMSCORE +
'&NUMBEROFEXAMS=' + this.data.timesOfexamination +
'&SIMULATION=1' +
'&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME+
'&type=practice'
})
},
async getData() {
let resData = await getExamListTaskByUser({
showCount: this.data.showCount,
currentPage: this.data.currentPage,
simulation: 1
})
this.setData({
varList: [...this.data.varList, ...resData.varList],
totalPage: resData.page.totalPage
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
this.setData({
showCount: 10,
currentPage: 1,
totalPage: 0,
varList: [],
})
this.getData()
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.setData({
currentPage: ++this.data.currentPage
})
if (this.data.totalPage >= this.data.currentPage) {
this.getData()
}
},
})

View File

@ -0,0 +1,11 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-count-down": "@vant/weapp/count-down/index",
"van-button": "@vant/weapp/button/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-toast": "@vant/weapp/toast/index",
"van-empty": "@vant/weapp/empty/index"
},
"navigationBarTitleText": "模拟考试"
}

View File

@ -0,0 +1,38 @@
<wxs module="util" src="../../../utils/util.wxs"></wxs>
<view class="co">
<view class="my-studies-main" wx:if="{{ varList.length > 0 }}">
<view class="studies_wrap" wx:for="{{ varList }}" wx:key="CLASS_ID">
<view class="studies_wrap-top">
<view class="studies_wrap_title">班级名称: {{ item.CLASS_NAME }}</view>
<view class="studies_wrap_state">
<view class="fcd" wx:if="{{item.REMAINING > 0}}">待考试</view>
<view class="fcb" wx:else>考试中</view>
</view>
</view>
<view class="studies_wrap-main">
<view class="">行业类型:{{ item.TYPENAME }}</view>
<view class="">
培训开始时间:{{ item.START_TIME }}
</view>
<view class="">
培训结束时间:{{ item.END_TIME }}
</view>
</view>
<view class="studies_wrap-bottom">
<van-image width="50rpx" height="50rpx" src="/assets/images/exam/online/time.png"></van-image>
<view style="margin-right: 180rpx">
距离可考试时间
<van-count-down time="{{ item.REMAINING }}" format="DD天HH时mm分ss秒" />
</view>
<view>
<van-button round type="info" size="small" bind:click="goExam" data-item="{{ item }}">模拟考试</van-button>
</view>
</view>
</view>
</view>
<view wx:else>
<van-empty description="暂无更多" />
</view>
</view>
<van-dialog id="myDialog"></van-dialog>
<van-toast id="van-toast" />

View File

@ -0,0 +1,77 @@
.co {
min-height: 100vh;
}
.my-studies-main {
box-sizing: border-box;
padding: 20rpx;
}
.studies_wrap-top {
width: 100%;
display: flex;
justify-content: space-between;
padding: 20rpx 0;
}
.studies_wrap {
width: 100%;
padding: 0 20rpx;
background: #ffffff;
border-radius: 10rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
}
.studies_wrap_title {
font-weight: bold;
font-size: 30rpx;
}
.studies_wrap_state {
font-size: 30rpx;
flex-basis: 130rpx;
margin-left: 20rpx;
}
.studies_wrap-main {
border-top: 1px solid #eee;
line-height: 50rpx;
margin-top: 10rpx;
font-size: 28rpx;
color: #666;
}
.fcb {
margin-top: 2rpx;
margin-left: 15rpx;
color: #3377ff;
}
.fcd {
margin-top: 2rpx;
margin-left: 15rpx;
color: #666;
}
.studies_wrap-bottom {
width: 100%;
display: flex;
border-top: 1px solid #eee;
padding: 20rpx 0;
margin-top: 10rpx;
font-size: 28rpx;
color: #999;
justify-content: space-between;
align-items: center;
}
.van-count-down{
color: #999 !important;
font-size: 28rpx !important;
}
.flex {
display: flex;
align-items: center;
}

341
pages/exam/online/online.js Normal file
View File

@ -0,0 +1,341 @@
// pages/exam/online/online.js
import Dialog from '@vant/weapp/dialog/dialog';
import Toast from '@vant/weapp/toast/toast';
import {
getExamListTaskByUser,
updStuStartTime,
updStuSign
} from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
showCount: 10,
userSignShow: false,
timesOfexamination: 0,
currentPage: 1,
totalPage: 0,
STUDENT_ID: '',
varList: [],
dataInfo: {},
},
fnInput1(event) {
// 签字图片 event.detail
updStuSign({
filePath: event.detail,
formData:{
STUDENT_ID: this.data.STUDENT_ID
}
}).then((resData) => {
if(resData.code != 0) {
wx.showToast({
title: '请重签',
mask: false,
icon:error
})
}else {
wx.showToast({
title: '签字已经更新',
mask: false
})
this.setData({
varList: []
})
this.getData()
// if (!this.data.dataInfo.EXAM_FACE_PATH) {
// // 去人脸识别
// wx.navigateTo({
// url: '/pages/photo/collection?STUDENT_ID='+this.data.STUDENT_ID,
// })
// return
// }
}
}).catch((e) =>{
console.log(e);
})
},
userSignShowChange(){
this.setData({
userSignShow:!this.data.userSignShow
})
},
goExam(item) {
let dataInfo = item.currentTarget.dataset.item
this.setData({
STUDENT_ID: dataInfo.STUDENT_ID,
dataInfo: dataInfo
})
let that = this
// 是否签字
if (!dataInfo.SIGNATURE_PATH) {
this.userSignShowChange()
return
}
// if (!that.data.dataInfo.EXAM_FACE_PATH) {
// // 去人脸识别
// wx.navigateTo({
// url: '/pages/photo/collection?STUDENT_ID='+that.data.STUDENT_ID,
// })
// return
// }
this.setData({
timesOfexamination: dataInfo.NUMBEROFEXAMS - dataInfo.KSCOUNT
})
if (this.data.timesOfexamination === 0) {
Toast.loading({
type: 'fail',
message: '您无考试机会',
selector: '#van-toast',
});
} else {
Dialog.confirm({
message: '你还有' + that.data.timesOfexamination + '次考试机会',
context: this
})
.then(() => {
updStuStartTime({
STUDENT_ID: dataInfo.STUDENT_ID
})
wx.navigateTo({
url: '/pages/exam/examination/examination' +
'?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
'&CLASS_ID=' + dataInfo.CLASS_ID +
'&EXAMNAME=' + dataInfo.EXAMNAME +
'&STUDENT_ID=' + dataInfo.STUDENT_ID +
'&PASSSCORE=' + dataInfo.PASSSCORE +
'&EXAMSCORE=' + dataInfo.EXAMSCORE +
'&NUMBEROFEXAMS=' + this.data.timesOfexamination +
'&SIMULATION=0' +
'&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
})
})
.catch(() => {});
Dialog.confirm({
message: '你还有' + that.data.timesOfexamination + '次考试机会',
selector: '#myDialog',
})
.then(() => {
updStuStartTime({
STUDENT_ID: dataInfo.STUDENT_ID
})
wx.navigateTo({
url: '/pages/exam/examination/examination' +
'?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
'&CLASS_ID=' + dataInfo.CLASS_ID +
'&EXAMNAME=' + dataInfo.EXAMNAME +
'&STUDENT_ID=' + dataInfo.STUDENT_ID +
'&PASSSCORE=' + dataInfo.PASSSCORE +
'&EXAMSCORE=' + dataInfo.EXAMSCORE +
'&NUMBEROFEXAMS=' + this.data.timesOfexamination +
'&SIMULATION=0' +
'&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
})
})
.catch(() => {});
// wx.showModal({
// content: '你还有'+ that.data.timesOfexamination +'次考试机会',
// success: function(res) {
// if(res.confirm) {
// updStuStartTime({
// STUDENT_ID: dataInfo.STUDENT_ID
// })
// wx.navigateTo({
// url: '/pages/exam/examination/examination' +
// '?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
// '&CLASS_ID=' + dataInfo.CLASS_ID +
// '&EXAMNAME=' + dataInfo.EXAMNAME +
// '&STUDENT_ID=' + dataInfo.STUDENT_ID +
// '&PASSSCORE=' + dataInfo.PASSSCORE +
// '&EXAMSCORE=' + dataInfo.EXAMSCORE +
// '&NUMBEROFEXAMS=' + that.data.timesOfexamination +
// '&SIMULATION=0' +
// '&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
// })
// } else if (res.cancel) {
// console.log('用户点击了取消')
// }
// }
// })
// Dialog.confirm({
// message: '你还有' + that.data.timesOfexamination + '次考试机会',
// selector: '#myDialog',
// })
// .then(() => {
// updStuStartTime({
// STUDENT_ID: dataInfo.STUDENT_ID
// })
// wx.navigateTo({
// url: '/pages/exam/examination/examination' +
// '?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
// '&CLASS_ID=' + dataInfo.CLASS_ID +
// '&EXAMNAME=' + dataInfo.EXAMNAME +
// '&STUDENT_ID=' + dataInfo.STUDENT_ID +
// '&PASSSCORE=' + dataInfo.PASSSCORE +
// '&EXAMSCORE=' + dataInfo.EXAMSCORE +
// '&NUMBEROFEXAMS=' + this.data.timesOfexamination +
// '&SIMULATION=0' +
// '&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
// })
// })
// .catch(() => {});
}
},
// 倒计时结束
finished() {
this.setData({
varList: [],
})
this.getData()
},
/**
* 人脸验证成功回调
*/
photoResult(dataInfo) {
let that = this
this.setData({
timesOfexamination: dataInfo.NUMBEROFEXAMS - dataInfo.KSCOUNT
})
if (this.data.timesOfexamination === 0) {
Toast.loading({
type: 'fail',
message: '您无考试机会',
selector: '#van-toast',
});
} else {
Dialog.confirm({
message: '你还有' + that.data.timesOfexamination + '次考试机会',
context: this
})
.then(() => {
updStuStartTime({
STUDENT_ID: dataInfo.STUDENT_ID
})
wx.navigateTo({
url: '/pages/exam/examination/examination' +
'?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
'&CLASS_ID=' + dataInfo.CLASS_ID +
'&EXAMNAME=' + dataInfo.EXAMNAME +
'&STUDENT_ID=' + dataInfo.STUDENT_ID +
'&PASSSCORE=' + dataInfo.PASSSCORE +
'&EXAMSCORE=' + dataInfo.EXAMSCORE +
'&NUMBEROFEXAMS=' + this.data.timesOfexamination +
'&SIMULATION=0' +
'&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
})
})
.catch(() => {});
Dialog.confirm({
message: '你还有' + that.data.timesOfexamination + '次考试机会',
selector: '#myDialog',
})
.then(() => {
updStuStartTime({
STUDENT_ID: dataInfo.STUDENT_ID
})
wx.navigateTo({
url: '/pages/exam/examination/examination' +
'?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
'&CLASS_ID=' + dataInfo.CLASS_ID +
'&EXAMNAME=' + dataInfo.EXAMNAME +
'&STUDENT_ID=' + dataInfo.STUDENT_ID +
'&PASSSCORE=' + dataInfo.PASSSCORE +
'&EXAMSCORE=' + dataInfo.EXAMSCORE +
'&NUMBEROFEXAMS=' + this.data.timesOfexamination +
'&SIMULATION=0' +
'&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
})
})
.catch(() => {});
// wx.showModal({
// content: '你还有'+ that.data.timesOfexamination+'次考试机会',
// success: function(res) {
// if(res.confirm) {
// updStuStartTime({
// STUDENT_ID: dataInfo.STUDENT_ID
// })
// wx.navigateTo({
// url: '/pages/exam/examination/examination' +
// '?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
// '&CLASS_ID=' + dataInfo.CLASS_ID +
// '&EXAMNAME=' + dataInfo.EXAMNAME +
// '&STUDENT_ID=' + dataInfo.STUDENT_ID +
// '&PASSSCORE=' + dataInfo.PASSSCORE +
// '&EXAMSCORE=' + dataInfo.EXAMSCORE +
// '&NUMBEROFEXAMS=' + that.data.timesOfexamination +
// '&SIMULATION=0' +
// '&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
// })
// } else if (res.cancel) {
// console.log('用户点击了取消')
// }
// }
// })
// Dialog.alert({
// message: '你还有'+ that.data.timesOfexamination+'次考试机会',
// selector: '#myDialog',
// })
// .then(() => {
// updStuStartTime({
// STUDENT_ID: dataInfo.STUDENT_ID
// })
// wx.navigateTo({
// url: '/pages/exam/examination/examination' +
// '?STAGEEXAMPAPERINPUT_ID=' + dataInfo.PAPER_ID +
// '&CLASS_ID=' + dataInfo.CLASS_ID +
// '&EXAMNAME=' + dataInfo.EXAMNAME +
// '&STUDENT_ID=' + dataInfo.STUDENT_ID +
// '&PASSSCORE=' + dataInfo.PASSSCORE +
// '&EXAMSCORE=' + dataInfo.EXAMSCORE +
// '&NUMBEROFEXAMS=' + this.data.timesOfexamination +
// '&SIMULATION=0' +
// '&ANSWERSHEETTIME=' + dataInfo.ANSWERSHEETTIME,
// })
// })
// .catch(() => {});
}
},
async getData() {
let resData = await getExamListTaskByUser({
showCount: this.data.showCount,
currentPage: this.data.currentPage
})
this.setData({
varList: [...this.data.varList, ...resData.varList],
totalPage: resData.page.totalPage
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
this.setData({
showCount: 10,
currentPage: 1,
totalPage: 0,
varList: [],
})
this.getData()
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.setData({
currentPage: ++this.data.currentPage
})
if (this.data.totalPage >= this.data.currentPage) {
this.getData()
}
},
})

View File

@ -0,0 +1,12 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-count-down": "@vant/weapp/count-down/index",
"van-button": "@vant/weapp/button/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-toast": "@vant/weapp/toast/index",
"van-empty": "@vant/weapp/empty/index",
"sign": "/components/sign/sign"
},
"navigationBarTitleText": "在线考试"
}

View File

@ -0,0 +1,42 @@
<wxs module="util" src="../../../utils/util.wxs"></wxs>
<view class="co">
<view class="my-studies-main" wx:if="{{varList.length > 0}}">
<view class="studies_wrap" wx:for="{{ varList }}" wx:key="CLASS_ID">
<view class="studies_wrap-top">
<view class="studies_wrap_title">班级名称: {{ item.CLASS_NAME }}</view>
<view class="studies_wrap_state">
<view class="fcb" wx:if="{{item.STAGEEXAMSTATE == 1}}">待考试</view>
<view class="fcr" wx:else>未通过</view>
</view>
</view>
<view class="studies_wrap-main">
<view class="">行业类型:{{ item.TYPENAME }}</view>
<view class="">
培训开始时间:{{ item.START_TIME }}
</view>
<view class="">
培训结束时间:{{ item.END_TIME }}
</view>
</view>
<view class="studies_wrap-bottom">
<van-image wx:if="{{item.REMAINING > 0}}" width="50rpx" height="50rpx" src="/assets/images/exam/online/time.png"></van-image>
<!--占个位-->
<view wx:else width="50rpx" height="50rpx" ></view>
<view wx:if="{{item.REMAINING > 0}}" class="flex">
<view>距离可考试时间:</view>
<van-count-down bind:finish="finished" time="{{ item.REMAINING }}" format="DD天HH时mm分ss秒" />
</view>
<view wx:else>
<van-button wx:if="{{item.NUMBEROFEXAMS - item.KSCOUNT > 0 }}" round type="info" size="small" bind:click="goExam" data-item="{{ item }}">立即考试</van-button>
<view wx:else round type="info" size="small" >您无考试机会</view>
</view>
</view>
</view>
</view>
<view wx:else>
<van-empty description="暂无更多" />
</view>
<sign show="{{userSignShow}}" bindsubCanvas="fnInput1" bindhideModal="userSignShowChange" data-key="userSign"></sign>
</view>
<van-dialog id="van-dialog" />
<van-toast id="van-toast" />

View File

@ -0,0 +1,80 @@
.co {
min-height: 100vh;
}
.my-studies-main {
box-sizing: border-box;
padding: 20rpx;
}
.studies_wrap-top {
width: 100%;
display: flex;
justify-content: space-between;
padding: 20rpx 0;
}
.studies_wrap {
width: 100%;
padding: 0 20rpx;
background: #ffffff;
border-radius: 10rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
}
.studies_wrap_title {
font-weight: bold;
font-size: 30rpx;
}
.studies_wrap_state {
font-size: 30rpx;
flex-basis: 130rpx;
margin-left: 20rpx;
}
.studies_wrap-main {
border-top: 1px solid #eee;
line-height: 50rpx;
margin-top: 10rpx;
font-size: 28rpx;
color: #666;
}
.fcb {
margin-top: 2rpx;
margin-left: 15rpx;
color: #3377ff;
}
.fcr {
margin-top: 2rpx;
margin-left: 15rpx;
color: red;
}
.fcd {
margin-top: 2rpx;
margin-left: 15rpx;
color: #666;
}
.studies_wrap-bottom {
width: 100%;
display: flex;
border-top: 1px solid #eee;
padding: 20rpx 0;
margin-top: 10rpx;
font-size: 28rpx;
color: #999;
justify-content: space-between;
align-items: center;
}
.van-count-down{
color: #999 !important;
font-size: 28rpx !important;
}
.flex {
display: flex;
}

101
pages/exam/record/record.js Normal file
View File

@ -0,0 +1,101 @@
// pages/exam/record/record.js
import {
getExamRecordListByUser
} from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
PASSEDNUM: 0,
showCount: 10,
currentPage: 1,
totalPage: 0,
varList: [],
},
async getData() {
const resData = await getExamRecordListByUser({
showCount: this.data.showCount,
currentPage: this.data.currentPage
})
this.setData({
varList: [...this.data.varList, ...resData.varList],
totalPage: resData.page.totalPage,
ALLEXAMTIMES: resData.page.totalResult,
PASSEDNUM: resData.baseInfo.PASSEDNUM
})
},
goResult(e) {
let resData = e.currentTarget.dataset.item
wx.navigateTo({
url: '/pages/exam/results/results?STAGEEXAM_ID=' +
resData.STAGEEXAM_ID +
'&EXAMRESULT=' + resData.RESULT +
'&EXAMSCORE=' + resData.EXAMSCORE +
'&PASSSCORE=' + resData.PASSSCORE +
'&PAPER_EXAMSCORE=' + resData.ALL_EXAMSCORE,
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.getData()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.setData({
currentPage: ++this.data.currentPage
})
if (this.data.totalPage >= this.data.currentPage) {
this.getData()
}
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

View File

@ -0,0 +1,14 @@
{
"usingComponents": {
"van-tag": "@vant/weapp/tag/index",
"van-image": "@vant/weapp/image/index",
"van-count-down": "@vant/weapp/count-down/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-icon": "@vant/weapp/icon/index",
"van-sticky": "@vant/weapp/sticky/index",
"van-button": "@vant/weapp/button/index",
"van-empty": "@vant/weapp/empty/index"
},
"navigationBarTitleText": "考试记录"
}

View File

@ -0,0 +1,61 @@
<view class="content">
<view class="top">
<view class="option">
<van-image width="700rpx" height="230rpx" src="/assets/images/exam/examination/bgimg1.png" />
<view class="head-text">
我的成绩
</view>
<view class="scoremain">
<view>
<view>
{{ ALLEXAMTIMES }}
</view>
<view>
参加考试次数
</view>
</view>
<view>
<view>
{{ PASSEDNUM }}
</view>
<view>
合格次数
</view>
</view>
<view>
<view>
{{ ALLEXAMTIMES - PASSEDNUM }}
</view>
<view>
不合格次数
</view>
</view>
</view>
</view>
</view>
<view wx:if="{{varList.length > 0}}">
<view class="studies_wrap" wx:for="{{ varList }}" wx:key="STAGEEXAM_ID">
<view bindtap="goResult" data-item="{{ item }}">
<view class="studies_wrap-top">
<view class="studies_wrap_title">考试成绩: {{ item.EXAMSCORE }}</view>
<view class="studies_wrap_state">
<view class="fcd" wx:if="{{item.RESULT != '1'}}">未通过</view>
<view class="fcb" wx:else="">已通过</view>
</view>
</view>
<view class="studies_wrap-main">
<view class="">班级名称:{{ item.CLASS_NAME }}</view>
<view class="">
考试开始时间:{{item.EXAMTIMEBEGIN}}
</view>
<view class="">
考试结束时间:{{item.EXAMTIMEEND}}
</view>
</view>
</view>
</view>
</view>
<view wx:else>
<van-empty description="暂无更多记录" />
</view>
</view>

View File

@ -0,0 +1,80 @@
.content {
padding: 20rpx;
}
.top {
border-radius: 20px;
text-align: center;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.option{
height:230rpx;
}
.head-text {
position: relative;
z-index: 99;
text-align: center;
font-size: 40rpx;
bottom: 220rpx;
color: #fff;
font-weight: bold;
}
.scoremain {
position: relative;
z-index: 99;
text-align: center;
font-size: 30rpx;
bottom: 180rpx;
color: #fff;
font-weight: bold;
display: flex;
flex-direction: row;
justify-content: space-between;
color: #fff;
padding: 0 30rpx;
}
.studies_wrap-top {
width: 100%;
display: flex;
justify-content: space-between;
padding: 20rpx 0;
}
.studies_wrap {
width: 100%;
padding: 0 20rpx;
margin-top: 20rpx;
background: #ffffff;
border-radius: 10rpx;
box-sizing: border-box;
}
.studies_wrap_title {
font-weight: bold;
font-size: 30rpx;
}
.fcb {
margin-top: 2rpx;
margin-left: 15rpx;
color: green;
}
.fcd {
margin-top: 2rpx;
margin-left: 15rpx;
color: red;
}
.studies_wrap_state {
font-size: 30rpx;
flex-basis: 130rpx;
margin-left: 20rpx;
}
.studies_wrap-main {
border-top: 1px solid #eee;
line-height: 50rpx;
font-size: 28rpx;
padding: 15rpx 0;
color: #666;
}

View File

@ -0,0 +1,53 @@
import {
getExamRecordByUser
} from "../../../api/index";
Page({
data: {
type: '',
STAGEEXAM_ID: '',
STUDYTASK_ID: '',
CURRICULUM_ID: '',
topic: [],
stageExam: {
EXAMRESULT: '1',
PAPERSCORE: "100",
EXAMSCORE: "60"
}
},
onLoad(options) {
let info = {}
info.EXAMRESULT = options.EXAMRESULT
info.PAPERSCORE = options.PAPER_EXAMSCORE
info.EXAMSCORE = options.EXAMSCORE
// STAGEEXAM_ID
this.setData({
stageExam: info,
STAGEEXAM_ID: options.STAGEEXAM_ID
})
this.getData()
// if (options.type === 'learned') {
// this.getData()
// } else {
// this.setData({
// topic: app.globalData.mockTestResult.topic,
// stageExam: app.globalData.mockTestResult.stageExam,
// })
// }
},
async getData() {
let resData = await getExamRecordByUser({
STAGEEXAM_ID: this.data.STAGEEXAM_ID
})
this.setData({
topic: resData.varList
})
},
onUnload() {
// app.globalData.mockTestResult = {}
// if (this.data.type !== 'learned') {
// wx.switchTab({
// url: '/pages/index/index'
// })
// }
}
})

View File

@ -0,0 +1,6 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-tag": "@vant/weapp/tag/index"
}
}

View File

@ -0,0 +1,98 @@
<!--pages/exam/results/results.wxml-->
<wxs module="tool" src="../../../utils/util.wxs"></wxs>
<view class="content">
<van-image width="100%" height="278rpx" src="/assets/images/exam/results/showbg.png"/>
<view class="results">
<block wx:if="{{stageExam.EXAMRESULT === '1'}}">
<view class="image">
<van-image width="135rpx" height="135rpx" src="/assets/images/exam/results/OK.png"/>
</view>
<view class="title success">恭喜您,考试合格!</view>
</block>
<block wx:if="{{stageExam.EXAMRESULT === '0'}}">
<view class="image">
<van-image width="135rpx" height="135rpx" src="/assets/images/exam/results/wrong.png"/>
</view>
<view class="title error">很遗憾,考试不合格!</view>
</block>
<view class="score">
<view>
<view class="value total-score">{{stageExam.PAPERSCORE}}</view>
<view class="label">总分</view>
</view>
<view>
<view class="value this-score">{{stageExam.EXAMSCORE}}</view>
<view class="label">本次得分</view>
</view>
</view>
</view>
<view class="tip" wx:if="{{type === 'coursewareLibrary'}}">此次考试为模拟考试,不计入成绩,退出之后无法再次查看</view>
<view class="placeholder" wx:else></view>
<view class="exercises">
<view class="title">答案详情</view>
<view class="container">
<view class="item" wx:for="{{topic}}" wx:key="index">
<van-tag type="primary" size="small">
<block wx:if="{{item.QUESTIONTYPE === '1'}}">单选题</block>
<block wx:if="{{item.QUESTIONTYPE === '2'}}">多选题</block>
<block wx:if="{{item.QUESTIONTYPE === '3'}}">判断题</block>
<block wx:if="{{item.QUESTIONTYPE === '4'}}">填空题</block>
</van-tag>
<text class="index">{{index + 1}}.</text>
<text class="stem">{{item.QUESTIONDRY}}</text>
<view class="options" wx:if="{{item.QUESTIONTYPE === '1'}}">
<view class="option">
<text class="choice {{item.ANSWER === 'A' ? (item.ANSWERRIGHT === 'A' ? 'success' : 'error') : ''}}">A</text>
<text class="title">{{item.OPTIONA}}</text>
</view>
<view class="option">
<text class="choice {{item.ANSWER === 'B' ? (item.ANSWERRIGHT === 'B' ? 'success' : 'error') : ''}}">B</text>
<text class="title">{{item.OPTIONB}}</text>
</view>
<view class="option">
<text class="choice {{item.ANSWER === 'C' ? (item.ANSWERRIGHT === 'C' ? 'success' : 'error') : ''}}">C</text>
<text class="title">{{item.OPTIONC}}</text>
</view>
<view class="option">
<text class="choice {{item.ANSWER === 'D' ? (item.ANSWERRIGHT === 'D' ? 'success' : 'error') : ''}}">D</text>
<text class="title">{{item.OPTIOND}}</text>
</view>
</view>
<view class="options" wx:if="{{item.QUESTIONTYPE === '2'}}">
<view class="option">
<text class="choice {{tool.indexOf(item.ANSWER,'A') !== -1 ? (tool.indexOf(item.ANSWERRIGHT,'A') !== -1 ? 'success' : 'error') : ''}}">A</text>
<text class="title">{{item.OPTIONA}}</text>
</view>
<view class="option">
<text class="choice {{tool.indexOf(item.ANSWER,'B') !== -1 ? (tool.indexOf(item.ANSWERRIGHT,'B') !== -1 ? 'success' : 'error') : ''}}">B</text>
<text class="title">{{item.OPTIONB}}</text>
</view>
<view class="option">
<text class="choice {{tool.indexOf(item.ANSWER,'C') !== -1 ? (tool.indexOf(item.ANSWERRIGHT,'C') !== -1 ? 'success' : 'error') : ''}}">C</text>
<text class="title">{{item.OPTIONC}}</text>
</view>
<view class="option">
<text class="choice {{tool.indexOf(item.ANSWER,'D') !== -1 ? (tool.indexOf(item.ANSWERRIGHT,'D') !== -1 ? 'success' : 'error') : ''}}">D</text>
<text class="title">{{item.OPTIOND}}</text>
</view>
</view>
<view class="options" wx:if="{{item.QUESTIONTYPE === '3'}}">
<view class="option">
<text class="choice {{item.ANSWER === 'A' ? (item.ANSWERRIGHT === 'A' ? 'success' : 'error') : ''}}">A</text>
<text class="title">{{item.OPTIONA}}</text>
</view>
<view class="option">
<text class="choice {{item.ANSWER === 'B' ? (item.ANSWERRIGHT === 'B' ? 'success' : 'error') : ''}}">B</text>
<text class="title">{{item.OPTIONB}}</text>
</view>
</view>
<view class="answer">
学员答案:{{item.ANSWER}}
</view>
<view class="answer">
正确答案:{{item.ANSWERRIGHT}}
</view>
</view>
</view>
</view>
</view>

View File

@ -0,0 +1,162 @@
.content {
background-color: #fff;
}
.results {
width: 90%;
height: 300rpx;
background-color: #fff;
position: absolute;
top: 100rpx;
left: 5%;
border-radius: 20rpx;
box-shadow: 6rpx 6rpx 40rpx 0 rgba(27, 87, 178, 0.3), -6rpx 0 40rpx 0 rgba(27, 87, 178, 0.3);
}
.results .image {
background-color: #fff;
border-radius: 50%;
box-shadow: 6rpx 0 40rpx 0 rgba(27, 87, 178, 0.3);
width: 180rpx;
height: 180rpx;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: -90rpx;
left: 50%;
transform: translateX(-50%);
}
.results .title {
text-align: center;
width: 100%;
font-weight: bold;
font-size: 36rpx;
position: absolute;
top: 40%;
transform: translateY(-50%);
}
.results .title.success {
color: #5ea908;
}
.results .title.error {
color: #ff3c02;
}
.results .score {
width: 100%;
display: flex;
justify-content: space-around;
text-align: center;
position: absolute;
bottom: 30rpx;
font-size: 24rpx;
}
.results .score .value {
font-weight: bold;
font-size: 36rpx;
}
.results .score .value.total-score {
color: #247bff;
}
.results .score .value.this-score {
color: #60a808;
}
.results .score .value.earn-points {
color: #f65a4b;
}
.results .score .label {
color: #b6b6b6;
}
.tip {
width: 90%;
background-color: #ecf2fd;
margin: 150rpx 5% 40rpx;
font-size: 24rpx;
padding: 10rpx 0;
text-align: center;
border-radius: 10rpx;
color: #db8b84;
}
.placeholder {
margin-top: 160rpx;
height: 0;
}
.exercises>.title {
font-weight: bold;
position: relative;
padding-left: 20rpx;
margin-left: 5%;
}
.exercises>.title::before {
content: '';
position: absolute;
top: 10rpx;
left: 0;
width: 8rpx;
height: 30rpx;
background-color: #257cff;
border-radius: 10rpx;
}
.exercises .container .item {
padding: 20rpx 5%;
border-bottom: 10rpx solid #f0f0f0;
}
.exercises .container .index {
padding-left: 10rpx;
}
.exercises .container .stem {
padding-left: 10rpx;
line-height: 55rpx;
}
.exercises .container .options .option {
margin-top: 50rpx;
}
.exercises .container .options .option .choice {
display: inline-block;
border-radius: 50%;
border: 1px solid #f1f1f1;
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
box-shadow: #f1f1f1;
}
.exercises .container .options .option .choice.error {
background-color: #f65a4b;
color: #fff;
}
.exercises .container .options .option .choice.success {
background-color: #3676f2;
color: #fff;
}
.exercises .container .options .option .title {
margin-left: 20rpx;
}
.exercises .container .answer {
background-color: #ecf2fe;
padding: 20rpx;
margin-top: 50rpx;
border-radius: 10rpx;
}

63
pages/index/index.js Normal file
View File

@ -0,0 +1,63 @@
const app = getApp()
import Dialog from '@vant/weapp/dialog/dialog';
Page({
data: {
userSignShow: false
},
toOnline: function (events) {
this.isAuthentication('/pages/exam/online/online')
},
toPhoto: function (events) {
wx.navigateTo({
url: '/pages/photo/collection',
})
},
toSign: function (events) {
wx.navigateTo({
url: '/pages/sign/sign',
})
},
toImitate: function (events) {
this.isAuthentication('/pages/exam/imitate/imitate')
// wx.navigateTo({
// url: '/pages/exam/imitate/imitate',
// // events: events,
// // success: (result) => {},
// // fail: (res) => {},
// // complete: (res) => {},
// })
},
isAuthentication: function (url) {
wx.navigateTo({
url: url,
})
// 首次照片采集
// let user = app.globalData.userInfo
// if (user.AUTHENTICATION == '1') {
// wx.navigateTo({
// url: url,
// })
// } else {
// Dialog.confirm({
// message: '需要先进行照片采集',
// selector: '#myDialog',
// })
// .then(() => {
// wx.navigateTo({
// url: '/pages/photo/collection',
// })
// })
// .catch(() => {
// });
// }
},
toRecord: function (events) {
this.isAuthentication('/pages/exam/record/record')
// wx.navigateTo({
// url: '/pages/exam/record/record',
// })
}
})

9
pages/index/index.json Normal file
View File

@ -0,0 +1,9 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-toast": "@vant/weapp/toast/index",
"sign": "/components/sign/sign"
},
"navigationBarTitleText": "联安考"
}

45
pages/index/index.wxml Normal file
View File

@ -0,0 +1,45 @@
<view class="content">
<view>
<view class="banner">
<van-image width="692rpx" height="202rpx" src="/assets/images/index/banner.png" />
</view>
<view class="options">
<view class="option" style="background-color: #1c76ea;" bindtap="toOnline">
<van-image width="60rpx" height="60rpx" src="/assets/images/index/kaoshi.png" />
<view>
<view class="title">在线考试</view>
<view class="describe">随机抽题/自动评分</view>
</view>
</view>
<view class="option" style="background-color: #9570f2;" bindtap="toImitate">
<van-image width="60rpx" height="60rpx" src="/assets/images/index/lianxi.png" />
<view>
<view class="title">模拟练习</view>
<view class="describe">随机抽题模拟测试</view>
</view>
</view>
<view class="option" style="background-color: #00bebe;" bindtap="toRecord">
<van-image width="60rpx" height="60rpx" src="/assets/images/index/jilu.png" />
<view>
<view class="title">考试记录</view>
<view class="describe">记录考试状态成绩</view>
</view>
</view>
<view class="option" style="background-color: #F79709" bindtap="toSign">
<van-image width="60rpx" height="60rpx" src="/assets/images/index/sign.png" />
<view>
<view class="title">签字采集</view>
<view class="describe">采集考试签字信息</view>
</view>
</view>
<!-- <view class="option" style="background-color: #14adf9;" bindtap="toPhoto">
<van-image width="60rpx" height="60rpx" src="/assets/images/index/tupian.png" />
<view>
<view class="title">照片采集</view>
<view class="describe">采集人脸照片信息</view>
</view>
</view> -->
</view>
</view>
<van-dialog id="myDialog"></van-dialog>
</view>

43
pages/index/index.wxss Normal file
View File

@ -0,0 +1,43 @@
.content{
background-color: #fff;
min-height: 100vh;
}
.banner {
width: 692rpx;
height: 202rpx;
padding-top: 15rpx;
margin: auto;
}
.options {
width: 692rpx;
margin: 10rpx auto 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.options .option {
width: calc((692rpx - 15rpx) / 2);
padding: 26rpx 0;
margin-top: 15rpx;
margin-left: 15rpx;
border-radius: 20rpx;
color: #fff;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.options .option:nth-child(2n+1) {
margin-left: 0;
}
.options .option .title {
font-size: 30rpx;
}
.options .option .describe {
font-size: 22rpx;
padding-top: 10rpx;
}

46
pages/login/login.js Normal file
View File

@ -0,0 +1,46 @@
import {login} from "../../api/index";
import debounce from '../../utils/debounce'
const app = getApp()
Page({
data: {
userName: '',
password: '',
},
onLoad() {
if (!app.globalData.userInfo.USER_ID) {
wx.reLaunch({
url: 'pages/login/login'
})
} else {
wx.switchTab({
url: '/pages/index/index'
})
}
},
submitLogin() {
debounce(async () => {
if (!this.data.userName) {
wx.showToast({
title: '请输入用户名',
icon: 'none'
})
return
}
if (!this.data.password) {
wx.showToast({
title: '请输入密码',
icon: 'none'
})
return
}
let KEYDATA = `qdkjchina${this.data.userName},qd,${this.data.password}`
app.globalData.userInfo = await login({
KEYDATA
})
wx.switchTab({
url: '/pages/index/index'
})
})
}
})

9
pages/login/login.json Normal file
View File

@ -0,0 +1,9 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-field": "@vant/weapp/field/index",
"van-cell-group": "@vant/weapp/cell-group/index",
"van-button": "@vant/weapp/button/index"
},
"navigationStyle": "custom"
}

22
pages/login/login.wxml Normal file
View File

@ -0,0 +1,22 @@
<view class="container">
<!-- <web-view src="http://192.168.0.18:8080/static/html.html" fullscreen allow></web-view> -->
<view class="banner">
<van-image width="100%" height="415rpx" src="/assets/images/login/loginbg.png" />
<view class="title text-white">
<view class="hello">您好!</view>
<view class="welcome">欢迎来到联安考</view>
</view>
</view>
<view class="login">
<view class="title">登录</view>
<view class="form">
<van-cell-group border="{{ false }}">
<van-field left-icon="/assets/images/login/userico.png" model:value="{{ userName }}" placeholder="请输入用户名" border="{{ false }}" custom-style="margin-top:50rpx;background-color:#f4f4fc;border-radius:40rpx" />
<van-field left-icon="/assets/images/login/paswordico.png" model:value="{{ password }}" type="password" placeholder="请输入密码" border="{{ false }}" custom-style="margin-top:50rpx;background-color:#f4f4fc;border-radius:40rpx" />
</van-cell-group>
<van-button color="linear-gradient(to right, #00ccff, #3676f2)" round size="small" custom-style="margin-top:50rpx; width:100%; height:70rpx" bind:click="submitLogin">
登录
</van-button>
</view>
</view>
</view>

37
pages/login/login.wxss Normal file
View File

@ -0,0 +1,37 @@
.container{
background-color: #fff;
min-height: 100vh;
}
.banner {
position: relative;
}
.banner .title {
position: absolute;
top: 150rpx;
left: 50rpx;
}
.banner .title .hello {
font-weight: bold;
font-size: 40rpx;
}
.banner .title .welcome {
padding-top: 8rpx;
font-size: 38rpx;
}
.login {
background-color: #fff;
border-radius: 40rpx 40rpx 0 0;
padding: 50rpx 50rpx;
margin-top: -50rpx;
position: relative;
z-index: 99;
}
.login .title {
font-weight: bold;
font-size: 46rpx;
}

View File

@ -0,0 +1,66 @@
// pages/mine/aboutus/aboutus.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"navigationBarTitleText": "关于我们"
}

View File

@ -0,0 +1,4 @@
<view class="container">
<!-- 那么重点就是对模式的叙述;有些公司的成立,是因为创始人有了一项新的发明,那么重点就是对发明价值的陈述;有些公司的成立,是因为有几个合伙人的志同道合,大家想做出一份事业... -->
河北秦安安全科技股份有限公司是以“大数据”为载体为企业提供精准风险管理的综合技术服务提供商。公司于2017年8月3日在全国中小企业股转中心新三板挂牌上市是河北省内一家以提供安全生产技术服务上市的公司股票代码871771。
</view>

View File

@ -0,0 +1,10 @@
.container {
background-color: #fff;
min-height: 100vh;
padding: 20rpx;
box-sizing: border-box;
line-height: 1.8;
font-size:32rpx;
text-indent: 2rem;
color: #333333;
}

View File

@ -0,0 +1,69 @@
import debounce from "../../../utils/debounce";
import {setChangePassword} from "../../../api/index";
const app = getApp()
Page({
data: {
form: {
password: '',
newPassword: '',
againNewPassword: '',
},
rules: {
"password": "请输入旧密码",
"newPassword": "请输入新密码",
"againNewPassword": "请再次输入新密码",
}
},
bindInput(event) {
this.setData({
form: {
...this.data.form,
[event.currentTarget.dataset.key]: event.detail,
}
})
},
submitPassword() {
debounce(async () => {
for (const rulesKey in this.data.rules) {
if (!this.data.form[rulesKey]) {
wx.showToast({
title: this.data.rules[rulesKey],
icon: "none"
})
return;
}
}
if (this.data.form.newPassword !== this.data.form.againNewPassword) {
wx.showToast({
title: '两次密码不一致',
icon: "none"
})
return
}
const resData = await setChangePassword({
USERNAME: app.globalData.userInfo.USERNAME,
USER_ID: app.globalData.userInfo.USER_ID,
PASSWORD: this.data.form.password,
NOWPASSWORD: this.data.form.newPassword,
})
if(resData.code != "0") {
wx.showToast({
title: '旧密码有误',
icon:'error'
})
return
}
wx.showToast({
title: '修改成功',
mask: true
})
app.globalData.userInfo = {}
setTimeout(() => {
wx.reLaunch({
url: '/pages/login/login'
})
}, 1500)
})
}
})

View File

@ -0,0 +1,8 @@
{
"usingComponents": {
"van-field": "@vant/weapp/field/index",
"van-button": "@vant/weapp/button/index",
"van-cell-group": "@vant/weapp/cell-group/index"
},
"navigationBarTitleText": "修改密码"
}

View File

@ -0,0 +1,37 @@
<view class="container">
<van-cell-group inset>
<van-field
value="{{ form.password }}"
type="password"
label="旧密码"
placeholder="请输入旧密码"
required
bind:input="bindInput"
data-key="password"
/>
<van-field
value="{{ form.newPassword }}"
type="password"
label="新密码"
placeholder="请输入新密码"
required
bind:input="bindInput"
data-key="newPassword"
/>
<van-field
value="{{ form.againNewPassword }}"
type="password"
label="重复密码"
placeholder="请再次输入新密码"
required
bind:input="bindInput"
data-key="againNewPassword"
/>
</van-cell-group>
<view class="button">
<van-button color="linear-gradient(to right, #00ccff, #3676f2)" round size="small"
custom-style="margin-top:50rpx; width:100%; height:70rpx" bind:click="submitPassword">
确定
</van-button>
</view>
</view>

View File

@ -0,0 +1,10 @@
.container {
background-color: #f7f8fa;
min-height: 100vh;
padding: 30rpx 0;
}
.button {
width: 90%;
margin-left: 5%;
}

35
pages/mine/index/index.js Normal file
View File

@ -0,0 +1,35 @@
import Dialog from '@vant/weapp/dialog/dialog';
import {getUserScoreSum} from "../../../api/index";
const app = getApp()
Page({
data: {
totalScore: 0,
userInfo: {}
},
onShow(options) {
this.setData({
userInfo: app.globalData.userInfo,
})
this.getUserScoreSum()
},
async getUserScoreSum() {
let resData = await getUserScoreSum({USER_ID: app.globalData.userInfo.USER_ID})
this.setData({
totalScore: resData.totalScore
})
},
logOut() {
Dialog.confirm({
title: '提示',
message: '确认退出登陆吗?',
}).then(() => {
app.globalData.userInfo = {}
wx.reLaunch({
url: '/pages/login/login'
})
}).catch(() => {
})
}
})

View File

@ -0,0 +1,9 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-icon": "@vant/weapp/icon/index",
"van-dialog": "@vant/weapp/dialog/index"
},
"navigationBarTitleText": "我的",
"navigationBarBackgroundColor": "#257cff"
}

View File

@ -0,0 +1,65 @@
<view>
<view class="bgclore"></view>
<view class="container">
<view class="my-banner">
<view class="image">
<van-image width="100%" height="200rpx" src="/assets/images/mine/mybg.png"/>
</view>
<text class="username">{{userInfo.USERNAME}}</text>
</view>
</view>
<view class="my-container">
<navigator url="/pages/mine/aboutus/aboutus" hover-class="none">
<view class="list-wrap">
<view class="list-wrap-img">
<van-icon size="20px" name="/assets/images/mine/ico1.png"/>
</view>
<view class="list-wrap-info">
<view>关于我们</view>
<view>
<van-icon name="arrow" color="#999"/>
</view>
</view>
</view>
</navigator>
<navigator url="/pages/mine/survey/survey" hover-class="none">
<view class="list-wrap">
<view class="list-wrap-img">
<van-icon size="20px" name="/assets/images/mine/ico3.png"/>
</view>
<view class="list-wrap-info">
<view>调查问卷</view>
<view>
<van-icon name="arrow" color="#999"/>
</view>
</view>
</view>
</navigator>
<navigator url="/pages/mine/changePassword/changePassword" hover-class="none">
<view class="list-wrap">
<view class="list-wrap-img">
<van-icon size="20px" name="/assets/images/mine/ico2.png"/>
</view>
<view class="list-wrap-info">
<view>修改密码</view>
<view>
<van-icon name="arrow" color="#999"/>
</view>
</view>
</view>
</navigator>
<view class="list-wrap" bind:tap="logOut">
<view class="list-wrap-img">
<van-icon size="20px" name="/assets/images/mine/ico5.png"/>
</view>
<view class="list-wrap-info">
<view>退出登录</view>
<view>
<van-icon name="arrow" color="#999"/>
</view>
</view>
</view>
</view>
<van-dialog id="van-dialog" />
</view>

View File

@ -0,0 +1,67 @@
.bgclore {
width: 100%;
height: 100%;
background: #f9f9f9;
position: absolute;
z-index: -2;
}
.my-banner {
width: 100%;
height: 100rpx;
position: relative;
padding: 40rpx;
box-sizing: border-box;
}
.my-banner .image {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: -1;
}
.my-banner .username {
font-size: 36rpx;
color: #ffffff;
display: block;
font-weight: bold;
margin-bottom: 10rpx;
text-align: center;
}
.my-container {
width: 100%;
background: #ffffff;
padding: 20rpx 40rpx;
margin-top: 120rpx;
box-sizing: border-box;
}
.list-wrap {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 40rpx 0rpx;
/* border-bottom: 1px solid #eeeeee; */
}
.list-wrap .list-wrap-img {
width: 40rpx;
height: 40rpx;
margin-right: 20rpx;
vertical-align: middle;
}
.list-wrap-info {
flex: 1;
display: flex;
justify-content: space-between;
font-weight: 500;
}
.fc9 {
color: #999999
}

View File

@ -0,0 +1,133 @@
import {
getUserSurveyInfo,
surveySubmit
} from "../../../api/index";
import Dialog from '@vant/weapp/dialog/dialog'
import debounce from '../../../utils/debounce'
Page({
data: {
time: 0,
count: 0,
current: 0,
CLASS_ID: '',
SURVEY_ID: '',
CORPINFO_ID: '',
topic: [],
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.setData({
CLASS_ID: options.CLASS_ID,
SURVEY_ID: options.SURVEY_ID,
CORPINFO_ID: options.CORPINFO_ID,
})
this.getData()
},
onChange(e) {
const index = e.currentTarget.dataset.index
let detail = e.detail
let varList = this.data.topic
varList[index].ANSWER = detail
this.setData({
topic: [...varList]
})
},
submitPapers() {
Dialog.confirm({
title: '确定要交问卷吗?',
selector: '#nation',
})
.then(() => {
debounce(async () => {
let varList = this.data.topic
await surveySubmit({
questionList: JSON.stringify(varList),
CLASS_ID: this.data.CLASS_ID,
CORPINFO_ID: this.data.CORPINFO_ID,
})
wx.showToast({
title: '问卷提交成功',
mask: true
})
setTimeout(() => {
wx.navigateBack()
}, 1500)
})
}).catch((e) => {
})
},
async getData() {
const resData = await getUserSurveyInfo({
SURVEY_ID: this.data.SURVEY_ID
})
for (let i = 0; i < resData.questionList.length; i++) {
resData.questionList[i].ANSWER = ''
resData.questionList[i].CHECK = ''
}
this.setData({
topic: resData.questionList
})
},
chooseTopic(e) {
const {
type,
check,
itemid
} = e.currentTarget.dataset
let topic = this.data.topic
let current = this.data.current
if (type === 'radio') {
if (topic[current].CHECK === check) {
topic[current].CHECK = ''
} else {
topic[current].CHECK = check
topic[current].ANSWER = itemid
}
this.setData({
topic: [...topic]
})
}
if (type === 'multiple') {
if (topic[current].CHECK) {
let checkedArr = topic[current].CHECK.split(',')
let checkedANSWER = topic[current].ANSWER.split(',')
if (checkedArr.includes(check)) {
checkedArr.splice(checkedArr.indexOf(check), 1)
checkedANSWER.splice(checkedANSWER.indexOf(itemid), 1)
topic[current].CHECK = checkedArr.join(',')
topic[current].ANSWER = checkedANSWER.join(',')
} else {
checkedArr.push(check)
checkedANSWER.push(itemid)
checkedArr.sort()
checkedANSWER.sort()
topic[current].CHECK = checkedArr.join(',')
topic[current].ANSWER = checkedANSWER.join(',')
}
} else {
topic[current].CHECK = check
topic[current].ANSWER = itemid
}
this.setData({
topic: [...topic]
})
}
},
previousQuestion() {
this.setData({
current: --this.data.current
})
},
nextQuestion() {
this.setData({
current: ++this.data.current
})
}
})

View File

@ -0,0 +1,14 @@
{
"usingComponents": {
"van-tag": "@vant/weapp/tag/index",
"van-image": "@vant/weapp/image/index",
"van-count-down": "@vant/weapp/count-down/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-icon": "@vant/weapp/icon/index",
"van-field": "@vant/weapp/field/index",
"van-sticky": "@vant/weapp/sticky/index",
"van-button": "@vant/weapp/button/index",
"van-empty": "@vant/weapp/empty/index"
},
"navigationBarTitleText": "调查问卷"
}

View File

@ -0,0 +1,54 @@
<wxs module="tool" src="../../../utils/util.wxs"></wxs>
<view class="content">
<view class="question-info">
<view class="container">
<van-tag type="primary" size="small">
<block wx:if="{{topic[current].QUESTIONTYPE === '1'}}">单选题</block>
<block wx:if="{{topic[current].QUESTIONTYPE === '2'}}">多选题</block>
<block wx:if="{{topic[current].QUESTIONTYPE === '3'}}">问答题</block>
</van-tag>
<text class="index">{{current + 1}}.</text>
<text class="stem">{{topic[current].QUESTIONDRY}}</text>
<view class="options" wx:if="{{topic[current].QUESTIONTYPE === '1'}}">
<view class="option" bind:tap="chooseTopic" wx:for="{{topic[current].itemList}}" data-type="radio" data-check="{{item.OPTIONDES}}" data-itemid="{{item.ITEM_ID}}">
<!--单选样式-->
<text class="choice {{topic[current].CHECK === item.OPTIONDES ? 'check' : ''}}">{{index + 1}}</text>
<text class="title">{{item.OPTIONDES}}</text>
</view>
</view>
<view class="options" wx:if="{{topic[current].QUESTIONTYPE === '2'}}">
<view class="option" bind:tap="chooseTopic" wx:for="{{topic[current].itemList}}" data-type="multiple" data-check="{{item.OPTIONDES}}" data-itemid="{{item.ITEM_ID}}">
<!--多选样式-->
<text class="choice {{tool.indexOf(topic[current].CHECK,item.OPTIONDES) !== -1 ? 'check' : ''}}">{{index + 1}}</text>
<text class="title">{{item.OPTIONDES}}</text>
</view>
</view>
<view class="options" wx:if="{{topic[current].QUESTIONTYPE === '3'}}">
<view class="option">
<van-field value="{{ topic[current].ANSWER }}" placeholder="请输入答案" border="{{ true }} " bind:change="onChange" data-index="{{ current }}" />
</view>
</view>
</view>
<view class="button">
<van-button color="#d0d0d2" custom-style="color:#000;border-radius: 10rpx;width:{{current === topic.length - 1 ? 630 : 280}}rpx;" size="large" wx:if="{{current !== 0}}" bind:click="previousQuestion">
上一题
</van-button>
<van-button type="info" custom-style="border-radius: 10rpx;width:{{current === 0 ? 630 : 280}}rpx;" size="large" wx:if="{{current !== topic.length - 1}}" bind:click="nextQuestion">
下一题
</van-button>
</view>
</view>
<view class="footer">
<van-button color="linear-gradient(to right, #00ccff, #3676f2)" round size="small" bind:click="submitPapers">
提交问卷
</van-button>
<view class="surplus">
<!-- <van-icon name="../../../assets/images/fenlei.png" /> -->
<view class="ml-10">
<text class="text-blue">{{current + 1}} </text>
<text>/ {{topic.length}}</text>
</view>
</view>
</view>
<van-dialog id="nation"></van-dialog>
</view>

View File

@ -0,0 +1,149 @@
.content{
padding: 20rpx;
}
.top {
border-radius: 20px;
text-align: center;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.van-count-down{
color: #eeecec !important;
font-size: 30rpx !important;
}
.head-text {
position: relative;
z-index: 99;
text-align: center;
font-size: 36rpx;
/* color: whitesmoke; */
bottom: 285rpx;
color: #fff;
font-weight: bold;
}
.question-info {
background-color: white;
padding: 20rpx;
border-radius: 20rpx;
}
.questions {
position: relative;
z-index: 99;
text-align: center;
font-size: 30rpx;
/* color: whitesmoke; */
bottom: 250rpx;
color: #eeecec;
}
.time {
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
z-index: 99;
text-align: center;
font-size: 25rpx;
/* color: whitesmoke; */
bottom: 220rpx;
color: #eeecec;
}
.van-count-down {
color: #eeecec;
font-size: 30rpx;
line-height: normal;
}
.question {
width: 100%;
padding: 20rpx 20rpx;
background: #ffffff;
border-radius: 10rpx;
box-sizing: border-box;
}
.count-down {
display: flex;
align-items: center;
justify-content: center;
background-color: #3676f2;
padding: 20rpx;
border-top: 1px solid rgba(248, 248, 248, 0.2);
text-align: center;
}
.container {
padding: 20rpx 20rpx;
}
.container .index {
padding-left: 10rpx;
}
.container .stem {
padding-left: 10rpx;
line-height: 55rpx;
}
.container .options .option {
margin-top: 50rpx;
}
.container .options .option .choice {
display: inline-block;
border-radius: 50%;
border: 1px solid #f1f1f1;
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
box-shadow: #f1f1f1;
}
.container .options .option .choice.check {
background-color: #cbcbcd;
color: #fff;
}
.container .options .option .title {
margin-left: 20rpx;
}
.container .answer {
background-color: #ecf2fe;
padding: 20rpx;
margin-top: 50rpx;
border-radius: 10rpx;
}
.button {
padding: 40rpx 20rpx;
display: flex;
justify-content: space-between;
}
.footer {
display: flex;
align-items: center;
justify-content: space-between;
position: fixed;
left: 0;
right: 0;
bottom: 0;
box-shadow: 0 -2px 0 0 #f4f4f4;
background-color: #fff;
padding: 15rpx 30rpx;
}
.footer .surplus {
display: flex;
align-items: center;
color: #d5d5d5;
}

View File

@ -0,0 +1,70 @@
// pages/exam/online/online.js
import Dialog from '@vant/weapp/dialog/dialog';
import Toast from '@vant/weapp/toast/toast';
import {
getUserSurveyListPage
} from "../../../api/index";
Page({
/**
* 页面的初始数据
*/
data: {
showCount: 10,
timesOfexamination: 0,
currentPage: 1,
totalPage: 0,
varList: [],
},
goExam(item) {
let info = item.currentTarget.dataset.item
console.log(item.currentTarget.dataset.item);
wx.navigateTo({
url: '/pages/mine/survey/question?SURVEY_ID='+info.SURVEY_ID
+'&CLASS_ID='+info.CLASS_ID
+'&CORPINFO_ID='+info.CORPINFO_ID
,
})
},
async getData() {
let resData = await getUserSurveyListPage({
showCount: this.data.showCount,
currentPage: this.data.currentPage
})
this.setData({
varList: [...this.data.varList, ...resData.varList],
totalPage: resData.page.totalPage
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
this.setData({
showCount: 10,
currentPage: 1,
totalPage: 0,
varList: [],
})
this.getData()
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
this.setData({
currentPage: ++this.data.currentPage
})
if (this.data.totalPage >= this.data.currentPage) {
this.getData()
}
},
})

View File

@ -0,0 +1,11 @@
{
"usingComponents": {
"van-image": "@vant/weapp/image/index",
"van-count-down": "@vant/weapp/count-down/index",
"van-button": "@vant/weapp/button/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-toast": "@vant/weapp/toast/index",
"van-empty": "@vant/weapp/empty/index"
},
"navigationBarTitleText": "调查问卷"
}

View File

@ -0,0 +1,30 @@
<wxs module="util" src="../../../utils/util.wxs"></wxs>
<view class="co">
<view class="my-studies-main" wx:if="{{ varList.length > 0 }}">
<view class="studies_wrap" wx:for="{{ varList }}" wx:key="SURVEY_ID">
<view class="studies_wrap-top">
<view class="studies_wrap_title">班级名称: {{ item.NAME }}</view>
</view>
<view class="studies_wrap-main">
<view class="">行业类型:{{ item.TRAININGTYPE_NAME }}-{{ item.INDUSTRY_END_NAME }}-{{ item.POSTTYPE_NAME }}</view>
<view class="">
培训开始时间:{{ item.START_TIME }}
</view>
<view class="">
培训结束时间:{{ item.END_TIME }}
</view>
</view>
<view class="studies_wrap-bottom">
<van-image width="50rpx" height="50rpx" src="/assets/images/fenlei.png"></van-image>
<view>
<van-button round type="info" size="small" bind:click="goExam" data-item="{{ item }}">立即填写</van-button>
</view>
</view>
</view>
</view>
<view wx:else>
<van-empty description="暂无更多" />
</view>
</view>
<van-dialog id="myDialog"></van-dialog>
<van-toast id="van-toast" />

View File

@ -0,0 +1,62 @@
.co {
min-height: 100vh;
}
.my-studies-main {
box-sizing: border-box;
padding: 20rpx;
}
.studies_wrap-top {
width: 100%;
display: flex;
justify-content: space-between;
padding: 20rpx 0;
}
.studies_wrap {
width: 100%;
padding: 0 20rpx;
background: #ffffff;
border-radius: 10rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
}
.studies_wrap_title {
font-weight: bold;
font-size: 30rpx;
}
.studies_wrap_state {
font-size: 30rpx;
flex-basis: 130rpx;
margin-left: 20rpx;
}
.studies_wrap-main {
border-top: 1px solid #eee;
line-height: 50rpx;
margin-top: 10rpx;
font-size: 28rpx;
color: #666;
}
.fcb {
margin-top: 2rpx;
margin-left: 15rpx;
color: #3377ff;
}
.fcd {
margin-top: 2rpx;
margin-left: 15rpx;
color: #666;
}
.studies_wrap-bottom {
width: 100%;
display: flex;
border-top: 1px solid #eee;
padding: 20rpx 0;
margin-top: 10rpx;
font-size: 28rpx;
color: #999;
justify-content: space-between;
align-items: center;
}
.flex {
display: flex;
align-items: center;
}

164
pages/photo/collection.js Normal file
View File

@ -0,0 +1,164 @@
import {
getHeadPhoto,
updateUserIdFile,
faceRecognition
} from "../../api/index";
import {
FILEPATHPRE
} from "../../utils/util"
import Dialog from '@vant/weapp/dialog/dialog';
const app = getApp()
Page({
data: {
capture: ['camera'],
uploadMsg: '上传图片',
FILEPATHPRE: FILEPATHPRE,
filePath: '',
EXAMFACE: false,
message: '照片要求人像清晰神态自然无明显畸变。头部占照片尺寸2/3纯色背景无边框照片尺寸为二寸35*49毫米413*578像素)'
},
afterRead(event) {
const {
file
} = event.detail;
// 正常的头像上传
if (!this.data.EXAMFACE) {
updateUserIdFile({
filePath: file.url,
}).then((resData) => {
if (resData.code == 0) {
app.globalData.userInfo.AUTHENTICATION = '1'
this.getData()
Dialog.alert({
message: '您已成功认证',
selector: '#myDialog',
})
.then(() => {
wx.navigateBack()
});
}
}).catch((e) => {
wx.showToast({
title: '人像比对不通过,请重新提交审核',
mask: false,
icon: error
})
})
} else {
// 考试前人脸识别
faceRecognition({
filePath: file.url,
formData:{
STUDENT_ID: this.data.STUDENT_ID
}
}).then((resData)=>{
if (resData.code == 0) {
Dialog.alert({
message: '您已成功认证,返回立即考试',
selector: '#myDialog',
})
.then(() => {
//当前页面
let pages = getCurrentPages();
//上一页面
let prevPage = pages[pages.length-2];
wx.navigateBack({
delta: 1,
success: function () {
if(prevPage != null && prevPage.route == 'pages/exam/online/online'){
let dataInfo = prevPage.data.dataInfo
dataInfo.EXAM_FACE_PATH = true
prevPage.photoResult(dataInfo);
}
}
})
});
} else {
Dialog.alert({
message: '比对失败,请重新比对',
selector: '#myDialog',
})
.then(() => {
});
}
})
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
console.log(options);
if (!options.STUDENT_ID) {
this.getData()
} else {
this.setData({
STUDENT_ID: options.STUDENT_ID,
EXAMFACE: true,
uploadMsg: '人脸认证',
message: '点击“人脸认证”按钮进行人脸识别核验,务必本人进行人脸识别。'
})
}
},
async getData() {
const resData = await getHeadPhoto({});
if (resData.pd.AUTHENTICATION == '1') {
this.setData({
filePath: FILEPATHPRE + resData.pd.PORTRAIT
})
this.setData({
uploadMsg: '已认证,重新上传'
})
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

View File

@ -0,0 +1,10 @@
{
"usingComponents": {
"van-uploader": "@vant/weapp/uploader/index",
"van-button": "@vant/weapp/button/index",
"van-image": "@vant/weapp/image/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-toast": "@vant/weapp/toast/index"
},
"navigationBarTitleText": "人像采集"
}

View File

@ -0,0 +1,17 @@
<view class="content">
<view class="te-info">
{{ message }}
</view>
<view class="img-stu" wx:if="{{!EXAMFACE}}">
<van-image width="480rpx" height="830rpx" src="{{ filePath }}" />
</view>
<view wx:else class="img-face">
<van-image round width="15rem" height="15rem" fit="fill" src="/assets/images/photo/rx.png" />
</view>
<view class="img-btn">
<van-uploader max-count="1" bind:after-read="afterRead" capture="{{capture}}">
<van-button icon="photo" type="primary">{{uploadMsg}}</van-button>
</van-uploader>
</view>
<van-dialog id="myDialog"></van-dialog>
</view>

View File

@ -0,0 +1,26 @@
.content{
background-color: #fff;
min-height: 100vh;
}
.te-info {
padding: 20rpx;
position: relative;
}
.img-stu {
margin-top: 50rpx;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.img-face{
margin-top: 120rpx;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.img-btn {
position: absolute;
margin-top: 950rpx;
left: 50%;
transform: translateX(-50%);
}

199
pages/sign/sign.js Normal file
View File

@ -0,0 +1,199 @@
import {
getHeadPhoto,
updateUserIdFile,
faceRecognition,
updUserSign
} from "../../api/index";
import {
FILEPATHPRE
} from "../../utils/util"
import Dialog from '@vant/weapp/dialog/dialog';
const app = getApp()
Page({
data: {
capture: ['camera'],
uploadMsg: '上传签字',
FILEPATHPRE: FILEPATHPRE,
filePath: '',
EXAMFACE: false,
},
afterRead(event) {
const {
file
} = event.detail;
// 正常的头像上传
if (!this.data.EXAMFACE) {
updateUserIdFile({
filePath: file.url,
}).then((resData) => {
if (resData.code == 0) {
app.globalData.userInfo.AUTHENTICATION = '1'
this.getData()
Dialog.alert({
message: '您已成功认证',
selector: '#myDialog',
})
.then(() => {
wx.navigateBack()
});
}
}).catch((e) => {
wx.showToast({
title: '人像比对不通过,请重新提交审核',
mask: false,
icon: error
})
})
} else {
// 考试前人脸识别
faceRecognition({
filePath: file.url,
formData:{
STUDENT_ID: this.data.STUDENT_ID
}
}).then((resData)=>{
if (resData.code == 0) {
Dialog.alert({
message: '您已成功认证,返回立即考试',
selector: '#myDialog',
})
.then(() => {
//当前页面
let pages = getCurrentPages();
//上一页面
let prevPage = pages[pages.length-2];
wx.navigateBack({
delta: 1,
success: function () {
if(prevPage != null && prevPage.route == 'pages/exam/online/online'){
let dataInfo = prevPage.data.dataInfo
dataInfo.EXAM_FACE_PATH = true
prevPage.photoResult(dataInfo);
}
}
})
});
} else {
Dialog.alert({
message: '比对失败,请重新比对',
selector: '#myDialog',
})
.then(() => {
});
}
})
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
console.log(options);
if (!options.STUDENT_ID) {
this.getData()
} else {
this.setData({
STUDENT_ID: options.STUDENT_ID,
EXAMFACE: true,
uploadMsg: '上传签字'
})
}
},
userSignShowChange(){
this.setData({
userSignShow:!this.data.userSignShow
})
},
async getData() {
const resData = await getHeadPhoto({});
if (resData.pd.SIGNATURE_FILE_PATH != null) {
this.setData({
filePath: FILEPATHPRE + resData.pd.SIGNATURE_FILE_PATH
})
this.setData({
uploadMsg: '已签字,重新上传'
})
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
},
openSign() {
this.setData({
userSignShow: true
})
},
fnInput1(event) {
// 签字图片 event.detail
updUserSign({
filePath: event.detail,
formData:{
USER_ID: app.globalData.userInfo.USER_ID
}
}).then((resData) => {
if(resData.code != 0) {
wx.showToast({
title: '请重签',
mask: false,
icon:error
})
}else {
wx.showToast({
title: '签字已经更新',
mask: false
})
this.getData();
}
}).catch((e) =>{
console.log(e);
})
},
})

11
pages/sign/sign.json Normal file
View File

@ -0,0 +1,11 @@
{
"usingComponents": {
"van-uploader": "@vant/weapp/uploader/index",
"van-button": "@vant/weapp/button/index",
"van-image": "@vant/weapp/image/index",
"van-dialog": "@vant/weapp/dialog/index",
"van-toast": "@vant/weapp/toast/index",
"sign": "/components/sign/sign"
},
"navigationBarTitleText": "签字采集"
}

17
pages/sign/sign.wxml Normal file
View File

@ -0,0 +1,17 @@
<view class="content">
<view class="te-info">
签字要求字体清晰,横向排版,在画布中心签字。勿乱涂乱画、大小不一、签字不全等。此签字仅在档案中使用。
</view>
<view class="img-stu" wx:if="{{!EXAMFACE}}">
<van-image width="480rpx" height="230rpx" src="{{ filePath }}" />
</view>
<view wx:else class="img-face">
<van-image round width="15rem" height="15rem" fit="fill" src="/assets/images/photo/rx.png" />
</view>
<view class="img-btn">
<van-button icon="photo" type="primary" bindtap="openSign">{{uploadMsg}}</van-button>
</view>
<sign show="{{userSignShow}}" bindsubCanvas="fnInput1" bindhideModal="userSignShowChange" data-key="userSign"></sign>
<van-dialog id="myDialog"></van-dialog>
<van-toast id="van-toast" />
</view>

26
pages/sign/sign.wxss Normal file
View File

@ -0,0 +1,26 @@
.content{
background-color: #fff;
min-height: 100vh;
}
.te-info {
padding: 20rpx;
position: relative;
}
.img-stu {
margin-top: 350rpx;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.img-face{
margin-top: 120rpx;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.img-btn {
position: absolute;
margin-top: 950rpx;
left: 50%;
transform: translateX(-50%);
}

62
project.config.json Normal file
View File

@ -0,0 +1,62 @@
{
"description": "项目配置文件详见文档https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"bundle": false,
"userConfirmedBundleSwitch": false,
"urlCheck": true,
"scopeDataCheck": false,
"coverView": true,
"es6": true,
"postcss": true,
"compileHotReLoad": false,
"lazyloadPlaceholderEnable": false,
"preloadBackgroundData": false,
"minified": true,
"autoAudits": false,
"newFeature": false,
"uglifyFileName": false,
"uploadWithSourceMap": true,
"useIsolateContext": true,
"nodeModules": false,
"enhance": true,
"useMultiFrameRuntime": true,
"useApiHook": true,
"useApiHostProcess": true,
"showShadowRootInWxmlPanel": true,
"enableEngineNative": false,
"minifyWXSS": true,
"showES6CompileOption": false,
"minifyWXML": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./"
}
],
"ignoreDevUnusedFiles": false,
"useStaticServer": true,
"checkInvalidKey": true,
"disableUseStrict": false,
"useCompilerPlugins": false,
"condition": false
},
"compileType": "miniprogram",
"libVersion": "2.26.1",
"appid": "wx0c79c2adb6ae5f04",
"projectname": "miniprogram-92",
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}

Some files were not shown because too many files have changed in this diff Show More