87 Commits

Author SHA1 Message Date
qsh
a684d255d2 sc 2025-06-19 18:05:43 +08:00
qsh
70fe0f0c42 sc 2025-06-19 16:02:14 +08:00
qsh
62896b197d sc 2025-06-19 11:16:24 +08:00
qsh
9b677ade15 sc 2025-06-18 16:20:59 +08:00
qsh
4bd08bde70 sc 2025-06-18 16:01:08 +08:00
qsh
e889c92d35 sc 2025-06-11 17:16:41 +08:00
qsh
7442289a87 sc 2025-06-11 17:16:12 +08:00
qsh
d70a0141cc sc 2025-03-17 18:55:44 +08:00
qsh
459baca3f8 sc 2025-03-17 17:27:11 +08:00
f5c0df688c Merge pull request '样式调整' (#41) from dev-qsh into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/41
2024-02-02 17:13:02 +08:00
qsh
38cc93cba4 样式调整 2024-02-02 17:12:38 +08:00
zcx
ccef999bbe Merge pull request '失效' (#40) from dev-zcx into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/40
2024-02-02 16:27:06 +08:00
zcx
589eec1d80 失效 2024-02-02 16:26:21 +08:00
zcx
242744c0f9 Merge pull request 'dev-zcx' (#38) from dev-zcx into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/38
2024-02-02 16:24:24 +08:00
zcx
e67e1edf12 助力 2024-02-02 14:16:26 +08:00
zcx
8f50f42f8c 助力 2024-02-02 14:05:43 +08:00
zcx
65149c38cd 助力 2024-02-02 13:55:15 +08:00
zcx
c26e306b3a 助力 2024-02-02 13:51:36 +08:00
6141270437 Merge pull request '添加抖音小程序配置' (#35) from dev-qsh into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/35
2024-01-30 15:05:23 +08:00
qsh
074b53f307 添加抖音小程序 2024-01-30 15:03:55 +08:00
qsh
ab05529015 活动 2024-01-27 21:21:24 +08:00
zcx
9e24edad28 活动接口 2024-01-26 20:50:31 +08:00
zcx
67b3e63de9 活动接口 2024-01-26 20:41:25 +08:00
qsh
056ca965b3 抽奖 2024-01-25 08:59:04 +08:00
4fd6a21f35 Merge pull request 'dev-hxf' (#33) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/33
2023-11-07 20:58:25 +08:00
7b1db47383 提交 2023-11-07 20:50:15 +08:00
79236493e6 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-10-30 20:29:32 +08:00
59c49bfdf2 提交 2023-10-30 20:29:18 +08:00
110e9d4adc Merge pull request '屏蔽Ios支付' (#32) from dev-qsh into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/32
2023-10-25 20:33:06 +08:00
qsh
b533581a5d 屏蔽Ios支付 2023-10-25 20:30:58 +08:00
ac8acdccda Merge pull request 'dev-hxf' (#31) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/31
2023-10-17 12:03:51 +08:00
f4b6f96649 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-10-17 12:01:11 +08:00
9ba3f6ed48 提交 2023-10-17 12:00:58 +08:00
253ab2a80d Merge pull request 'dev-hxf' (#30) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/30
2023-10-10 18:07:01 +08:00
bfdbd3f7f3 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-10-10 17:56:31 +08:00
e3544ee06e 提交 2023-10-10 17:56:20 +08:00
7e15974ea6 Merge pull request 'dev-hxf' (#29) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/29
2023-09-21 16:34:55 +08:00
46972d5bff Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-09-21 16:31:30 +08:00
851319e24c 提交 2023-09-21 16:30:36 +08:00
19616d56c5 Merge pull request 'dev-hxf' (#28) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/28
2023-09-20 22:32:22 +08:00
89c4b2148e 提交 2023-09-20 22:23:21 +08:00
e68a422cc8 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-09-20 22:18:41 +08:00
2e93ad93e9 提交 2023-09-20 22:18:19 +08:00
c783ff969d Merge pull request 'dev-hxf' (#27) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/27
2023-09-18 21:44:49 +08:00
4526430a38 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-09-18 21:43:29 +08:00
3a0545852f 提交 2023-09-18 21:42:50 +08:00
0410e5dda9 Merge pull request 'dev-hxf' (#26) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/26
2023-09-17 23:53:26 +08:00
0c230fa5f1 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-09-17 23:49:59 +08:00
ded28b62fb 提交 2023-09-17 23:49:42 +08:00
6834b3f9fe Merge pull request 'dev-hxf' (#25) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/25
2023-09-17 13:23:02 +08:00
3379a9b18e Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-09-17 13:19:26 +08:00
9e871e4079 提交 2023-09-17 13:18:59 +08:00
728fefac03 Merge pull request 'dev-hxf' (#24) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/24
2023-09-07 09:55:25 +08:00
bf05f771f7 提交 2023-09-07 09:47:38 +08:00
287f123ac7 提交 2023-09-06 00:28:46 +08:00
89c72e336b Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-08-30 23:15:55 +08:00
135bcc71ee 提交 2023-08-30 23:15:41 +08:00
a09ef61e2f Merge pull request 'dev-hxf' (#23) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/23
2023-08-29 00:30:36 +08:00
d88f92a893 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-08-29 00:24:59 +08:00
dc340c7f4d 提交 2023-08-29 00:24:24 +08:00
0c6182e6f5 Merge pull request '提交' (#22) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/22
2023-08-28 02:07:39 +08:00
f762ca430d 提交 2023-08-28 02:02:46 +08:00
37c5de0899 Merge pull request '科一真实考场' (#21) from dev-qsh into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/21
2023-08-27 02:38:45 +08:00
qsh
04a4a4781d 科一真实考场 2023-08-27 02:37:34 +08:00
741b5a1d29 Merge pull request '科一真实考场' (#20) from dev-qsh into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/20
2023-08-26 20:45:02 +08:00
qsh
f36cffdd37 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-qsh 2023-08-26 20:42:47 +08:00
qsh
7db9e68e77 真实考场科目1 2023-08-26 20:42:42 +08:00
d82a84798c Merge pull request 'dev-hxf' (#19) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/19
2023-08-26 14:15:26 +08:00
4bfce94c24 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-08-26 14:10:34 +08:00
c3e6002ca3 提交 2023-08-26 14:10:16 +08:00
fa6665d9f6 Merge pull request 'dev-hxf' (#18) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/18
2023-08-25 15:11:59 +08:00
77de5d5d6e Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-08-25 15:07:01 +08:00
9e4b78882e 提交 2023-08-25 15:06:46 +08:00
5640ef7f36 Merge pull request 'dev-hxf' (#17) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/17
2023-08-24 17:08:57 +08:00
d36b01a69f Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-08-24 17:07:58 +08:00
8a1d49b47f 提交 2023-08-24 17:07:43 +08:00
0b39b49a5d Merge pull request 'dev-hxf' (#16) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/16
2023-08-24 16:59:28 +08:00
9afe858077 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-08-24 16:58:45 +08:00
5f6646ae4e 提交 2023-08-24 16:58:38 +08:00
3c137e8025 Merge pull request 'dev-hxf' (#15) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/15
2023-08-24 16:55:38 +08:00
3c4e11799b 提交 2023-08-24 16:53:11 +08:00
97547afc4d 提交 2023-08-24 15:26:02 +08:00
4c4bd6236d Merge pull request '修改' (#14) from dev-qsh into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/14
2023-08-24 15:19:47 +08:00
qsh
49abbc764b 修改 2023-08-24 15:18:49 +08:00
91b90c809e Merge pull request 'dev-hxf' (#13) from dev-hxf into master
Reviewed-on: http://114.55.169.15:3000/huxiaofeng666/jwl-applet/pulls/13
2023-08-23 21:45:53 +08:00
1596959583 Merge branch 'master' of http://114.55.169.15:3000/huxiaofeng666/jwl-applet into dev-hxf 2023-08-23 21:44:22 +08:00
36f8a9b2cc 提交 2023-08-23 21:42:21 +08:00
155 changed files with 15525 additions and 2087 deletions

View File

@@ -5,7 +5,9 @@ VITE_APP_TITLE = 金武联驾校
VITE_APP_ENV = 'development'
# 金武联驾校/开发环境
VITE_APP_BASE_API = 'http://118.31.23.45:8888/'
VITE_APP_BASE_API = 'https://jwl.ahduima.com/'
# VITE_APP_BASE_API = 'http://tk-api.ahfkbg.com/'
#
VITE_WEB_BASE_URL = 'http://118.31.23.45:8888/'
VITE_WEB_BASE_URL = 'https://jwl.ahduima.com'
# 资源地址
VITE_RESOURSE_URL = 'http://huodong.ahduima.com'

View File

@@ -5,7 +5,10 @@ VITE_APP_TITLE = 金武联驾校
VITE_APP_ENV = 'production'
# 金武联驾校/开发环境
VITE_APP_BASE_API = 'https://i.equ-tech.com/zongheng-api/'
VITE_APP_BASE_API = 'https://jwl.ahduima.com/'
#
VITE_WEB_BASE_URL = 'https://i.equ-tech.com/zongheng'
VITE_WEB_BASE_URL = 'https://jwl.ahduima.com'
# 资源地址
VITE_RESOURSE_URL = 'http://huodong.ahduima.com'

View File

@@ -4,8 +4,10 @@
"scripts": {
"dev:h5": "uni",
"dev": "uni -p mp-weixin",
"dev:dy": "uni -p mp-toutiao",
"build:h5": "uni build",
"build": "uni build -p mp-weixin",
"build:dy": "uni build -p mp-toutiao",
"build-test:mp-weixin": "uni --mode test -p mp-weixin"
},
"dependencies": {
@@ -14,6 +16,7 @@
"@dcloudio/uni-components": "3.0.0-alpha-3060420220922001",
"@dcloudio/uni-h5": "3.0.0-alpha-3060420220922001",
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-3060420220922001",
"@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3060420220922001",
"jsencrypt-plus": "^0.1.0",
"pinia": "2.0.36",
"pinia-plugin-persist-uni": "^1.2.0",

28
project.config.json Normal file
View File

@@ -0,0 +1,28 @@
{
"appid": "wx24c1b58020a5ce66",
"compileType": "miniprogram",
"libVersion": "3.3.3",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"coverView": true,
"es6": true,
"postcss": true,
"minified": true,
"enhance": true,
"showShadowRootInWxmlPanel": true,
"packNpmRelationList": [],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}

View File

@@ -0,0 +1,7 @@
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "jwl-applet",
"setting": {
"compileHotReLoad": true
}
}

View File

@@ -1,16 +1,21 @@
<script>
import useUserStore from '@/jtools/store/user'
import useQuestionStore from '@/jtools/store/question' //引入store
import storage from './jtools/storage'
export default {
onLaunch: function () {
onLaunch: function (options) {
// 如果是二维码扫描过来的需要保存公司id
if (options.query?.scene) {
storage.set('companyId', options.query?.scene)
}
useUserStore().queryVipList()
if(useUserStore().isLogin) {
useQuestionStore().getOrderQuestion('1')
if (useUserStore().isLogin) {
useUserStore().getUserInfo()
useUserStore().searchUserVip()
}
},
onShow: function () {
useQuestionStore().getAllQuestion()
console.log('App Show')
},
onHide: function () {
@@ -23,4 +28,8 @@ export default {
/*每个页面公共css */
@import "uni_modules/uview-plus/index.scss";
@import "static/style/index.scss";
button::after {
border: none;
}
</style>

View File

@@ -140,8 +140,8 @@ export default {
.cu-bar {
width: 100%;
.content {
// width: 350rpx;
display: flex;
width: 350rpx;
// display: flex;
flex-direction: row;
flex: 1;
align-items: center;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,95 @@
## 使用方式
``` javascript
<yan-qr />
```
## 属性说明
|属性名 |类型 | 默认值 |说明 |
|-- |-- |-----------|-- |
|canvasId |String | 'qrcode' |canvas-id |
|text |String | 'hello' |二维码内容 |
|size |Number | 340 |单位是px |
|margin |Number | 0 |边距 |
|level |String | 'L' |二维码解析度L/M/Q/H |
|fColor |String | '#000000' |二维码颜色 |
|bColor |String | '#ffffff' |二维码背景颜色 |
|fileType |String | 'png' |二维码图片类型 |
## 示例代码
``` javascript
<template>
<view>
<view>
<view>
<view>需要转换的文本:</view>
<textarea v-model="content" @blur="inputText" placeholder="请在这里输入" />
</view>
</view>
二维码
<view>
<yan-qr :filePath.sync="filePath" :text="text" :margin="20" />
</view>
二维码图片地址
<view>
<textarea v-model="filePath" disabled />
</view>
<button @click='btn'>生成二维码</button>
</view>
</template>
<script>
export default {
data() {
return {
qrShow: false,
content: '',
filePath: '',
text: ''
}
},
watch: {
filePath() {
console.log(this.filePath);
}
},
methods: {
//*获取文本框内容*//
inputText: function(e) {
this.content = e.detail.value
},
//*按钮*//
btn: function() {
if (this.content == '') {
uni.showToast({ //显示对话框
title: "请输入文本",
icon: 'none',
duration: 1000,
})
} else {
this.text = this.content
}
},
}
}
</script>
<style>
textarea {
border: 1px solid #000000;
width: 98%;
}
button {
width: 80%;
margin-top: 180rpx;
border-radius: 25px;
color: aliceblue;
background-color: #55aaff;
}
</style>
```

View File

@@ -0,0 +1,115 @@
<template>
<view>
<canvas :canvas-id="canvasId" v-show="qrShow" :style="qrShowStyle" />
</view>
</template>
<script>
import uQRCode from './qrcode.js'
export default {
props: {
canvasId: {
type: String,
default: 'qrcode' //canvas-id
},
text: {
type: String,
default: 'hello' //二维码内容
},
size: {
type: Number,
default: 150 //二维码大小
},
margin: {
type: Number,
default: 0 //二维码边距
},
level: {
type: String,
default: 'L' //二维码质量L/M/Q/H
},
bColor: {
type: String,
default: '#ffffff' //二维码背景颜色
},
fColor: {
type: String,
default: '#000000' //二维码颜色
},
fileType: {
type: String,
default: 'png' //二维码图片类型
}
},
data() {
return {
qrShow: false,
qrShowStyle: {
"width": "150px",
"height": "150px",
}
}
},
watch: {
text(newVal, oldVal) {
this.onQrFun()
}
},
mounted() {
this.onQrFun()
},
methods: {
onQrFun() {
this.qrShow = this.text != ''
if(this.qrShow){
this.qrShowStyle.width = this.size+"px"
this.qrShowStyle.height = this.size+"px"
let level;
switch (this.level) {
case "M":
case "m":
level = uQRCode.errorCorrectLevel.M
break;
case "Q":
case "q":
level = uQRCode.errorCorrectLevel.Q
break;
case "H":
case "h":
level = uQRCode.errorCorrectLevel.H
break;
default:
level = uQRCode.errorCorrectLevel.L
break;
}
uQRCode.make({
canvasId: this.canvasId,
componentInstance: this,
text: this.text,
size: this.size,
margin: this.margin,
backgroundColor: this.bColor,
foregroundColor: this.fColor,
fileType: this.fileType,
errorCorrectLevel: level,
success: res => {}
})
setTimeout(() => {
uni.canvasToTempFilePath({
canvasId: this.canvasId,
success: (res) => {
// 在H5平台下tempFilePath 为 base64
this.$emit("update:filePath", res.tempFilePath);
}
}, this);
}, 600)
}
}
}
}
</script>
<style>
</style>

118
src/jtools/api/activity.js Normal file
View File

@@ -0,0 +1,118 @@
import request from '../request/index.js';
//查询活动列表
export function queryActivityList(data) {
return request({
url: 'activity/applet/activity/list',
method: 'get',
data,
noToken: true
});
}
//查询活动详情
export function queryActivityDetail(data) {
return request({
url: 'activity/applet/activity/detail',
method: 'get',
data,
noToken: true
});
}
//查询抽奖次数
export function queryLuckyNum(data) {
return request({
url: 'activity/applet/activity/lucky/num',
method: 'get',
data,
noToken: true
});
}
//查询中奖结果
export function queryLuckyResult(data) {
return request({
url: 'activity/applet/activity/lucky/result',
method: 'get',
data,
noToken: true
});
}
//录入中奖结果
export function saveWinner(data) {
return request({
url: 'activity/applet/activity/winner/save',
method: 'POST',
data,
noToken: true
});
}
//核销
export function receiveWinner(data) {
return request({
url: 'activity/applet/activity/winner/receive',
method: 'POST',
data,
noToken: true
});
}
//查询中奖记录
export function getLuckyRecord(data) {
return request({
url: 'activity/applet/activity/lucky/record',
method: 'get',
data,
noToken: true
});
}
//查询中奖记录
export function canRecieveGift(data) {
return request({
url: 'activity/applet/activity/receive/user',
method: 'get',
data,
noToken: true
});
}
//查询中奖信息
export function queryWinnerInfo(data) {
return request({
url: 'activity/applet/activity/winner/info',
method: 'get',
data,
noToken: true
});
}
//查询助力信息
export function queryHelpInfo(data) {
return request({
url: 'activity/applet/activity/help/info',
method: 'get',
data,
noToken: true
});
}
//保存助力信息
export function saveHelpInfo(data) {
return request({
url: 'activity/applet/activity/help/save',
method: 'post',
data,
noToken: true
});
}
//微信登录获取手机号
export function wxLogin(data) {
return request({
url: 'activity/applet/activity/wx/login',
method: 'post',
data,
noToken: true
});
}

View File

@@ -7,4 +7,21 @@ export function getAliCompanyInfo(data) {
data,
noToken: true
});
}
export function getCarTypeList(data) {
return request({
url: 'driver-api/tdCar/list',
method: 'GET',
data,
noToken: true
});
}
export function addInfo(data) {
return request({
url: 'chaoyuan-api/driver/addInfo',
method: 'POST',
data
});
}

9
src/jtools/api/pay.js Normal file
View File

@@ -0,0 +1,9 @@
import request from '../request/index.js';
export function prePay(data) {
return request({
url: 'driver-api/applet/pay/prepay',
method: 'POST',
data,
});
}

View File

@@ -1,11 +1,11 @@
import request from '../request/index.js';
export function queryQuestion(data) {
return request({
url: 'driver-api/tdQuestion/queryQuestion',
method: 'POST',
data,
noToken: true
});
}
@@ -14,6 +14,7 @@ export function questionCategory(data) {
url: 'driver-api/tdQuestion/questionCategory',
method: 'POST',
data,
noToken: true
});
}
@@ -21,7 +22,7 @@ export function getTestQuestion(data) {
return request({
url: 'driver-api/tdQuestion/getTestQuestion',
method: 'POST',
data,
data
});
}
@@ -29,7 +30,7 @@ export function submitTest(data) {
return request({
url: 'driver-api/tdQuestionTest/testSubmit',
method: 'POST',
data,
data
});
}
@@ -37,23 +38,73 @@ export function testTotal(data) {
return request({
url: 'driver-api/tdQuestionTest/testTotal',
method: 'POST',
data,
data
});
}
//获取配置
export function querySysConfigList(carTypeId,configKey) {
export function querySysConfigList(carTypeId, configKey) {
return request({
url: 'driver-api/tdSysConfigList/querySysConfigList?configKey='+configKey+'&carTypeId='+carTypeId,
url: 'driver-api/tdSysConfigList/querySysConfigList?configKey=' + configKey + '&carTypeId=' + carTypeId,
method: 'GET',
noToken: true
});
}
//获取配置
export function querySysConfig(carTypeId, configKey) {
return request({
url: 'driver-api/tdSysConfig/queryConfigByKey?configKey=' + configKey + '&carTypeId=' + carTypeId,
method: 'GET',
noToken: true
});
}
//获取项目列表 (考试项目和基础操作)
export function queryProjectList(data) {
return request({
url: 'driver-api/tdTestProject/queryProjectList',
method: 'POST',
data,
method: 'POST',
data,
noToken:true
});
}
//
//获取专项题目数量
export function querySpecialNum(data) {
return request({
url: 'driver-api/tdQuestion/querySpecialNum',
method: 'POST',
data,
noToken:true
});
}
//获取题库版本
export function getVersion(carTypeId) {
return request({
url: '/driver-api/tdQuestionVersion/currentVersion?carTypeId='+carTypeId,
method: 'GET',
noToken:true
});
}
//获取题目ID
export function queryQuestionId(data) {
return request({
url: '/driver-api/tdQuestion/queryQuestionId',
method: 'POST',
data,
noToken:true
});
}
//获取模拟考试ID
export function getTestQuestionId(data) {
return request({
url: '/driver-api/tdQuestion/getTestQuestionId',
method: 'POST',
data,
noToken:true
});
}

View File

@@ -4,7 +4,7 @@ export function queryVip(data) {
return request({
url: 'driver-api/tdMember/queryUserMember',
method: 'POST',
data,
data
});
}
@@ -13,5 +13,6 @@ export function getVipList(data) {
url: 'driver-api/tdMember/queryMember',
method: 'POST',
data,
noToken: true
});
}
}

159
src/jtools/pay/index.js Normal file
View File

@@ -0,0 +1,159 @@
import request from '../request/index.js';
// #ifdef H5
// import wxsdk from '@/jtools/wechat/sdk'
// #endif
// import wechat from '@/jtools/wechat/wechat'
import $platform from '@/jtools/platform';
import {prePay} from '@/jtools/api/pay'
/**
* 支付
*
* @param {String} payment = ['wechat','alipay','wallet'] - 支付方式
* @param {Object} order = {} - 订单详情
* @param {String} orderType = ['goods','recharge'] - 订单类型
*/
export default class JtoolsPay {
// wxOfficialAccount wxMiniProgram App H5
// wechat 公众号JSSDK支付 小程序支付 微信开放平台支付 H5网页支付
// alipay 复制网址 复制网址 支付宝开放平台支付 直接跳转链接
// wallet v v v v
constructor(payment, order, orderType) {
this.payment = payment;
this.order = order;
this.orderType = orderType;
this.platform = $platform.get();
let payMehod = this.getPayMethod();
payMehod();
}
getPayMethod() {
var payMethod = {
'wxMiniProgram': {
'wechat': () => {
this.wxMiniProgramPay()
},
},
'App': {
'wechat': () => {
this.wechatPay()
},
'alipay': () => {
this.aliPay()
},
},
}
return payMethod[this.platform][this.payment];
}
// 预支付
prepay() {
let that = this;
return new Promise((resolve, reject) => {
const p = $platform.device()
const tradeInfoType = p == 'android' ? 'Android' : p == 'ios' ? 'iOS' : 'Wap'
let params = {
"code":this.order.code,
"description": this.order.description,
"money": this.order.money,
"outTradeNo": this.order.outTradeNo,
"userId": this.order.userId,
"tradeType":'1'
}
if (uni.getStorageSync('openId')) {
params.openId = uni.getStorageSync('openId');
}
prePay(params).then(res => {
console.log('预支付',res);
if (res.code == '0000') {
resolve(res);
}
})
});
}
// 微信小程序支付
async wxMiniProgramPay() {
let that = this;
let result = await this.prepay();
const params = result.data
uni.requestPayment({
provider: 'wxpay',
...{
appId: params.appId, //公众号名称,由商户传入
timeStamp: params.timeStamp, //时间戳自1970年以来的秒数
nonceStr: params.nonceStr, //随机串
package: params.packageVal,
signType: params.signType, //微信签名方式:
paySign: params.paySign, //微信签名
},
success: res => {
console.log(res);
that.payResult('success', result.data.orderPayNo)
},
fail: err => {
console.log('支付取消或者失败:', err);
err.errMsg !== "requestPayment:fail cancel" && that.payResult('fail')
}
});
}
// 支付宝支付
async aliPay() {
let that = this;
let result = await this.prepay();
if (result.code === 1) {
uni.requestPayment({
provider: 'alipay',
orderInfo: result.data.pay_data, //支付宝订单数据
success: res => {
that.payResult('success')
},
fail: err => {
err.errMsg !== "requestPayment:fail cancel" && that.payResult('fail')
}
});
}
}
// 微信支付
async wechatPay() {
let that = this;
let result = await this.prepay();
console.log('微信支付');
if (result.code === 1) {
uni.requestPayment({
provider: 'wxpay',
orderInfo: JSON.parse(result.data.pay_data), //微信订单数据(官方说是string。实测为object)
success: res => {
that.payResult('success')
},
fail: err => {
err.errMsg !== "requestPayment:fail cancel" && that.payResult('fail')
console.log('支付取消或者失败:', err);
}
});
}
}
// 支付结果跳转,success:成功fail:失败
payResult(resultType, orderPayNo) {
const that = this;
let path = 'paySuccess'
uni.navigateTo({
url: path
})
}
}

View File

@@ -29,10 +29,10 @@ function service(options = {}) {
title: res?.data?.message || '请重新登录',
icon: 'none'
});
useUserStore().logout()
useUserStore().logoutWithoutToken()
//请求成功
resolved(res.data);
} else if(res.data.code != '0000') {
} else if(res.data.code != '0000'&&res.data.code !='4001'&&res.data.code != 200) {
uni.showToast({
title: res?.data?.message || '访问出错',
icon: 'none'

View File

@@ -1,38 +1,157 @@
import {
defineStore
} from 'pinia';
import { defineStore } from 'pinia';
import http from '@/jtools/request/index';
import {
queryQuestion
} from '@/jtools/api/question';
import { queryQuestion, getVersion, querySysConfig } from '@/jtools/api/question';
import storage from '@/jtools/storage';
let JSON_SPLIT_LENGTH = 10;
const question = defineStore({
id: 'question',
state: () => ({
currentCartype: storage.get('carType') || '1001',
orderQuestion: [], //顺序做题
currentIndex_subject1:0,//科目一索引 顺序做题
currentIndex_subject4:0,//科目四索引 顺序做题
}),
id: 'question',
state: () => ({
currentCartype: storage.get('carType') || '1001',
currentCarName: storage.get('carName') || '小车C1/C2/C3',
orderQuestion_subject1: [], //科目一顺序做题
orderQuestion_subject4: [], //科目四顺序做题
currentIndex_subject1: 0, //科目一索引 顺序做题
currentIndex_subject4: 0, //科目四索引 顺序做题
curSubject: storage.get('curSubject') || '1',
loading_subject1: false,
loading_subject4: false,
version: storage.get('version') || ''
}),
actions: {
// 获取顺序做题
getOrderQuestion(val) {
queryQuestion({
carTypeId: this.currentCartype,
subject: val
}).then(res => {
if (res.code == '0000') {
this.orderQuestion = res.data
}
})
},
//获取索引
getCurrentIndex(index,val){
this[`currentIndex_subject${val}`]=index
}
}
actions: {
resetStorage() {
this.currentIndex_subject1 = 0;
this.currentIndex_subject4 = 0;
this.curSubject = 0;
storage.remove('curSubject');
storage.remove('wrongList_subject1');
storage.remove('wrongList_subject4');
storage.remove('rightList_subject1');
storage.remove('rightList_subject4');
// this.getAllQuestion()
},
getAllQuestion() {
this.currentCartype = storage.get('carType') || '1001';
getVersion(this.currentCartype).then(resp => {
if (resp.code === '0000') {
querySysConfig(this.currentCartype, 'QuestionBank').then(res => {
const urlList = JSON.parse(res.data.configJson);
const urlOne = urlList.find(item => item.subject == '1').url;
const urlFour = urlList.find(item => item.subject == '4').url;
if (this.version != resp.data) {
this.version = resp.data;
storage.set('version', resp.data);
this.getOrderQuestion_sub1(true, urlOne);
this.getOrderQuestion_sub4(true, urlFour);
} else {
this.getOrderQuestion_sub1(false, urlOne);
this.getOrderQuestion_sub4(false, urlFour);
}
});
}
});
},
divideArray(array, numChunks) {
var chunkSize = Math.ceil(array.length / numChunks);
var dividedArray = [];
for (var i = 0; i < array.length; i += chunkSize) {
dividedArray.push(array.slice(i, i + chunkSize));
}
return dividedArray;
},
//改变当前科目
changeSubject(val) {
this.curSubject = val;
storage.set('curSubject', val);
},
// 获取顺序做题科目1
getOrderQuestion_sub1(isUpdate, url) {
if (isUpdate) {
this.loading_subject1 = true;
this.loadAllQuestion(url, 1);
} else {
this.orderQuestion_subject1 = [];
for (let i = 0; i < JSON_SPLIT_LENGTH; i++) {
const arr = uni.getStorageSync(`question1Sub${i + 1}`) || [];
this.orderQuestion_subject1 = [...this.orderQuestion_subject1, ...arr];
}
if (this.orderQuestion_subject1.length == 0) {
this.loading_subject1 = true;
this.loadAllQuestion(url, 1);
}
}
},
// 获取顺序做题科目4
getOrderQuestion_sub4(isUpdate, url) {
if (isUpdate) {
this.loading_subject4 = true;
this.loadAllQuestion(url, 4);
} else {
this.orderQuestion_subject4 = [];
for (let i = 0; i < JSON_SPLIT_LENGTH; i++) {
const arr = uni.getStorageSync(`question4Sub${i + 1}`) || [];
this.orderQuestion_subject4 = [...this.orderQuestion_subject4, ...arr];
}
if (this.orderQuestion_subject4.length == 0) {
this.loading_subject4 = true;
this.loadAllQuestion(url, 4);
}
}
},
// 加载线上题目
loadAllQuestion(url, course) {
const that = this;
uni.request({
url: url,
success(resp) {
if (resp?.data) {
try {
for (let i = 0; i < JSON_SPLIT_LENGTH; i++) {
storage.remove(`question${course}Sub${i + 1}`);
}
that[`orderQuestion_subject${course}`] = resp.data?.data || [];
const diveList = that.divideArray(that[`orderQuestion_subject${course}`], JSON_SPLIT_LENGTH);
that[`loading_subject${course}`] = false;
for (let i = 0; i < JSON_SPLIT_LENGTH; i++) {
uni.setStorageSync(`question${course}Sub${i + 1}`, diveList[i]);
}
const falseList = storage.get(`wrongList_subject${course}`) || [];
const trueList = storage.get(`rightList_subject${course}`) || [];
const falseArr = [];
const rightArr = [];
that[`orderQuestion_subject${course}`].forEach(item => {
if (falseList.includes(item.questionId)) {
falseArr.push(item.questionId);
}
if (trueList.includes(item.questionId)) {
rightArr.push(item.questionId);
}
});
storage.set(`wrongList_subject${course}`, falseArr);
storage.set(`rightList_subject${course}`, rightArr);
} catch (err) {
console.log(err);
uni.showToast({
title: '题库下载异常,请稍后再试',
icon: 'none'
});
}
} else {
uni.showToast({
title: '加载题目失败,请稍后再试',
icon: 'none'
});
}
}
});
},
//获取索引
getCurrentIndex(index, val) {
this[`currentIndex_subject${val}`] = index;
}
}
});
export default question;
export default question;

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { login,logout,getInfo } from '@/jtools/api/login';
import { queryVip,getVipList } from '@/jtools/api/vip'
import { login, logout, getInfo } from '@/jtools/api/login';
import { queryVip, getVipList } from '@/jtools/api/vip';
import constants from '@/jtools/constants';
import storage from '@/jtools/storage';
@@ -16,67 +16,77 @@ const useUserStore = defineStore({
}),
actions: {
login(params) {
return new Promise(async (resolve, reject) => {
const resp = await login(params);
if (resp.code === '0000') {
// 保存登录信息,用于重新登录
this.isLogin = true;
this.token = resp.data.token;
this.userInfo = resp.data
storage.set('isLogin', true)
storage.set('token', resp.data.token)
storage.set('userInfo', resp.data)
resolve(resp.data);
} else {
reject();
}
});
},
login(params) {
return new Promise(async (resolve, reject) => {
const resp = await login(params);
if (resp.code === '0000') {
// 保存登录信息,用于重新登录
this.isLogin = true;
this.token = resp.data.token;
this.userInfo = resp.data;
storage.set('isLogin', true);
storage.set('token', resp.data.token);
storage.set('userInfo', resp.data);
storage.remove('companyId');
resolve(resp.data);
} else {
reject();
}
});
},
// 登出
logout(force = false) {
return new Promise((resolve, reject) => {
this.resetUserData();
uni.redirectTo({
url: '/pages/login/login'
})
});
resolve();
})
});
},
//过期登出
logoutWithoutToken(force = false) {
return new Promise((resolve, reject) => {
this.resetUserData();
resolve();
});
},
// 获取用户信息
getUserInfo() {
getInfo().then(resp => {
if(resp.code == '0000') {
this.userInfo = resp.data
storage.set('userInfo', resp.data)
if (resp.code == '0000') {
this.userInfo = resp.data;
storage.set('userInfo', resp.data);
}
})
});
},
resetUserData() {
this.isLogin = false;
this.token = '';
this.userInfo = {}
this.vipOnList = []
storage.remove('isLogin')
storage.remove('token')
storage.remove('userInfo')
this.userInfo = {};
this.vipOnList = [];
storage.remove('isLogin');
storage.remove('token');
storage.remove('userInfo');
},
// 查询当前用户的vip开通情况
async searchUserVip() {
const resp=await queryVip({ carTypeId: this.currentCartype,memberId: null, subject:'' })
if(resp.code == '0000') {
this.vipOnList = resp.data
}
this.currentCartype = storage.get('carType') || '1001';
const resp = await queryVip({ carTypeId: this.currentCartype, memberId: null, subject: '' });
if (resp.code == '0000') {
this.vipOnList = resp.data;
}
},
// 查询所有的vip
queryVipList() {
getVipList({ carTypeId: this.currentCartype,memberId: null, subject:'' }).then(resp => {
if(resp.code == '0000') {
this.vipAllList = resp.data
this.currentCartype = storage.get('carType') || '1001';
getVipList({ carTypeId: this.currentCartype, memberId: null, subject: '' }).then(resp => {
if (resp.code == '0000') {
this.vipAllList = resp.data;
}
})
});
}
},
}
});
export default useUserStore;

261
src/jtools/wechat/wechat.js Normal file
View File

@@ -0,0 +1,261 @@
/**
* Wechat v1.1.0
* @Class Wechat
* @description jtools-wechat 1.1.0 wehcat第三方登录组件
* @Author lidongtony
* @Date 2020-05-20
* @Email lidongtony@qq.com
*/
import api from "@/jtools/request/index";
import $platform from "@/jtools/platform";
import store from "@/jtools/store";
import {
API_URL
} from "@/env";
export default {
eventMap(event) {
let map = "";
switch (event) {
case "login":
map = "登录中...";
break;
case "refresh":
map = "更新中...";
break;
case "bind":
map = "绑定中...";
break;
}
return map;
},
async login() {
let token = "";
// #ifdef MP-WEIXIN
token = await this.wxMiniProgramOauth("login");
return token;
// #endif
// #ifdef H5
this.wxOfficialAccountOauth("login");
// #endif
// #ifdef APP-PLUS
token = await this.wxOpenPlatformOauth("login");
return token;
// #endif
},
async refresh() {
let token = "";
// #ifdef MP-WEIXIN
token = await this.wxMiniProgramOauth("refresh");
return token;
// #endif
// #ifdef H5
this.wxOfficialAccountOauth("refresh");
// #endif
// #ifdef APP-PLUS
token = await this.wxOpenPlatformOauth("refresh");
return token;
// #endif
},
async bind() {
let token = "";
// #ifdef MP-WEIXIN
token = await this.wxMiniProgramOauth("bind");
return token;
// #endif
// #ifdef H5
this.wxOfficialAccountOauth("bind");
// #endif
// #ifdef APP-PLUS
token = await this.wxOpenPlatformOauth("bind");
return token;
// #endif
},
// #ifdef H5
// 微信公众号网页登录&刷新头像昵称&绑定
wxOfficialAccountOauth(event = "login") {
if ($platform.get() !== "wxOfficialAccount") {
uni.showToast({
title: "请在微信浏览器中打开",
icon: "none"
});
throw false;
}
let host = $platform.host();
let payloadObject = {
host: host,
event,
token: (event !== "login" && store.getters.isLogin) ? uni.getStorageSync("token") : ""
};
let payload = encodeURIComponent(JSON.stringify(payloadObject));
let redirect_uri = encodeURIComponent(`${API_URL}user/wxOfficialAccountOauth?payload=${payload}`);
let oauthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + store.getters.initWechat.appid +
`&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=1`;
uni.setStorageSync("lastPage", window.location.href);
window.location = oauthUrl;
},
// 微信公众号网页静默登录:临时登录获取OpenId 不入库不绑定用户
wxOfficialAccountBaseLogin() {
let state = encodeURIComponent(window.location.href);
window.location = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + store.getters.initWechat.appid +
`&redirect_uri=${API_URL}user/wxOfficialAccountBaseLogin&response_type=code&scope=snsapi_base&state=${state}`;
throw "stop";
},
// #endif
// #ifdef APP-PLUS
// 微信开放平台登录
wxOpenPlatformOauth(event = "login") {
let that = this;
return new Promise((resolve, reject) => {
uni.login({
provider: "weixin",
success: function(loginRes) {
if (loginRes.errMsg === "login:ok") {
let authResult = loginRes.authResult;
api("user.wxOpenPlatformOauth", {
authResult,
event
}, that.eventMap(event)).then(res => {
if (res.code === 1) {
resolve(res.data.token);
} else {
resolve(false);
}
});
}
},
fail: function(res) {
uni.showToast({
title: "登录失败,请稍后再试"
});
resolve(false);
api("common.debug", {
info: res
});
},
complete: function(res) {}
});
});
},
// #endif
// #ifdef MP-WEIXIN
// 微信小程序静默登录
async getWxMiniProgramSessionKey(autoLogin = true) {
let sessionStatus = false;
let session_key = "";
return new Promise((resolve, reject) => {
uni.checkSession({
success(res) {
if (res.errMsg === "checkSession:ok") sessionStatus = true;
},
complete() {
if (uni.getStorageSync("session_key") && sessionStatus && !autoLogin) {
resolve(uni.getStorageSync("session_key"));
} else {
uni.login({
success: function(info) {
let code = info.code;
api("user.getWxMiniProgramSessionKey", {
code: code,
autoLogin: autoLogin
}).then(res => {
if (res.code === 1) {
uni.setStorageSync("session_key", res
.data.session_key);
if (autoLogin) {
if (res.data.token) {
resolve(res.data.token);
} else {
resolve(false);
}
}
resolve(res.data.session_key);
} else {
reject(res.msg);
}
});
}
});
}
}
});
});
},
// 微信小程序获取用户信息登录
wxMiniProgramOauth(event = "login") {
let that = this;
let session_key = uni.getStorageSync("session_key");
uni.showLoading({
title: that.eventMap(event)
});
return new Promise((resolve, reject) => {
uni.getUserProfile({ // 必须手动确认触发
desc: "完善会员资料", // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: res => {
if (res.errMsg === "getUserProfile:ok") {
api("user.wxMiniProgramOauth", {
event,
session_key,
encryptedData: res.encryptedData,
iv: res.iv,
signature: res.signature,
}).then(res => {
console.log(res)
if (res.code === 1) {
resolve(res.data.token);
} else {
uni.removeStorageSync("session_key");
that.getWxMiniProgramSessionKey(false);
resolve(false);
}
});
}
},
complete: res => {
uni.hideLoading();
}
});
});
},
// 小程序更新
checkMiniProgramUpdate() {
if (uni.canIUse("getUpdateManager")) {
const updateManager = uni.getUpdateManager();
updateManager.onCheckForUpdate(function(res) {
// 请求完新版本信息的回调
if (res.hasUpdate) {
updateManager.onUpdateReady(function() {
uni.showModal({
title: "更新提示",
content: "新版本已经准备好,是否重启应用?",
success: function(res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate();
}
}
});
});
updateManager.onUpdateFailed(function() {
// 新的版本下载失败
uni.showModal({
title: "已经有新版本了哟~",
content: "新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~"
});
});
}
});
}
},
// #endif
};

View File

@@ -66,7 +66,13 @@
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
"usingComponents" : true,
"appid" : "ttbbd1cd6c24e1c00801",
"setting" : {
"es6" : true,
"postcss" : true,
"minified" : true
}
},
"uniStatistics" : {
"enable" : false

18
src/package.json Normal file
View File

@@ -0,0 +1,18 @@
{
"id": "yan-qr",
"name": "动态生成二维码",
"displayName": "动态生成二维码",
"version": "1.0.0",
"description": "动态生成二维码",
"keywords": [
"二维码",
"生成二维码",
"动态二维码"
],
"dcloudext": {
"category": [
"前端组件",
"通用组件"
]
}
}

View File

@@ -8,7 +8,8 @@
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "金武联驾考"
"navigationBarTitleText": "金武联驾考",
"enablePullDownRefresh": false
}
},
{
@@ -83,13 +84,6 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/me/tijian",
"style": {
"navigationBarTitleText": "我的体检",
"enablePullDownRefresh": false
}
},
{
"path": "pages/me/school",
"style": {
@@ -100,7 +94,14 @@
{
"path": "pages/index/videoVip",
"style": {
"navigationBarTitleText": "视频精品课",
"navigationBarTitleText": "开通会员",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/testTip",
"style": {
"navigationBarTitleText": "模拟考试",
"enablePullDownRefresh": false
}
},
@@ -111,27 +112,83 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/iconSkill",
"style": {
"navigationBarTitleText": "图标技巧",
"enablePullDownRefresh": false
}
},
{
"path": "pages/questionBank/chapterExercise",
"style": {
"navigationBarTitleText": "章节练习",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/testRoom",
"style": {
"navigationBarTitleText": "考场实况",
"enablePullDownRefresh": false
}
}
{
"path": "pages/index/iconSkill",
"style": {
"navigationBarTitleText": "图标技巧",
"enablePullDownRefresh": false
}
},
{
"path": "pages/questionBank/chapterExercise",
"style": {
"navigationBarTitleText": "章节练习",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/testRoom",
"style": {
"navigationBarTitleText": "考场实况",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/paySuccess",
"style": {
"navigationBarTitleText": "支付结果",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/trueTest",
"style": {
"navigationBarTitleText": "真实考场模拟",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/secretPapers",
"style": {
"navigationBarTitleText": "考前密卷",
"enablePullDownRefresh": false
}
},
{
"path": "pages/me/changeCarType",
"style": {
"navigationBarTitleText": "切换车型",
"enablePullDownRefresh": false
}
},
{
"path": "pages/index/activity",
"style": {
"navigationBarTitleText": "活动",
"enablePullDownRefresh": false
}
},
{
"path": "pages/me/myGift",
"style": {
"navigationBarTitleText": "我的奖品",
"enablePullDownRefresh": false
}
},
{
"path": "pages/me/qrCode",
"style": {
"navigationBarTitleText": "核销二维码",
"enablePullDownRefresh": false
}
},
{
"path": "pages/me/help",
"style": {
"navigationBarTitleText": "好友助力",
"enablePullDownRefresh": true
}
}
],
"globalStyle": {
@@ -142,7 +199,7 @@
},
"tabBar": {
"borderStyle": "white",
"selectedColor": "#333333",
"selectedColor": "#05C341",
"backgroundColor": "#FFFFFF",
"color": "#999999",
"list": [

View File

@@ -0,0 +1,26 @@
<template>
<view>
<GGL></GGL>
</view>
</template>
<script>
import GGL from './components/ggl/index'
export default {
components: {
GGL
},
data() {
return {
}
},
methods: {
}
}
</script>
<style>
</style>

View File

@@ -1,167 +1,385 @@
<template>
<view>
<view class="box-nav">
<image style="width: 100%;" src="../../static/image/index/index_bg.jpg"></image>
<image style="width: 100%;"
src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E9%A6%96%E9%A1%B5_20230830213855.png">
</image>
<view class="center-box flex jc-sb ai-c">
<view class="box-item flex ai-c jc-c">
<view class="flex jc-c ai-c" style="width: 230rpx;height: 230rpx;background-image: url(../../../static/image/index/green_bg.png);background-size: 100% 100%;">
<view class="btn-item flex ai-c jc-c">
<view class="text-center cor-fff" style="line-height: 40rpx;" @tap="toAnswer('顺序答题',false)">
<view class="fs16">顺序练习</view>
<text class="fs14">{{rightList.length+wrongList.length}}/{{orderQuestion.length}}</text>
</view>
<view class="flex jc-c ai-c relative" style="width: 230rpx;height: 230rpx;" @tap="toAnswer('顺序答题',false)">
<image style="width: 230rpx;height: 230rpx;position: absolute;left: 0;top: 0;"
src="../../../static/image/index/green_bg.png"></image>
<view class="btn-item flex ai-c jc-c">
<view class="text-center cor-fff" style="line-height: 40rpx;">
<view class="fs16">顺序练习</view>
<text
class="fs14">{{getDoNum}}/{{subject=='1'?orderQuestion_subject1.length:orderQuestion_subject4.length}}</text>
</view>
</view>
</view>
</view>
<view class="box-item flex ai-c jc-c">
<view class="flex jc-c ai-c" style="width: 230rpx;height: 230rpx;background-image: url(../../../static/image/index/orange_bg.png);background-size: 100% 100%;">
<view class="btn2-item flex ai-c jc-c">
<view class="text-center cor-fff" style="line-height: 40rpx;" @tap="toExams">
<view class="fs16">模拟考试</view>
<text class="fs14">去考试</text>
</view>
<view class="flex jc-c ai-c relative" style="width: 230rpx;height: 230rpx;" @tap="toExams('模拟考试')">
<image style="width: 230rpx;height: 230rpx;position: absolute;left: 0;top: 0;"
src="../../../static/image/index/orange_bg.png"></image>
<view class="btn2-item flex ai-c jc-c">
<view class="text-center cor-fff" style="line-height: 40rpx;">
<view class="fs16">模拟考试</view>
<text class="fs14">去考试</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view style="padding: 0 28rpx;margin-top: 60rpx;">
<view style="padding: 0 28rpx;margin-top: calc(100% - 718rpx);">
<view class="tabs-box">
<view class="wp33 flex ai-c jc-c" @tap="toVip">
<view class="text-center wp100">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto"
src="../../static/image/index/vipicon.png">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto" src="../../static/image/index/vipicon.png">
</image>
<view class="mt5">VIP课程</view>
</view>
</view>
<view class="wp33 flex ai-c jc-c" @tap="toAnswer('精简500题',true)">
<view class="wp33 flex ai-c jc-c" @tap="toAnswer(`精简${titleNum}题`,true)">
<view class="text-center wp100">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto"
src="../../static/image/index/500icon.png">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto" src="../../static/image/index/500icon.png">
</image>
<view class="mt5">精简500</view>
<view class="mt5">精简{{titleNum}}</view>
</view>
</view>
<view class="wp33 flex ai-c jc-c" @tap="toExclusive">
<view class="text-center wp100">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto"
src="../../static/image/index/zxicon.png">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto" src="../../static/image/index/zxicon.png">
</image>
<view class="mt5">专项练习</view>
</view>
</view>
<view class="wp33 flex ai-c jc-c" @tap="toTestRoom">
<view class="text-center wp100">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto;"
src="../../static/image/index/realicon.png"></image>
<image style="width: 72rpx;height: 72rpx;margin: 0 auto;" src="../../static/image/index/realicon.png">
</image>
<view class="mt5">真实考场模拟</view>
</view>
</view>
<view class="wp33 flex ai-c jc-c">
<view class="wp33 flex ai-c jc-c" @tap="toExams('考前秘卷')">
<view class="text-center wp100">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto"
src="../../static/image/index/testbeforeicon.png"></image>
<view class="mt5">考前</view>
<image style="width: 72rpx;height: 72rpx;margin: 0 auto" src="../../static/image/index/testbeforeicon.png">
</image>
<view class="mt5">考前</view>
</view>
</view>
<view class="wp33 flex ai-c jc-c" @tap="toWrongList">
<view class="text-center wp100">
<image style="width: 72rpx;height: 72rpx;margin: 0 auto"
src="../../static/image/index/worryicon.png"></image>
<image style="width: 72rpx;height: 72rpx;margin: 0 auto" src="../../static/image/index/worryicon.png">
</image>
<view class="mt5">错题收藏</view>
</view>
</view>
</view>
</view>
<view style="padding: 0 28rpx;margin-top: 30rpx;" @tap="toClass">
<!-- <view style="padding: 0 28rpx;margin-top: 30rpx;" @tap="toClass">
<view class="video-box">
<view class="flex jc-sb ai-c wp100">
<text style="color: #05C341;font-size: 36rpx;">{{subject==1?'一':'四'}}精品视频课</text>
<text class="cor-666 fs12">全部10节课 ></text>
</view>
<view class="flex ai-c mt20">
<image class="contain-box" src="../../static/image/index/index_bg.jpg"></image>
<view class="contain-box relative">
<image class="contain-box" src="../../../static/image/index/jpsp.png"></image>
<image class="play_btn_2" src="../../static/image/index/play.png" />
</view>
<view class="ml15 text-center">
<u-button :customStyle="{width:'200rpx',height:'66rpx',borderRadius: '33rpx'}" iconColor="#fff"
text="去看视频" color="linear-gradient(90deg, #11DF20 0%, #00B74F 100%)" icon="play-circle">
<u-button :customStyle="{width:'200rpx',height:'66rpx',borderRadius: '33rpx'}" iconColor="#fff" text="去看视频"
color="linear-gradient(90deg, #11DF20 0%, #00B74F 100%)" icon="play-circle">
</u-button>
<view class="cor-333 fs15 fw600 mt10">{{subject==1?'一':'四'}}易错试题</view>
</view>
</view>
</view>
</view>
</view> -->
</view>
</template>
<script>
import { mapState,mapActions } from 'pinia' //引入映射函数
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useUserStore from '@/jtools/store/user'
import storage from '@/jtools/storage';
import useQuestionStore from '@/jtools/store/question' //引入store
import {
querySysConfig,
queryQuestionId,
getTestQuestionId
} from '@/jtools/api/question';
export default {
props:{
subject:{
type:[String,Number],
props: {
subject: {
type: [String, Number],
},
rightList: {
type: Array
},
wrongList: {
type: Array
}
},
data() {
return {
rightList:storage.get(`rightList_subject${this.subject}`) || [],
wrongList:storage.get(`wrongList_subject${this.subject}`) || [],
allQuestionNum:0,
titleNum:500,
allQuestionNum: 0,
}
},
onLoad(){
// this.allQuestionNum=useQuestionStore().orderQuestion.length
mounted() {
this.getTitle()
},
onShow() {
this.getTitle()
},
computed: {
...mapState(useQuestionStore, ["orderQuestion"]) //映射函数取出tagslist
...mapState(useUserStore, ["vipOnList", "token"]),
...mapState(useQuestionStore, ["orderQuestion_subject1", "orderQuestion_subject4", "version"]), //映射函数取出tagslist
getDoNum() {
return this.rightList.length + this.wrongList.length
}
},
methods: {
toTestRoom(){
uni.navigateTo({
url:"/pages/index/testRoom"
...mapActions(useUserStore, ['searchUserVip']),
...mapActions(useQuestionStore, ['getOrderQuestion_sub1', 'getOrderQuestion_sub4', 'getAllQuestion']),
getTitle(){
const carId=storage.get('carType') || '1001'
querySysConfig(carId,'SimplifyQuestionNum').then(resp=>{
if(resp.code==='0000'){
const list = JSON.parse(resp.data.configJson)
this.titleNum=list.find(item=>item.subject==this.subject).num
}
})
},
toVip(){
uni.navigateTo({
url:"/pages/index/videoVip"
async toTestRoom() {
// uni.navigateTo({
// url:"/pages/index/trueTest"
// })
if (this.token) {
await this.searchUserVip()
const res = this.vipOnList.some(item => item.subjects.includes(this.subject))
if (!res) {
uni.navigateTo({
url: "/pages/index/videoVip?subject=" + this.subject
})
} else {
getTestQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
}).then(async (resp) => {
if (resp.code === '0000') {
if(resp.data&&resp.data.length){
const arr = resp.data
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/index/trueTest?subject="+ this.subject + "&questionIdList=" + listJson
})
}else{
uni.showToast({
title: '暂无题目',
icon: 'none'
})
}
} else if (resp.code === '4001') {
uni.showToast({
title: '当前题库非最新版,请更新~',
icon: 'none'
})
this.getAllQuestion()
}
})
}
} else {
uni.redirectTo({
url: '/pages/login/login'
});
}
},
async toVip() {
if (this.token) {
await this.searchUserVip()
const res = this.vipOnList.some(item => item.subjects.includes(this.subject))
if (!res) {
uni.navigateTo({
url: "/pages/index/videoVip?subject=" + this.subject
})
} else {
uni.navigateTo({
url: "/pages/me/vip"
})
}
} else {
uni.redirectTo({
url: '/pages/login/login'
});
}
},
toClass() {
uni.showToast({
title: '敬请期待',
icon: 'none'
})
},
toClass(){
uni.navigateTo({
url:"/pages/questionBank/baseOperate"
})
toAnswer(title, val) {
if (title == `精简${this.titleNum}`) {
queryQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
isVip: '1'
}).then(async (resp) => {
if (resp.code === '0000') {
if (this.token) {
await this.searchUserVip()
const result = this.vipOnList.some(item => item.subjects.includes(this.subject))
let arr = []
if (result) {
if(resp.data&&resp.data.length){
const listJson = JSON.stringify(resp.data)
uni.navigateTo({
url: "/pages/questionBank/questionBank?navTitle=" + title + "&subject=" + this.subject +
"&needVip=" + !result + "&questionIdList=" + listJson
})
}else{
uni.showToast({
title: '暂无题目',
icon: 'none'
})
}
} else {
if (resp.data && resp.data.length > 3) {
arr = resp.data.slice(0, 3)
} else {
arr = resp.data
}
if(arr&&arr.length){
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/questionBank?navTitle=" + title + "&subject=" + this.subject +
"&needVip=" + !result + "&questionIdList=" + listJson
})
}else{
uni.showToast({
title: '暂无题目',
icon: 'none'
})
}
}
} else {
uni.redirectTo({
url: '/pages/login/login'
});
}
} else if (resp.code === '4001') {
uni.showToast({
title: '当前题库非最新版,请更新~',
icon: 'none'
})
this.getAllQuestion()
}
})
} else {
uni.navigateTo({
url: "/pages/questionBank/questionBank?navTitle=" + title + "&subject=" + this.subject + "&needVip=" +
val
})
}
},
toAnswer(title,val) {
toExams(title) {
if (storage.get('token')) {
if(title=='模拟考试'){
getTestQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
}).then(async (resp) => {
if (resp.code === '0000') {
const arr = resp.data
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/index/testTip?subject=" + this.subject + "&questionIdList=" + listJson
})
} else if (resp.code === '4001') {
uni.showToast({
title: '当前题库非最新版,请更新~',
icon: 'none'
})
this.getAllQuestion()
}
})
}else if(title=='考前秘卷'){
const param=this.subject=='1'?{isExam1: '1'}:{isExam2: '1'}
queryQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
...param
}).then(async (resp) => {
if (resp.code === '0000') {
let arr = []
if (this.token) {
await this.searchUserVip()
const result = this.vipOnList.some(item => item.subjects.includes(this.subject))
if (result) {
uni.navigateTo({
url: "/pages/index/secretPapers?subject=" + this.subject
})
} else {
if (resp.data && resp.data.length > 3) {
arr = resp.data.slice(0, 3)
} else {
arr = resp.data
}
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/index/videoVip?subject=" + this.subject
})
}
} else {
uni.redirectTo({
url: '/pages/login/login'
});
}
} else if (resp.code === '4001') {
uni.showToast({
title: '当前题库非最新版,请更新~',
icon: 'none'
})
this.getAllQuestion()
}
})
}
} else {
uni.navigateTo({
url:"/pages/questionBank/questionBank?navTitle="+title+"&subject="+this.subject+"&needVip="+val
})
},
toExams(){
uni.navigateTo({
url:"/pages/questionBank/practiceExams?subject="+this.subject
})
},
toExclusive(){
uni.navigateTo({
url:"/pages/questionBank/exclusiveExercise"
})
},
toWrongList(){
uni.navigateTo({
url:"/pages/questionBank/wrongQuestion?subject="+this.subject
url: '/pages/login/login'
})
}
},
toExclusive() {
uni.navigateTo({
url: "/pages/questionBank/exclusiveExercise?subject=" + this.subject
})
},
toWrongList() {
uni.navigateTo({
url: "/pages/questionBank/wrongQuestion?subject=" + this.subject
})
}
}
}
</script>
<style scoped>
.box-nav {
width: 100%;
position: relative;
height: 500rpx;
}
.center-box {
@@ -224,4 +442,12 @@
background: #00B74F;
border-radius: 16rpx;
}
</style>
.play_btn_2 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 165.5rpx;
top: 78rpx
}
</style>

View File

@@ -1,130 +1,320 @@
<template>
<view>
<view class="box-nav">
<image style="width: 100%;" src="../../../static/image/index/index_bg.jpg"></image>
<view style="width: 100%;position: absolute;top: 80px;left: 0;" class="flex jc-c">
<image style="width: 694rpx" mode="widthFix" src="../../../static/image/index/subject2_bg.png"></image>
<view>
<view class="box-nav">
<image style="width: 100%;" src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E9%A6%96%E9%A1%B5_20230830213855.png"></image>
<view style="width: 100%;position: absolute;top: 80px;left: 0;" class="flex jc-c" @tap="toVipVideo">
<image style="width: 694rpx" mode="widthFix"
:src="subject=='2'?'https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E7%A7%91%E4%BA%8C%E9%A6%96%E9%A1%B5banner_20230830214212.png':'https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E7%A7%91%E4%B8%89%E9%A6%96%E9%A1%B5banner_20230830214245.png'">
</image>
</view>
</view>
</view>
<view class="p14lr" style="margin-top: -20px;">
<view class="video_box">
<view class="flex ai-c jc-sb mt5">
<text class="fs18 cor-000">考试项目讲解</text>
<view class="flex ai-c" style="height: 34rpx;line-height: 34rpx;" @tap="changeDiverType">
<text style="color:#05C341;font-size: 16px;">{{diverTypeList[diverTypeIndex].configItemName}}</text>
<text class="fs18 cor-000">{{subject=='2'?'二':'三'}}考试项目讲解</text>
<!-- <view class="flex ai-c" style="height: 34rpx;line-height: 34rpx;" @tap="changeDiverType">
<text style="color:#05C341;font-size: 16px;">{{diverTypeList[diverTypeIndex]?.configItemName}}</text>
<u-icon name="list" color="#05C341" size="18"></u-icon>
</view> -->
</view>
<view class="skill-sequence-panel-content-wrapper">
<scroll-view class="skill-sequence-panel-content" scroll-x :scroll-into-view="intoindex">
<view class="skill-sequence-skill-wrapper tab_iem m15tb" :class="videoIndex===index?'checked_tab':''"
v-for="(item,index) of operateList" :key="index" :id='"text"+index' @tap="checkVideo(index)">
{{item.description}}
</view>
</scroll-view>
</view>
<swiper class="swiper" :current="videoIndex" style="height: 362rpx;" :autoplay="false"
:disable-programmatic-animation="true" @change="onChange">
<swiper-item v-for="(item,index) of operateList" :key="index" @tap="toVideo">
<view class="p5lr wp100">
<view class="wp100 relative hide"
style="height: 362rpx;border-radius: 16rpx;overflow: hidden;">
<image style="width: 100%;height: 362rpx;position: absolute;left: 0;top: 0;" mode="widthFix"
:src="item.videoList[0].videoUrl+'?x-oss-process=video/snapshot,t_0,f_jpg'"></image>
<image class="play_btn_2" src="../../static/image/index/play.png" />
</view>
</view>
</swiper-item>
</swiper>
</view>
<view class="video_box mt10" v-if="subject=='2'">
<view class="flex ai-c jc-sb">
<text class="fs18 cor-000">基础操作讲解</text>
<view class="flex cor-666" @tap="toDetail">
<text>全部</text>
<u-icon color="#666" name="arrow-right" size="18"></u-icon>
</view>
</view>
<view class="flex ai-c jc-sb mt15">
<view class="tab_iem" :class="videoIndex===item.value?'checked_tab':''" v-for="(item,index) of operateList" :key="index" @tap="checkVideo(index)">{{item.description}}</view>
</view>
<view class="mt15">
<video style="width: 100%;height: 362rpx;border-radius: 16rpx;" id="myVideo" :src="operateList[videoIndex].videoList[0].videoUrl"></video>
</view>
</view>
<view class="video_box mt10">
<text class="fs18 cor-000">驾驶方法</text>
<view class="text-center mt10" style="width: 200rpx;" @tap="toDetail">
<image style="width: 200rpx;height: 200rpx;margin-bottom: 5px;" src="../../../static/image/index/base_operate.png"></image>
<text class="fs16 cor-000">基础操作讲解</text>
<view class="fs14 cor-999 mt5">操作方法精讲</view>
<view class="flex p14lr p20tb bc-fff" style="border-bottom: 1rpx solid #DDDCDC;"
v-for="(item,index) of videoList" :key="index" @click="toOperateDetail(item.videoId)">
<view class="pic relative hide" style="overflow: hidden;">
<image class="pic" style="position: absolute;left: 0;top: 0;" mode="widthFix" :src="item.videoUrl+'?x-oss-process=video/snapshot,t_0,f_jpg'"></image>
<image class="play_btn_3" src="../../static/image/index/play.png" />
</view>
<view class="ml10">
<text class="fs16 cor-000 fw600">{{baseList[0]?.description}}</text>
<view class="fs14 mt5 cor-666">{{item.description}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useUserStore from '@/jtools/store/user'
import {
querySysConfigList,
queryProjectList
} from '@/jtools/api/question';
import storage from '@/jtools/storage';
export default {
name: "Subject2",
props:{
subject:{
type:[String,Number]
}
},
data(){
return{
diverTypeIndex:0,
diverTypeList:[],
videoIndex:0,
operateList:[]
}
},
async mounted(){
await this.getDiverType()
},
methods:{
getVideoList(){
console.log('index',this.diverTypeIndex);
console.log(this.diverTypeList[this.diverTypeIndex]);
queryProjectList({
"carTypeId": storage.get('carType') || '1001',
"driveType": this.diverTypeList[this.diverTypeIndex].configItemCode,
"subject": String(this.subject),
"projectId":'1001',
"type": "1"
}).then(resp=>{
this.operateList=resp.data
})
export default {
name: "Subject2",
props: {
subject: {
type: [String, Number]
}
},
getDiverType(){
const carTypeId=storage.get('carType') || '1001'
querySysConfigList(carTypeId,'DriveType').then(resp=>{
if(resp.code==='0000'){
this.diverTypeList=resp.data
this.getVideoList()
data() {
return {
intoindex: '',
diverTypeIndex: 0,
diverTypeList: [],
videoIndex: 0,
projectId: undefined,
operateList: [],
baseList: [],
videoList: []
}
},
async mounted() {
// await this.getDiverType()
},
computed: {
...mapState(useUserStore, ["vipOnList", "token"])
},
methods: {
...mapActions(useUserStore, ['searchUserVip']),
//vip视频页面
async toVipVideo(){
if (this.token) {
await this.searchUserVip()
const res = this.vipOnList.some(item => item.subjects.includes(this.subject))
if (!res) {
uni.navigateTo({
url:"/pages/index/videoVip?subject="+this.subject
})
}else{
uni.navigateTo({
url: "/pages/questionBank/baseOperate?subject=" + this.subject+"&type=3"
})
}
} else {
uni.redirectTo({
url: '/pages/login/login'
});
}
},
onChange(e) {
this.videoIndex = e.detail.current
this.$nextTick(() => {
const index = this.videoIndex - 1 < 0 ? 0 : this.videoIndex - 1
this.intoindex = "text" + index
});
},
getOperateList() {
queryProjectList({
"carTypeId": storage.get('carType') || '1001',
"subject": String(this.subject),
"type": "2"
}).then(resp => {
if (resp.code === '0000' && resp.data &&resp.data.length) {
this.baseList = resp.data
this.videoList = resp.data[0] && resp.data[0].videoList? resp.data[0].videoList.slice(0, 5) : []
}
})
},
changeDiverType(){
this.diverTypeIndex=this.diverTypeIndex==0?1:0
this.getVideoList()
formateTime(time) {
const h = parseInt(time / 3600)
const minute = parseInt(time / 60 % 60)
const second = Math.ceil(time % 60)
const hours = h < 10 ? '0' + h : h
const formatSecond = second > 59 ? 59 : second
return `${hours > 0 ? `${hours}:` : ''}${minute < 10 ? '0' + minute : minute}:${formatSecond < 10 ? '0' + formatSecond : formatSecond}`
},
checkVideo(val){
this.videoIndex=val
},
toDetail(){
uni.navigateTo({
url:"/pages/questionBank/baseOperate"
})
async toVideo() {
if (this.token) {
await this.searchUserVip()
const res = this.vipOnList.some(item => item.subjects.includes(this.subject))
if (!res) {
uni.navigateTo({
url:"/pages/index/videoVip?subject="+this.subject
})
}else{
let arr = JSON.parse(JSON.stringify(this.operateList))
arr = arr.map(item => {
return {
...item,
videoUrl: item.videoList[0]?.videoUrl,
videoTime: this.formateTime(item.videoList[0]?.videoTime)
}
})
let jsonString = JSON.stringify(arr)
console.log('arr',jsonString);
uni.navigateTo({
url: "/pages/questionBank/videoDetail?videoList=" + jsonString + "&subject=" + this.subject +
"&projectId=" + this.projectId + "&type=1&driveType=2"
})
}
} else {
uni.redirectTo({
url: '/pages/login/login'
});
}
},
toOperateDetail(val) {
let arr = JSON.parse(JSON.stringify(this.baseList[0].videoList))
arr = arr.map(item => {
return {
...item,
projectId: item.videoId,
subDesc: this.baseList[0].description,
videoTime: this.formateTime(item.videoTime)
}
})
let jsonString = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/videoDetail?videoList=" + jsonString + "&subject=" + this.subject +
"&projectId=" + val + "&type=2"
})
},
getVideoList() {
queryProjectList({
"carTypeId": storage.get('carType') || '1001',
"driveType": '2',
"subject": String(this.subject),
"type": "1"
}).then(resp => {
if(resp.code==='0000'){
this.operateList = resp.data
this.projectId = this.operateList[0]?.projectId
}
})
},
getDiverType() {
const carTypeId = storage.get('carType') || '1001'
querySysConfigList(carTypeId, 'DriveType').then(resp => {
if (resp.code === '0000') {
this.diverTypeList = resp.data
this.getVideoList()
this.getOperateList()
}
})
},
changeDiverType() {
this.diverTypeIndex = this.diverTypeIndex == 0 ? 1 : 0
this.videoIndex = 0
this.getVideoList()
this.getOperateList()
},
checkVideo(val) {
this.projectId = this.operateList[val]?.projectId
this.videoIndex = val
},
toDetail() {
uni.navigateTo({
url: "/pages/questionBank/baseOperate?subject=" + this.subject+"&type=2"
})
}
}
}
}
</script>
<style scoped>
.box-nav{
width: 100%;
position: relative;
}
.center-box{
position: absolute;
width: 100%;
top: 170rpx;
padding: 0 28rpx;
}
.video_box{
width: 100%;
background: #FFFFFF;
border-radius: 16rpx;
padding: 14px;
}
.tab_iem{
width: 145rpx;
height: 56rpx;
line-height: 56rpx;
text-align: center;
background: #F5F5F5;
border-radius: 10rpx;
color:#333
.box-nav {
width: 100%;
position: relative;
}
.center-box {
position: absolute;
width: 100%;
top: 170rpx;
padding: 0 28rpx;
}
.video_box {
width: 100%;
background: #FFFFFF;
border-radius: 16rpx;
padding: 14px;
}
.tab_iem {
padding: 0 5px;
height: 56rpx;
line-height: 56rpx;
text-align: center;
background: #F5F5F5;
border-radius: 10rpx;
color: #333
}
.checked_tab {
background: linear-gradient(90deg, #11DF20 0%, #01B74F 100%);
color: #fff
}
.pic {
width: 300rpx;
height: 169rpx;
background: #00B74F;
border-radius: 10rpx;
}
.play_btn_3 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 117.5rpx;
top: 52rpx
}
.play_btn_2 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: calc((100% - 65rpx)/2);
top: 148.5rpx
}
/*scroll-view外层*/
.skill-sequence-panel-content-wrapper {
position: relative;
white-space: nowrap;
}
/*scroll-view本身*/
.skill-sequence-panel-content {
min-width: 100%;
}
/*scroll-view内层*/
.skill-sequence-skill-wrapper {
display: inline-block;
margin-right: 15px;
}
.hide {
backface-visibility: hidden;
transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
}
.checked_tab{
background: linear-gradient(90deg, #11DF20 0%, #01B74F 100%);
color:#fff
}
</style>

View File

@@ -0,0 +1,229 @@
<template>
<view style="padding-bottom: 50px;background-color: #9e0f00;">
<image class="wp100" mode="widthFix" src="https://jwl-jiakao-bq.oss-cn-hangzhou.aliyuncs.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/ggl_header.png"></image>
<view class="tip">您今日还剩{{actiNum}}次刮奖机会共有{{total}}人参加活动</view>
<view class="scraping">
<scraping-card style="z-index: 20;" :result="result" watermark="刮一刮" title="刮一刮赢取大奖" ref="reset" @complete="handleComplete" >
<cover-view v-if="showBtn" class="gj">
<cover-view class="btn" @tap="handleScrap">
{{btnText}}
</cover-view>
</cover-view>
</scraping-card>
</view>
<view class="relative mt30 m20lr">
<image class="wp100" mode="widthFix" src="/static/image/index/tip.png"></image>
<view class="title">中奖名单</view>
<view class="card">
<view v-for="(item, index) in winningList" :key="index" class="card-item">
<text class="item-text">{{ hidePhoneNumber(item.phone) }}</text>
<text class="item-text">{{ item.awards }}</text>
</view>
</view>
</view>
<view class="relative mt30 m20lr">
<image class="wp100" mode="widthFix" src="/static/image/index/tip.png"></image>
<view class="title">活动说明</view>
<view class="card">
<u-parse :content="activityRule"></u-parse>
</view>
</view>
</view>
</template>
<script>
import useUserStore from '@/jtools/store/user'
import ScrapingCard from './scraping.vue'
import { queryActivityDetail,queryLuckyNum,queryLuckyResult,saveWinner,getLuckyRecord } from '@/jtools/api/activity'
export default {
components: {
ScrapingCard
},
data() {
return {
detailId: undefined,
result: '',
btnText: '点我刮奖',
showBtn: true,
actiNum: 0,
total: 0,
winningList: [],
activityRule: undefined
}
},
onLoad(op) {
this.detailId = op.detailId
this.getActivityDetail()
this.getActivityNum()
this.searchWinningList()
},
methods: {
handleScrap() {
if(!this.actiNum) {
uni.showToast({
icon: 'none',
title: '暂无抽奖机会'
})
return
}
queryLuckyResult({
detailId: this.detailId
}).then(resp => {
if(resp.code == 200) {
this.result = resp.msg
this.showBtn = !this.showBtn
this.$refs.reset.init()
}
})
},
getActivityDetail() {
queryActivityDetail({detailId: this.detailId}).then(resp => {
if(resp.code == 200) {
this.activityRule = resp.data.activity.activityRule
}
})
},
hidePhoneNumber(phoneNumber) {
// 验证电话号码格式
if (!/^\d{11}$/.test(phoneNumber)) {
return "无效的电话号码";
}
// 替换中间四位数字为星号
return phoneNumber.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
},
getActivityNum() {
queryLuckyNum({
detailId: this.detailId,
phone: useUserStore().userInfo?.phone || ''
}).then(resp => {
if(resp.code == 200) {
this.actiNum = resp.data.drawNum
this.total = resp.data.totalPeople
}
})
},
searchWinningList() {
getLuckyRecord({
detailId: this.detailId,
pageSize: 8
}).then(resp => {
if(resp.code == 200) {
this.winningList = resp.rows
}
})
},
handleComplete() {
saveWinner({
phone: useUserStore().userInfo?.phone || '',
detailId: this.detailId,
awards: this.result
}).then(resp => {
this.btnText = '再刮一次!'
if(resp.code == 200) {
this.getActivityNum()
let help = ",完成助力即可领取奖品!"
uni.showToast({
icon: 'none',
title: `恭喜获得${this.result}` + help
})
this.showBtn = true
}
})
}
},
}
</script>
<style scoped lang="scss">
.tip {
position: relative;
margin-top: -80px;
margin-left: 40px;
margin-right: 40px;
height: 52rpx;
background: rgba(0,0,0,0.5);
border-radius: 26rpx;
text-align: center;
font-size: 24rpx;
color: #fff;
line-height: 52rpx;
}
.scraping {
position: relative;
margin-top: 20rpx;
margin-left: 40px;
margin-right: 40px;
background-color: #fff;
border: 3px solid #9e0f00; /* 实线边框 */
border-top: 3px dashed #9e0f00; /* 虚线边框 */
border-right: 3px dashed #9e0f00; /* 虚线边框 */
border-bottom: 3px dashed #9e0f00; /* 虚线边框 */
border-left: 3px dashed #9e0f00; /* 虚线边框 */
border-radius: 5px; /* 圆角 */
padding: 10px; /* 内容与边框之间的空间 */
}
.gj {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 21;
.btn {
position: absolute;
top: 50%;
left: calc(50% - 100rpx);
width: 200rpx;
height: 70rpx;
line-height: 70rpx;
background-color: #BE1200;
border-radius: 10rpx;
text-align: center;
font-size: 28rpx;
color: #fff;
}
}
.title {
position: absolute;
left: calc(50% - 160rpx);
top: -14px;
width: 320rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
background: linear-gradient(0deg, #ECB181, #FFEDD3);
border: 6rpx solid #E32D1A;
border-radius: 40rpx 40rpx 0 0;
font-weight: 600;
color: #BE1200;
font-size: 32rpx;
}
.card {
position: relative;
margin-top: -40rpx;
padding: 26rpx;
min-height: 280rpx;
background: #FFEDD3;
border: 6rpx solid #E32D1A;
border-radius: 24rpx;
.card-item {
display: flex;
align-items: center;
justify-content: space-between;
height: 80rpx;
line-height: 80rpx;
border-bottom: 1px solid #ecd3ae;
}
.card-item:last-of-type {
border-bottom: none;
}
.item-text {
font-size: 28rpx;
color: #BE1200;
}
}
</style>

View File

@@ -0,0 +1,280 @@
<template>
<view class="scraping-happy" id="container">
<canvas canvas-id="scraping-happy" class="scraping__canvas" :disable-scroll="true" @touchstart="touchstart"
@touchmove="touchmove" @touchend="touchend" />
<cover-view class="scraping__view">
{{ showText }}
</cover-view>
<slot></slot>
</view>
</template>
<script>
/** @name 水印配置默认值 **/
const WATERMARK = {
text: '刮一刮',
fontSize: 14,
color: '#C5C5C5',
}
/** @name 标题配置默认值 **/
const TITLE = {
text: '刮一刮',
fontSize: 16,
color: '#333',
}
/**
* @name 涂层配置默认值
* @property { string } color 涂层颜色
* @property { number } drawSize 清除涂层的画笔大小
*/
const MASK = {
color: '#DDDDDD',
drawSize: 20,
}
/** @name 容错值解决部分机型涂层没有覆盖满的情况主要原因是由于像素尺寸不同导致的应尽可能让width与height保持整数 **/
const TOLERANT = 3;
let ctx = null;
export default {
props: {
/** @name 涂层设置 **/
mask: {
type: [String, Object],
},
/** @name 水印设置 **/
watermark: {
type: [String, Object],
},
/** @name 提示文字 **/
title: {
type: [String, Object],
},
/** @name 刮开百分之多少直接消除图层为0的时候不消除 **/
percentage: {
type: Number,
default: 40,
},
result: {
type: String,
default: ''
}
},
data() {
return {
width: 0,
height: 0,
touchX: 0,
touchY: 0,
showText: ''
}
},
computed: {
maskSetting() {
return {
...MASK,
...(typeof this.mask === 'object' ? this.mask : {
text: this.mask
}),
}
},
watermarkSetting() {
return {
...WATERMARK,
...(typeof this.watermark === 'object' ? this.watermark : {
text: this.watermark
}),
};
},
titleSetting() {
return {
...TITLE,
...(typeof this.title === 'object' ? this.title : {
text: this.title
}),
};
}
},
mounted() {
// 获取画布实例
ctx = uni.createCanvasContext('scraping-happy', this);
this.init();
},
methods: {
/** @name 初始化 **/
init() {
const query = uni.createSelectorQuery().in(this);
query
.select('#container')
.boundingClientRect(({
width,
height
}) => {
this.width = width;
this.height = height;
setTimeout(() => {
this.initCanvas();
this.showText = this.result
}, 20)
})
.exec();
},
/** @name 初始化canvas状态 **/
initCanvas() {
const {
width,
height
} = this;
// 清空矩形内容
ctx.clearRect(0, 0, width, height);
// 设置画笔颜色
ctx.setFillStyle(this.maskSetting.color);
// 绘制矩形
ctx.fillRect(0, 0, width, height + TOLERANT);
// 绘制水印
this.drawWatermark();
// 绘制提示文字
this.drawTitle();
// 绘制到canvas身上
ctx.draw();
},
/** @name 绘制水印 **/
drawWatermark() {
if (!this.watermarkSetting.text) return;
// 保存当前的绘图上下文
ctx.save();
// 旋转
ctx.rotate((-10 * Math.PI) / 180);
// 水印具体绘制过程
const {
width,
height
} = this;
const watermarkWidth = this.watermarkSetting.text.length * this.watermarkSetting.fontSize;
let x = 0;
let y = 0;
let i = 0;
while ((x <= width * 5 || y <= height * 5) && i < 300) {
ctx.setFillStyle(this.watermarkSetting.color);
ctx.setFontSize(this.watermarkSetting.fontSize);
ctx.fillText(this.watermarkSetting.text, x, y);
x += watermarkWidth + watermarkWidth * 1.6;
if (x > width && y <= height) {
x = -Math.random() * 100;
y += this.watermarkSetting.fontSize * 3;
}
i++;
}
ctx.restore();
},
/** @name 绘制提示文字 **/
drawTitle() {
if (!this.titleSetting.text) return;
ctx.setTextAlign('center');
ctx.setTextBaseline('middle');
ctx.setFillStyle(this.titleSetting.color);
ctx.setFontSize(this.titleSetting.fontSize);
ctx.fillText(this.titleSetting.text, this.width / 2, this.height / 3);
},
/** @name 触摸事件 **/
touchstart(e) {
this.touchX = e.touches[0].x;
this.touchY = e.touches[0].y;
},
async touchmove(e) {
// 把画笔到画布中的指定点
ctx.moveTo(this.touchX, this.touchY);
// 清除涂层
ctx.clearRect(this.touchX, this.touchY, this.maskSetting.drawSize, this.maskSetting.drawSize);
ctx.draw(true);
// 记录移动点位
this.touchX = e.touches[0].x;
this.touchY = e.touches[0].y;
// if (this.percentage > 0) {
// const clearPercent = await this.getClearMaskPercent();
// }
},
async touchend() {
if (this.percentage > 0) {
const clearPercent = await this.getClearMaskPercent();
if (clearPercent >= this.percentage) {
ctx.moveTo(0, 0);
ctx.clearRect(0, 0, this.width, this.height);
ctx.stroke();
ctx.draw(true);
this.$emit('complete')
}
}
},
/** @name 计算被清除的涂层百分比 **/
getClearMaskPercent() {
return new Promise(resolve => {
uni.canvasGetImageData({
canvasId: 'scraping-happy',
x: 0,
y: 0,
width: this.width,
height: this.height,
success: res => {
// 区域内所有点的像素信息,它是一个数组,数组中每 "4" 项表示一个点的 rgba 值
const allPointPixels = res.data;
// 储存被清除的点-点的透明度
const clearPoint = [];
// 取透明度来判断,如果透明度值小于一半,则判断为该点已经被清除
for (let i = 0; i < allPointPixels.length; i += 4) {
if (allPointPixels[i + 3] < 128) {
clearPoint.push(allPointPixels[i + 3]);
}
}
// 已被清除的百分比 = 清除的点 / 全部的点
const percent = (
(clearPoint.length / (allPointPixels.length / 4)) *
100
).toFixed(2);
resolve(percent);
},
fail: e => {
console.log('canvasGetImageData', e);
},
}, this);
});
},
/** @name 重置 **/
reset() {
this.initCanvas();
this.touchX = 0;
this.touchY = 0;
}
}
};
</script>
<style>
.scraping-happy {
width: 100%;
height: 200rpx;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.scraping__canvas {
width: 100%;
height: 100%;
position: absolute;
z-index: 10;
/* background-color: red; */
display: inline-block;
}
.scraping__view {
position: absolute;
z-index: 1;
color: #f29100;
font-size: 20px;
font-weight: bold;
letter-spacing: 8px;
}
</style>

View File

@@ -1,62 +1,153 @@
<template>
<view>
<u-sticky bgColor="#fff">
<u-tabs :list="categoryList" :scrollable="false" @change="changeCategory"></u-tabs>
</u-sticky>
<view style="height: 100vh;background-color: rgb(245, 245, 245);">
<template v-if="tIndex===0 || tIndex===3">
<Subject1 :subject="tIndex+1" />
</template>
<template v-else>
<subject2 :subject="tIndex+1" />
</template>
</view>
</view>
<view>
<view v-if="getLoading" class="wp100 relative" style="height: 100vh;">
<image class="wp100" mode="widthFix"
src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E8%80%83%E8%AF%95%E6%8F%90%E9%86%92_20230906135037.png">
</image>
<view class="wp100 flex ai-c jc-c" style="position: absolute;bottom: 0;left: 0;padding-bottom: 124rpx;">
<image style="width: 452rpx;"
src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E9%87%91%E6%AD%A6%E8%81%94_20230831123333.png"
mode="widthFix"></image>
</view>
</view>
<view v-if="!getLoading">
<!-- <j-navbar :isBack="false">金武联驾考</j-navbar> -->
<u-sticky bgColor="#fff">
<u-tabs :list="categoryList" :current="curTab" :scrollable="false" @change="changeCategory"></u-tabs>
</u-sticky>
<view class="m10tb" v-if="activityList&&activityList.length">
<u-swiper class="acticity" keyName="image" :list="activityList" @click="handleToActivity"></u-swiper>
</view>
<view style="background-color: rgb(245, 245, 245);">
<template v-if="subject=='1' || subject=='4'">
<Subject1 :subject="subject" :rightList="rightList" :wrongList="wrongList" />
</template>
<template v-else>
<Subject2 :subject="subject" ref="subjectRef" />
</template>
</view>
</view>
</view>
</template>
<script>
import { mapState,mapActions } from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import storage from '@/jtools/storage';
import Subject1 from "./components/Subject1";
import Subject2 from "./components/Subject2";
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import useUserStore from '@/jtools/store/user'
import storage from '@/jtools/storage';
import {
querySysConfigList,
} from '@/jtools/api/question';
import Subject1 from "./components/Subject1";
import Subject2 from "./components/Subject2";
// import {
// queryActivityList
// } from '@/jtools/api/activity';
export default {
components: {Subject1,Subject2},
components: {
Subject1,
Subject2
},
data() {
return {
tIndex:0,
searchValue:'',
cityName:'',
categoryList:[{
name:'科目1'
},{
name:'科目2'
},{
name:'科目3'
},{
name:'科目4'
}]
};
},
onLoad() {
},
methods:{
...mapActions(useQuestionStore,['getOrderQuestion']),
//切换科目
changeCategory(val){
this.tIndex=val.index
if(this.tIndex==0){
this.getOrderQuestion('1')
}else if(this.tIndex==3){
this.getOrderQuestion('4')
}
},
}
}
return {
getLoading: true,
show: false,
subject: storage.get('curSubject') || '1',
curTab: 0,
searchValue: '',
cityName: '',
categoryList: [],
rightList: storage.get(`rightList_subject${this.subject}`) || [],
wrongList: storage.get(`wrongList_subject${this.subject}`) || [],
activityList: []
};
},
onShow() {
setTimeout(() => {
this.getLoading = false
this.show = true
}, 100);
this.getSubjectConfig()
if (this.subject == '1' || this.subject == '4') {
this.rightList = storage.get(`rightList_subject${this.subject}`) || []
this.wrongList = storage.get(`wrongList_subject${this.subject}`) || []
}
if (this.subject == '2' || this.subject == '3') {
this.$refs.subjectRef.getDiverType()
}
// this.queryActivityList()
},
onHide() {
this.show = false
},
computed: {
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1", "curSubject", "orderQuestion_subject1",
"orderQuestion_subject4"
]), //映射函数取出tagslist
},
methods: {
...mapActions(useQuestionStore, ['getOrderQuestion_sub4', 'getOrderQuestion_sub1', 'changeSubject']),
//获取科目配置
getSubjectConfig() {
const carTypeId = storage.get('carType') || '1001'
querySysConfigList(carTypeId, 'Subject').then(resp => {
if (resp.code === '0000') {
this.categoryList = resp.data.map(item => {
return {
...item,
name: item.configItemName
}
})
this.subject = storage.get('curSubject') || '1',
this.curTab = this.categoryList.findIndex(item => item.configItemCode == this.subject) || 0
}
})
},
//切换科目
async changeCategory(val) {
this.subject = val.configItemCode
this.changeSubject(this.subject)
if (this.subject == '1' || this.subject == '4') {
this.rightList = storage.get(`rightList_subject${this.subject}`) || []
this.wrongList = storage.get(`wrongList_subject${this.subject}`) || []
} else {
setTimeout(() => {
this.$refs.subjectRef.getDiverType()
}, 100)
}
},
//查询活动列表
queryActivityList() {
queryActivityList({
schoolId: useUserStore().userInfo?.schoolId || ''
}).then(resp => {
this.activityList = resp.data.map(item => ({
...item,
image: 'https://jwl.ahduima.com' + item.image
}));
})
},
// 去活动
handleToActivity(index) {
let detailId;
this.activityList.find((item, index1) => {
if (index === index1) {
detailId = item.detailId;
}
})
uni.navigateTo({
url: '/pages/index/activity?detailId=' + detailId,
})
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .u-tabs__wrapper__nav__line {
background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%) !important;
bottom: 14rpx !important;
}
</style>
::v-deep .u-tabs__wrapper__nav__line {
background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%) !important;
bottom: 14rpx !important;
}
</style>

View File

@@ -0,0 +1,47 @@
<template>
<view class="wp100 flex jc-c bc-fff " style="height: 100vh;">
<view class="mt50 text-center flex ai-c" style="flex-direction: column;">
<view style="width: 211rpx;" class="text-center">
<image style="width: 211rpx;height: 222rpx;;" src="../../static/image/index/paysucess.jpg"></image>
</view>
<view style="width: 385rpx;" class="text-center">
<view class="fw600 fs16 cor-000 mb10">支付成功</view>
<tetx class="fs14 cor-666">恭喜您您已成功购买VIP课程赶紧去学习吧</tetx>
</view>
<button class="btn mt10" @click="goBack">去学习</button>
</view>
</view>
</template>
<script>
import useUserStore from '@/jtools/store/user'
export default{
data(){
return{
}
},
onLoad(){
useUserStore().searchUserVip()
},
methods:{
goBack(){
uni.switchTab({
url:"/pages/index/index"
})
}
}
}
</script>
<style scoped>
.btn{
width: 260rpx;
height: 80rpx;
line-height: 80rpx;
text-align: center;
color:#00B74F;
border: 2px solid #00B74F;
border-radius: 40rpx;
}
</style>

View File

@@ -0,0 +1,139 @@
<template>
<view>
<u-loading-page :loading="getLoading" loading-text="题库更新中..."></u-loading-page>
<view class="relative" v-if="!getLoading"
style="width: 100%;background-image: url(https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E8%80%83%E5%89%8D%E5%AF%86%E5%8D%B7_20230904212623.png);background-size: 100% 100%;height: 100vh;">
<view style="position: absolute;top: 320px;" class="wp100 p35lr flex jc-sb ai-c">
<view class="paper_item" @tap="toExam({isExam1:'1'})">
<view class="topTitle">
秘卷一
</view>
<view class="bottom">
<text class="wenzi">新规考点提炼</text>
<view class="wp100 p5 mt15">
<view class="btn">
去考试
</view>
</view>
</view>
</view>
<view class="paper_item" @tap="toExam({isExam2:'1'})">
<view class="topTitle">
秘卷二
</view>
<view class="bottom">
<text class="wenzi">精选高频考试</text>
<view class="wp100 p5 mt15">
<view class="btn">
去考试
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import storage from '@/jtools/storage';
import {
queryQuestionId,
getTestQuestionId
} from '@/jtools/api/question';
export default {
data() {
return {
subject:'1'
}
},
onLoad(op){
if(op.subject){
this.subject=op.subject
}
},
computed: {
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1", "curSubject","version"]), //映射函数取出tagslist
getLoading() {
return this.loading_subject4 && this.loading_subject1
}
},
methods: {
...mapActions(useQuestionStore, ['getOrderQuestion_sub4', 'getOrderQuestion_sub1', 'changeSubject']),
toExam(param) {
queryQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
...param
}).then(async (resp) => {
if (resp.code === '0000') {
const arr = resp.data
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/practiceExams?title=考前秘卷&subject=" + this.subject + "&questionIdList=" + listJson
})
}
})
},
}
}
</script>
<style scoped>
.paper_item {
width: 287rpx;
height: 320rpx;
/* border: 4px solid #F8A42C; */
border-radius: 16rpx;
}
.topTitle {
width: 100%;
height: 85rpx;
line-height: 85rpx;
text-align: center;
background: linear-gradient(90deg, #E66501 0%, #F8A42C 100%);
border-radius: 16rpx 16rpx 0rpx 0rpx;
font-size: 48rpx;
font-family: PingFang SC;
font-weight: 600;
color: #FFFFFF;
}
.bottom {
padding-top: 15px;
width: 100%;
height: 235rpx;
border-radius: 0rpx 0rpx 16rpx 16rpx;
border-bottom: 4px solid #F8A42C;
border-left: 4px solid #F8A42C;
border-right: 4px solid #F8A42C;
text-align: center;
}
.wenzi {
font-size: 40rpx;
font-family: PingFang SC;
font-weight: 600;
color: #7D4310;
line-height: 48rpx;
}
.btn {
width: 246rpx;
height: 76rpx;
text-align: center;
line-height: 76rpx;
color: #fff;
background: linear-gradient(0deg, #E66501 0%, #F8A42C 100%);
box-shadow: 0rpx 2rpx 21rpx 0rpx #F7A12A;
border-radius: 38rpx;
}
</style>

View File

@@ -0,0 +1,83 @@
<template>
<view class="bc-fff hp100">
<view class="wp100 p14 flex ai-c jc-c">
<view class="text-center">
<view style="width: 64px;height: 64px;border-radius: 50%;overflow: hidden;margin-bottom: 10px;">
<u-avatar class="br-p50 overflow-h" :size="64" mp-avatar shape="circle"></u-avatar>
</view>
<text class="fs18">{{user.userName}}{{ user.userId }}</text>
</view>
</view>
<view class="p14">
<view class="wp100 p14lr p20tb mb14" style="background-color: rgb(248, 248, 248);border-radius: 20rpx;">
<view class="flex ai-c jc-sb pb10">
<text style="color: rgb(175, 175, 175);">考试类型</text>
<text>{{carName}}</text>
</view>
<view class="flex ai-c jc-sb pb10">
<text style="color: rgb(175, 175, 175);">考试标准</text>
<text>{{subject=='1'?100:50}}/45分钟</text>
</view>
<view class="flex ai-c jc-sb pb10">
<text style="color: rgb(175, 175, 175);">合格标准</text>
<text>90分及格(满分100分)</text>
</view>
<view class="flex ai-c jc-sb">
<text style="color: rgb(175, 175, 175);">出题规则</text>
<text>根据公安部出题规则组卷</text>
</view>
</view>
<text>模拟考试不能修改答案每错1题扣{{subject=='1'?1:2}}错题累计超过{{subject=='1'?10:5}}考试不通过</text>
</view>
<view class="p14lr wp100" style="margin-top: 30px;">
<u-button :customStyle="{width: '100%',borderRadius:'40rpx',backgroundColor:'#05C341',color:'#fff'}" text="开始考试"
@click="submit" />
</view>
<view>
</view>
</view>
</template>
<script>
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useUserStore from '@/jtools/store/user'
import storage from '@/jtools/storage';
import useQuestionStore from '@/jtools/store/question' //引入store
export default {
data() {
return {
carName:storage.get('carName') ||'小车C1/C2/C3',
questionList: '',
subject:'1',
}
},
onLoad(op) {
if (op.questionIdList) {
this.questionList = op.questionIdList
}
if(op.subject){
this.subject = op.subject
}
},
computed: {
...mapState(useQuestionStore, ["currentCarName"]), //映射函数取出tagslist
user() {
return useUserStore().userInfo
},
},
methods: {
submit(){
uni.navigateTo({
url: "/pages/questionBank/practiceExams?title=模拟考试&subject=" + this.subject + "&questionIdList=" + this.questionList
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,356 @@
<template>
<view class="ml40 p10lr hp100 bc-f5" style="overflow-y: auto;">
<view class="flex" style="align-items: stretch;">
<view class="left hp100">
<view class="fl1 flex" style="align-items: stretch;">
<view class="info">
<view class="flex ai-c jc-c mr10 fs16" style="border: 1px solid #999;height: 32px;">
第01考台
</view>
<view class="mt10 p10tb" style="background-color: rgb(177, 222, 255);">
<view style="margin: 0 auto;width: 64px;">
<u-avatar :size="64" mp-avatar shape="circle"></u-avatar>
</view>
</view>
<view class="p10" style="background-color: rgb(235, 235, 235);">
<view class="flex ai-c">
<text class="fs12 cor-333">姓名</text>
<view class="fl1 info-box">{{ user.userName }}{{ user.userId }}</view>
</view>
<view class="flex ai-c mt5">
<text class="fs12 cor-333">类型</text>
<view class="fl1 info-box">小车</view>
</view>
<view class="flex ai-c mt5">
<text class="fs12 cor-333">科目</text>
<view class="fl1 info-box">科目一</view>
</view>
</view>
</view>
<view class="fl1 question-box">
<view class="fs14 cor-000">
{{questionIndex}} {{question.question}}
</view>
<view v-if="question.type != 1" v-for="(item, idx) in question.optionList" :key="idx"
class="mt5 fs14 cor-000">
{{item.op}}: {{item.opDesc}}
</view>
</view>
</view>
<view class="ans-box">
<view class="flex ai-c">
<view class="time">
<!-- <text class="mt7">45:00</text> -->
<u-count-down ref="countDown" :time="timeCount" format="mm:ss" @change="e=>this.time=e"
@finish="timeFinish"></u-count-down>
</view>
<view class="ml20 fs16 cor-333 fwb">
您的答案
</view>
</view>
<view v-if="question.type==1" class="flex">
<button class="btn" :class="{ done: question.yourAnswer==1 }" @tap="handleAnswer(1)"></button>
<button class="btn" :class="{ done: question.yourAnswer==2 }" @tap="handleAnswer(2)">×</button>
</view>
<view v-else class="flex">
<template v-for="(item,index) in question.optionList" :key="index">
<button class="btn" :class="{ done: question.yourAnswer.includes(index+1) }"
@tap="handleAnswer(index+1)">{{['A','B','C','D','E','F','G'][index]}}</button>
</template>
</view>
</view>
</view>
<view class="right" style="border: 1px solid #999;;">
<u-grid border :col="subject==1?10:5">
<u-grid-item v-for="(listItem,listIndex) in list" :key="listIndex" style="box-sizing: border-box;">
<view class="q-item" :class="{ 'current-question': questionIndex==listIndex+1, done: listItem.yourAnswer }"
@tap="questionIndex=listIndex+1">{{listIndex+1}}</view>
</u-grid-item>
</u-grid>
</view>
</view>
<view class="operate-box">
<view class="fl1">
<view class="fs16" style="height: 20px;line-height: 20px;color: rgb(232, 72, 75);">
操作提示{{['','判断题','单选题','多选题'][question.type]}}
</view>
<view class="fs14 cor-333" style="height: 20px;line-height: 20px;">
本题是{{getDesc(question.type)}}
</view>
</view>
<view class="flex">
<button :disabled="questionIndex==1" class="btn" @tap="questionIndex--">上一题</button>
<button :disabled="questionIndex==list.length" class="btn" @tap="questionIndex++">下一题</button>
<button class="btn" @tap="handleConfirm">交卷</button>
</view>
</view>
<view class="img-box">
<image style="height: 100%;" mode="heightFix" :src="question.imageUrl"></image>
</view>
</view>
</template>
<script>
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import useUserStore from '@/jtools/store/user'
import {
getTestQuestion,
submitTest
} from '@/jtools/api/question';
import storage from '@/jtools/storage';
export default {
data() {
return {
subject:'1',
questionIndex: 1,
list: [],
mutiAns: []
}
},
computed: {
...mapState(useQuestionStore, ["orderQuestion_subject1", "orderQuestion_subject4", "version"]), //映射函数取出tagslis
user() {
return useUserStore().userInfo
},
question() {
if (this.questionIndex != 0 && this.list.length) {
return this.list[this.questionIndex - 1]
} else {
return {}
}
},
timeCount() {
return this.subject == 1 ? 60 * 60 * 1000 : 45 * 60 * 1000
}
},
onShow() {
this.fz()
},
onLoad(option) {
this.subject = option.subject || 1
if(option.questionIdList){
const idList=JSON.parse(option.questionIdList)
let arr = this[`orderQuestion_subject${this.subject}`].filter(qItem=>idList.includes(qItem.questionId))
this.list = arr.map(it => ({
...it,
yourAnswer: ''
}))
}
},
methods: {
fz() {
wx.setPageOrientation({
orientation: 'landscape'
});
},
// _getList() {
// getTestQuestion({
// carTypeId: storage.get('carType') || '1001',
// subject: this.subject
// }).then(resp => {
// if (resp.code === '0000') {
// this.list = resp.data.map(it => ({
// ...it,
// yourAnswer: ''
// }))
// }
// })
// },
handleAnswer(index) {
// 如果是多选
let q = this.list[this.questionIndex - 1]
if (q.type == 3) {
let arr = q.yourAnswer ? q.yourAnswer.split(',') : []
arr.includes(index + '') ? arr = arr.filter(it => it != (index + '')) : arr.push(index)
this.list[this.questionIndex - 1].yourAnswer = arr.join(',')
} else {
this.list[this.questionIndex - 1].yourAnswer = index + ''
}
},
getDesc(type) {
let tt1 = ['', '判断题,', '单选题,', '多选题,'][type]
let tt2 = ['', '请判断对错!', '请在备选答案中选择你认为正确的答案!', '请在备选答案中选择多个你认为正确的答案!'][type]
return tt1 + tt2
},
handleConfirm() {
const wdLength = this.list.filter(it => !it.yourAnswer).length
if (wdLength) {
uni.showModal({
title: '考试确认窗口',
content: `您还有${wdLength}题未答,是否确认交卷?`,
confirmText: '确认交卷',
cancelText: '继续考试',
success: (res) => {
if (res.confirm) {
this.toSubmit()
}
}
})
} else {
uni.showModal({
title: '考试确认窗口',
content: `是否确认交卷?`,
confirmText: '确认交卷',
cancelText: '继续考试',
success: (res) => {
if (res.confirm) {
this.toSubmit()
}
}
})
}
},
timeFinish() {
uni.showToast({
title: "考试结束,将为您自动交卷~",
icon: 'none'
})
setTimeout(() => {
this.toSubmit()
}, 1000)
},
toSubmit() {
const restTime = this.time.hours * 60 * 60 + this.time.minutes * 60 + this.time.seconds
const trueCount = this.list.reduce((pre, cur) => {
const ya = cur.trueAnswer.replace('A', '1').replace('B', '2').replace('C', '3').replace('D', '4').replace('E', '5').replace('F', '6').replace('G', '7')
const isTrue = ya == cur.yourAnswer.replace(/,/g, '')
return pre + 1 * (isTrue ? 1 : 0)
}, 0)
const score = (trueCount / this.list.length * 100).toFixed(0)
submitTest({
"carTypeId": storage.get('carType') || '1001',
"score": score,
"testTime": 60 * 60 - restTime,
subject: this.subject
}).then(resp => {
uni.showToast({
title: '考试结束!',
icon: 'none',
complete() {
uni.navigateBack()
}
})
})
}
},
}
</script>
<style lang="scss" scoped>
.left {
flex: 1;
display: flex;
flex-direction: column;
.info {
width: 100px;
display: flex;
flex-direction: column;
.info-box {
margin-left: 5px;
padding-left: 5px;
height: 28px;
line-height: 28px;
box-shadow: inset 2px 2px 5px #babecc, inset -5px -5px 10px #fff;
font-size: 10px;
color: #333;
}
}
.question-box {
position: relative;
padding: 10px;
border-top: 1px solid #999;
border-left: 1px solid #999;
}
.ans-box {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
border-top: 1px solid #999;
.time {
position: relative;
display: flex;
width: 90px;
height: 32px;
line-height: 16px;
justify-content: center;
align-items: center;
font-size: 14px;
color: #333;
border: 1px solid #999;
&::before {
content: '剩余时间';
position: absolute;
left: 6px;
top: 0;
background-color: #f5f5f5;
font-size: 10px;
color: #333;
transform: translateY(-50%);
}
}
}
}
.right {
width: 270px;
.q-item {
width: 28px;
height: 27px;
font-size: 10px;
line-height: 27px;
text-align: center;
}
}
.operate-box {
padding-left: 10px;
display: flex;
justify-content: space-between;
align-items: center;
height: 50px;
border-top: 2px solid rgb(43, 102, 167);
border-bottom: 2px solid rgb(43, 102, 167);
border-left: 1px solid #999;
border-right: 1px solid #999;
}
.btn {
margin-right: 10px;
height: 30px;
line-height: 30px;
// background-color: rgb(244, 243, 239);
font-size: 14px;
box-shadow:
0 0 4px rgba(0, 0, 0, .4),
// -7px -7px 12px rgba(255, 255, 255, .9);
}
.img-box {
height: 120px;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #999;
}
.current-question {
background-color: #93F0E4;
}
.done {
background-color: #33FF66;
}
</style>

View File

@@ -1,38 +1,75 @@
<template>
<view class="relative" style="height: 100vh;">
<image style="width: 100%;height: 600rpx;" src="../../static/image/index/vip_bg.jpg"></image>
<view class="p14">
<view class="flex jc-sb ai-c">
<view class="option_tem relative" :class="checkedPrice===item.priceId?'checked_item':''" v-for="(item,index) of priceList" :key="index" @click="checkPrice(item.priceId,item.money)">
<text class="fw600 fs16 cor-333">{{item.title}}</text>
<view class="mt5">
<text class="fs14" style="color: #FF6E02;">¥</text>
<text class="fs30 fw600" style="color: #FF6E02;">{{item.money}}</text>
</view>
<text class="fs12 cor-999">长期有效</text>
<view class="bottom_box fs12 cor-333" :class="checkedPrice===item.priceId?'checked_bottom':''">赠送vip题库</view>
<view class="tag" v-if="item.all">
<text style="transform:scale(0.83);">合买更优惠</text>
<view style="height: 100%;overflow: scroll;background-color: #fff;">
<image style="width: 100%;height: 600rpx;" src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/vip%E9%A2%98%E5%BA%93_20230911211532.png"></image>
<view style="margin-bottom: 100px;">
<view class="flex jc-fa ai-c wp100 p14">
<view style="width: 33.3%;" v-for="(item, index) of priceList" :key="index">
<view class="option_tem relative" :class="checkedId === item.memberId ? 'checked_item' : ''" @click="checkPrice(item.memberId, item.price)">
<text class="fw600 fs12 cor-333">{{ item.memberName }}</text>
<view class="mt5" v-if="!isIOS">
<text class="fs14" style="color: #FF6E02;">¥</text>
<text class="fs30 fw600" style="color: #FF6E02;">{{ item.price }}</text>
</view>
<view v-else class="mt5">
<text class="fs14" style="color: #FF6E02;">iOS暂不支持</text>
</view>
<text class="fs12 cor-999">一年有效</text>
<!-- <view class="bottom_box fs12 cor-333" :class="checkedId===item.memberId?'checked_bottom':''">赠送vip题库</view> -->
<view class="tag" v-if="item.all">
<text style="transform:scale(0.83);">合买更优惠</text>
</view>
</view>
</view>
</view>
<view class="mt15 intr_box">
<view class="fw600 fs16 cor-000">免费获赠<text style="color: #FF6E02;">价值68元</text>的VIP题库</view>
<view class="flex ai-c jc-sb mt15">
<view class="flex ai-c">
<image style="width: 63rpx;height: 63rpx;margin-right: 5px;" src="../../static/image/index/vip500.png"></image>
<view class="vip_item">含精简500题</view>
</view>
<view class="flex ai-c">
<image style="width: 63rpx;height: 63rpx;margin-right: 5px;" src="../../static/image/index/vipmijuan.png"></image>
<view class="vip_item">含考前密卷2套</view>
</view>
</view>
<view class="intr_box p14">
<view class="fw600 fs16 cor-000">尊享以下权益</view>
<view class="flex ai-c jc-sb mt15" v-if="subject == '1' || subject == '4'">
<view class="text-center" style="width: 33%">
<view class="wp100 flex ai-c jc-c mb5">
<image style="width: 63rpx;height: 63rpx;margin-right: 5px;" src="../../static/image/index/vip500.png"></image>
</view>
<text>精简{{ titleNum }}</text>
</view>
<view class="text-center" style="width: 33%;">
<view class="wp100 flex ai-c jc-c mb5">
<image style="width: 63rpx;height: 63rpx;margin-right: 5px;" src="../../static/image/index/vip_trueRoom.png"></image>
</view>
<text>真实考场模拟</text>
</view>
<view class="text-center" style="width: 33%;">
<view class="wp100 flex ai-c jc-c mb5">
<image style="width: 63rpx;height: 63rpx;margin-right: 5px;" src="../../static/image/index/vipmijuan.png"></image>
</view>
<text>考前密卷</text>
</view>
</view>
<view v-else>
<view class="flex ai-c jc-c mt15">
<view class="flex ai-c">
<image style="width: 63rpx;height: 63rpx;margin-right: 5px;" src="../../static/image/index/vip_ksxj.png"></image>
<view class="vip_item">考试项目详解</view>
</view>
</view>
<view class="flex ai-c mt20">
<view class="contain-box relative">
<image class="contain-box" src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E5%B0%8F%E8%BD%A6_20230911211545.png"></image>
</view>
<view class="ml15" style="text-align: left;">
<view class="cor-333 fw600">考试项目详解</view>
<view class="fs15 mt10" style="color: #9F826C ;">考试实操技巧讲解事半功倍</view>
</view>
</view>
</view>
</view>
<view class="wp100 mt15" v-if="subject == '1' || subject == '4'">
<image class="wp100" mode="widthFix" :src="picUrl"></image>
</view>
</view>
</view>
<view class="wp100 p14" style="position: absolute;left: 0;bottom:20px">
</view>
<view v-if="!isIOS" class="wp100 p14" style="position: absolute;left: 0;bottom:20px" @tap="handlePay()">
<view class="sub_btn flex ai-c jc-sb">
<text class="cor-fff fs14">¥<text class="fs24 cor-fff">{{nowPrice}}</text></text>
<text class="cor-fff fs14">¥<text class="fs24 cor-fff">{{ nowPrice }}</text></text>
<image style="width: 276rpx;height: 88rpx;margin-top: -5px;" src="../../static/image/index/buy.png"></image>
</view>
</view>
@@ -40,108 +77,197 @@
</template>
<script>
export default {
data(){
return{
nowPrice:168,
checkedPrice:0,
priceList:[{
priceId:0,
title:'科一精品课',
money:168,
all:false
},
{
priceId:1,
title:'科四精品课',
money:168,
all:false
},
{
priceId:2,
title:'科一+科四',
money:268,
all:true,
}]
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import { getVipList } from '@/jtools/api/vip'
import { querySysConfig } from '@/jtools/api/question';
import storage from '@/jtools/storage';
import Pay from '@/jtools/pay/index.js';
import useUserStore from '@/jtools/store/user'
export default {
data() {
return {
picUrl: '',
titleNum: 500,
subject: '1',
loading: true,
nowPrice: 168,
checkedId: 0,
priceList: [],
order: {
money: 0,
description: '会员充值'
},
isIOS: true
}
},
onLoad(op) {
this.isIOS = this.$platform.device().includes('ios')
if (op.subject) {
this.subject = op.subject
}
this.loading = true
this.getVipList()
this.getWXOpenId()
this.getTitle()
this.getPic()
this.$set(this.order, 'userId', this.userInfo.userId);
},
computed: {
...mapState(useUserStore, ["userInfo"])
},
methods: {
getPic() {
const currentCartype = storage.get('carType') || '1001'
querySysConfig(currentCartype, 'VipDescImageUrl').then(res => {
this.picUrl = JSON.parse(res.data.configJson).url
})
},
getTitle() {
const carId = storage.get('carType') || '1001'
querySysConfig(carId, 'SimplifyQuestionNum').then(resp => {
if (resp.code === '0000') {
const list = JSON.parse(resp.data.configJson)
this.titleNum = list.find(item => item.subject == this.subject).num
}
})
},
async handlePay() {
if (this.loading) {
this.loading = false
await this.getWXOpenId()
new Pay('wechat', this.order);
this.loading = true
}
},
methods:{
checkPrice(val,price){
this.checkedPrice=val
this.nowPrice=price
}
}
getWXOpenId() {
const that = this
uni.login({
success(res) {
that.$set(that.order, 'code', res.code);
}
})
},
getVipList() {
getVipList({
carTypeId: storage.get('carType') || '1001',
subject: this.subject
}).then(resp => {
if (resp.code === '0000') {
this.priceList = resp.data
this.checkedId = this.priceList[0].memberId
this.order.outTradeNo = this.priceList[0].memberId
this.order.money = this.priceList[0].price
this.nowPrice = this.priceList[0].price
this.priceList.forEach(item => {
if (item.subjects.length > 1) {
item.all = true
}
})
}
})
},
checkPrice(val, price) {
this.checkedId = val
this.order.outTradeNo = val
this.nowPrice = price
this.order.money = price
}
}
}
</script>
<style scoped>
.option_tem{
width: 220rpx;
height: 241rpx;
text-align: center;
background: #FFFFFF;
border: 2px solid #D8D8D8;
border-radius: 16rpx 46rpx 16rpx 16rpx;
padding: 14px;
}
.checked_item{
width: 228rpx;
background: #FFF0E5;
border: 4px solid #FF6E02;
}
.bottom_box{
width: 214rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
background: rgb(239,239,239);
border-radius: 0 0 16rpx 16rpx;
position: absolute;
bottom: 0;
left: 0;
}
.checked_bottom{
width: 218rpx;
border-radius: 0 0 16rpx 12rpx;
background-color: #FF6E02;
color:#fff
}
.tag{
width: 122rpx;
height: 36rpx;
background: linear-gradient(90deg, #E66501 0%, #F8A42C 100%);
border-radius: 8rpx 20rpx 8rpx 8rpx;
line-height: 36rpx;
text-align: center;
font-size: 12px;
color: #FFFC27;
position: absolute;
left: 10rpx;
top:-18rpx
}
.intr_box{
width: 100%;
text-align: center;
padding: 40rpx;
background: #FFF0E5;
border-radius: 16rpx;
}
.vip_item{
width: 208rpx;
height: 54rpx;
line-height: 54rpx;
text-align: center;
font-size: 14px;
background: #F3D7C2;
border-radius: 0rpx 10rpx 10rpx 10rpx;
}
.sub_btn{
width:100%;
height: 110rpx;
border: 4px solid #F59B26;
background: linear-gradient(0deg, #E66501 0%, #F8A42C 100%);
box-shadow: 0rpx 16rpx 20rpx 1rpx rgba(245,155,38,0.78);
border-radius: 55rpx;
padding: 14rpx;
}
.option_tem {
width: 220rpx;
height: 241rpx;
text-align: center;
background: #FFFFFF;
border: 2px solid #D8D8D8;
border-radius: 16rpx 46rpx 16rpx 16rpx;
padding: 14px;
}
.checked_item {
background: #FFF0E5;
border: 4px solid #FF6E02;
}
.bottom_box {
width: 214rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
background: rgb(239, 239, 239);
border-radius: 0 0 16rpx 16rpx;
position: absolute;
bottom: 0;
left: 0;
}
.checked_bottom {
width: 218rpx;
border-radius: 0 0 16rpx 5rpx;
background-color: #FF6E02;
color: #fff
}
.tag {
padding: 0 5px;
height: 36rpx;
background: linear-gradient(90deg, #E66501 0%, #F8A42C 100%);
border-radius: 8rpx 20rpx 8rpx 8rpx;
line-height: 36rpx;
text-align: center;
font-size: 12px;
color: #FFFC27;
position: absolute;
left: 10rpx;
top: -18rpx
}
.intr_box {
width: 100%;
text-align: center;
padding: 40rpx;
background: #FFF0E5;
border-radius: 16rpx;
}
.vip_item {
width: 208rpx;
height: 54rpx;
line-height: 54rpx;
text-align: center;
font-size: 14px;
background: #F3D7C2;
border-radius: 0rpx 10rpx 10rpx 10rpx;
}
.sub_btn {
width: 100%;
height: 110rpx;
border: 4px solid #F59B26;
background: linear-gradient(0deg, #E66501 0%, #F8A42C 100%);
box-shadow: 0rpx 16rpx 20rpx 1rpx rgba(245, 155, 38, 0.78);
border-radius: 55rpx;
padding: 14rpx;
}
.contain-box {
width: 344rpx;
height: 196rpx;
background: #00B74F;
border-radius: 16rpx;
}
.play_btn_2 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 165.5rpx;
top: 78rpx
}
</style>

View File

@@ -1,22 +1,22 @@
<template>
<view class="content">
<view class="header">
<image src="/static/image/login/logo.jpg" mode="widthFix"></image>
<view class="mt21 fs16 cor-333 fwb text-center">欢迎使用金武驾考</view>
<image src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E9%87%91%E6%AD%A6%E8%81%94_20230831123333.png" mode="widthFix"></image>
<view class="mt21 fs16 cor-333 fwb text-center">欢迎使用金武驾考</view>
</view>
<view class="list">
<view class="list-call">
<u-input class="sl-input" border="none" v-model="login.phone" type="number" maxlength="11"
<u-input class="sl-input" border="none" v-model="loginForm.phone" type="number" maxlength="11"
placeholder="输入手机号" />
</view>
<view class="list-call">
<u-input class="sl-input" v-model="login.code" type="text" maxlength="6" border="none" placeholder="输入验证码">
<!-- <view class="list-call">
<u-input class="sl-input" v-model="loginForm.code" type="text" maxlength="6" border="none" placeholder="输入验证码">
<template #suffix>
<text class="fs14 mr10" style="color: #05C341;" @tap="getCode">{{countDown==0?'获取验证码':countDown}}</text>
<text class="fs14 mr10" style="color: #05C341;" @tap="getCode">{{ countDown == 0 ? '获取验证码' : countDown }}</text>
</template>
</u-input>
</view>
</view> -->
</view>
<view class="button-login" @tap="bindLogin()">
@@ -27,136 +27,142 @@
</template>
<script>
import {
isPhone
} from '@/jtools/utils/validate.js'
import {
getCode,
login
} from '@/jtools/api/login'
import useUserStore from '@/jtools/store/user'
export default {
data() {
return {
login: {
phone: '',
code: ''
},
countDown: 0,
js: undefined
};
},
onShow() {
if(useUserStore().isLogin) {
this.toHome()
}
},
methods: {
getCode() {
if (isPhone(this.login.phone) && this.countDown == 0) {
getCode({
phone: this.login.phone
}).then(resp => {
// if (resp.code == '0000') {
uni.showToast({
title: '发送成功!',
icon: 'none'
})
this.countDown = 60
this.js = setInterval(() => {
this.countDown--;
if (this.countDown == 0) {
this.clear()
}
}, 1000)
// }
import {
isPhone
} from '@/jtools/utils/validate.js'
import {
getCode,
login
} from '@/jtools/api/login'
import useUserStore from '@/jtools/store/user'
import storage from '@/jtools/storage';
export default {
data() {
return {
loginForm: {
phone: '',
code: '000000'
},
countDown: 0,
js: undefined
};
},
onShow() {
if (useUserStore().isLogin) {
this.toHome()
}
},
methods: {
getCode() {
if (isPhone(this.loginForm.phone) && this.countDown == 0) {
getCode({
phone: this.loginForm.phone
}).then(resp => {
// if (resp.code == '0000') {
uni.showToast({
title: '发送成功!',
icon: 'none'
})
}
},
clear() {
clearInterval(js)
this.js = null
this.countDown = 0
},
bindLogin() {
if(isPhone(this.login.phone) && this.login.code) {
useUserStore().login(this.login).then(resp => {
if(resp.userId) {
this.toHome()
this.countDown = 60
this.js = setInterval(() => {
this.countDown--;
if (this.countDown == 0) {
this.clear()
}
})
}
},
toHome() {
uni.switchTab({
url: '/pages/index/index'
}, 1000)
// }
})
}
},
clear() {
clearInterval(js)
this.js = null
this.countDown = 0
},
bindLogin() {
if (isPhone(this.loginForm.phone) && this.loginForm.code) {
let params = { ...this.loginForm }
if (storage.get('companyId')) {
params.id = storage.get('companyId')
}
useUserStore().login(params).then(resp => {
if (resp.userId) {
useUserStore().getUserInfo()
useUserStore().searchUserVip()
this.toHome()
}
})
}
},
toHome() {
uni.switchTab({
url: '/pages/index/index'
})
}
}
}
</script>
<style>
page {
background-color: #fff;
}
page {
background-color: #fff;
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
}
.header {
margin-top: 166rpx;
margin-left: auto;
margin-right: auto;
letter-spacing: 10rpx;
}
.header {
margin-top: 166rpx;
margin-left: auto;
margin-right: auto;
letter-spacing: 10rpx;
}
.header image {
width: 383rpx;
}
.header image {
width: 383rpx;
}
.list {
display: flex;
flex-direction: column;
padding-top: 120rpx;
padding-left: 90rpx;
padding-right: 90rpx;
}
.list {
display: flex;
flex-direction: column;
padding-top: 120rpx;
padding-left: 90rpx;
padding-right: 90rpx;
}
.list-call {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 100rpx;
color: #333333;
border-bottom: 0.5px solid #e2e2e2;
}
.list-call {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 100rpx;
color: #333333;
border-bottom: 0.5px solid #e2e2e2;
}
.list-call .sl-input {
flex: 1;
text-align: left;
font-size: 32rpx;
margin-left: 16rpx;
}
.button-login {
color: #FFFFFF;
font-size: 34rpx;
width: 560rpx;
height: 100rpx;
background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%);
border-radius: 50rpx;
line-height: 100rpx;
text-align: center;
margin-top: 100rpx;
margin-left: auto;
margin-right: auto;
}
.list-call .sl-input {
flex: 1;
text-align: left;
font-size: 32rpx;
margin-left: 16rpx;
}
.button-login {
color: #FFFFFF;
font-size: 34rpx;
width: 560rpx;
height: 100rpx;
background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%);
border-radius: 50rpx;
line-height: 100rpx;
text-align: center;
margin-top: 100rpx;
margin-left: auto;
margin-right: auto;
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<view>
<view class="p14">
<view class="wp100 p14lr p20tb bc-fff br8 mb10 relative" style="box-sizing: border-box;" :class="checkedCar==item.carTypeId?'checked':''" v-for="(item,index) of carTypeList" :key="index" @click="changeType(item)">{{item.carName}}{{item.remark}}
<view class="p5 cor-fff fs12 br4" style="background-color:#05C341;position: absolute;right: -1rpx;top:-1rpx" v-if="checkedCar==item.carTypeId">已选</view>
</view>
<view class="wp100" style="margin-top: 40px;">
<u-button :customStyle="{width: '100%',borderRadius:'40rpx',backgroundColor:'#05C341',color:'#fff'}" text="确定"
@click="submit" />
</view>
<u-modal :show="show" title="提示" content="切换题库后上一个题库练习记录将会全部清空,确定要切换吗" showCancelButton @confirm="confirmSubmit" @cancel="cancel"></u-modal>
</view>
</view>
</template>
<script>
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import {
getCarTypeList,
} from '@/jtools/api/index';
import storage from '@/jtools/storage';
import useQuestionStore from '@/jtools/store/question' //引入store
export default{
data() {
return{
show:false,
carTypeList:[],
checkedCar: storage.get('carType') ||'1001',
checkedCarName:storage.get('carName') || '小车C1/C2/C3'
}
},
mounted() {
this.getCarTypeList()
},
computed:{
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1","curSubject"]), //映射函数取出tagslist
getLoading() {
return this.loading_subject4 && this.loading_subject1
}
},
watch:{
getLoading(newVal){
console.log(newVal);
if(newVal){
uni.hideLoading()
uni.showToast({
title:'切换成功!'
})
this.cancel()
}
}
},
methods:{
getCarTypeList(){
getCarTypeList().then(resp=>{
if(resp.code==='0000'){
this.carTypeList=resp.data
}
})
},
changeType(item){
this.checkedCar=item.carTypeId
this.checkedCarName=item.carName+item.remark
},
submit(){
const id=storage.get('carType') ||'1001'
if(this.checkedCar==id){
uni.showToast({
title:'当前已是该车型题库!',
icon:'error'
})
}else{
this.show=true
}
},
cancel(){
this.show=false
},
confirmSubmit(){
storage.set('carType',this.checkedCar)
storage.set('carName',this.checkedCarName)
uni.showLoading({
title: '加载中'
});
useQuestionStore().resetStorage()
useQuestionStore().getAllQuestion()
}
}
}
</script>
<style scoped>
.checked{
border: 6rpx solid #05C341;
}
</style>

254
src/pages/me/help.vue Normal file
View File

@@ -0,0 +1,254 @@
<template>
<view style="padding-bottom: 50px;background-color: #C5121B;">
<image class="wp100 img" mode="widthFix"
src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/%E5%8A%A9%E5%8A%9B%E4%B8%BB%E5%9B%BE.jpg">
</image>
<view class="relative tip">邀请好友帮助你进行助力即可有机会领取奖品</view>
<view class="relative help_div">
<!-- -->
<view v-if="type == 1" class="relative help_card">
<view class="relative help_tip">
还差{{diffNum}}位好友助力即可领取奖品:
</view>
<view v-if="winnerInfo.awards != undefined" class="relative help_tip" style="font-size: 40rpx;">
{{winnerInfo.awards}}
</view>
<view class="p20">
<u-grid :border="false" col="3">
<u-grid-item v-for="(item, index) in helpUserList" :key="index">
<u-avatar v-if="item.id" class="p10tb border" size="120rpx" :src="item.avatarUrl"></u-avatar>
<view v-else class="p10tb">
<view class="avatar-text">
<u-avatar bg-color="#fff" color="#ccc" size="120rpx" text="邀"></u-avatar>
</view>
</view>
</u-grid-item>
</u-grid>
</view>
<view class="help_btn">
<button open-type="share" class="help_btn_font"> 邀请好友助力</button>
</view>
</view>
<view v-if="type == 2" class="relative help_card">
<view class="relative help_list" style="top: 200rpx;">
<view v-if="winnerInfo?.activityName" class="help_tip"
style="font-size: 40rpx; margin: 25rpx 0rpx;">
{{winnerInfo?.activityName}}
</view>
<view v-if="winnerInfo.schoolName != undefined" class="help_tip">
举办单位{{winnerInfo.schoolName}}
</view>
<view v-if="winnerInfo.awards != undefined" class="help_tip" style="font-size: 45rpx;margin: 25rpx 0rpx;">
奖品{{winnerInfo.awards}}
</view>
</view>
<view class="help_btn">
<button class="help_btn_font" open-type="chooseAvatar" @chooseavatar="handleHelp"
:disabled="disBtn">帮好友助力</button>
</view>
</view>
</view>
</view>
</template>
<script>
import useUserStore from '@/jtools/store/user'
import {
queryActivityDetail,
queryHelpInfo,
saveHelpInfo,
queryWinnerInfo
} from '@/jtools/api/activity'
export default {
data() {
return {
winnerId: undefined,
helpUserList: [],
drawNum: 0,
phone: undefined,
type: 2,
winnerInfo: undefined,
disBtn: false
}
},
onLoad(op) {
this.winnerId = op.id
// this.type = op.type ? Number(op.type) : 1
this.phone = useUserStore().userInfo?.phone || undefined
console.log(this.phone)
this.getWinnerInfo()
this.getHelpInfo()
this.disBtn = false
},
onShareAppMessage(res) {
if (res.from === 'button') { // 来自页面内分享按钮
console.log(res.target)
}
return {
title: '我正在参与领奖活动柜,请帮我助力',
path: '/pages/me/help?id=' + this.winnerId + '&type=2'
}
},
methods: {
//查询中奖信息
getWinnerInfo() {
queryWinnerInfo({
winnerId: this.winnerId
}).then(resp => {
if (resp.code == 200) {
console.log(resp)
this.winnerInfo = resp.data;
if (this.phone && this.winnerInfo.phone == this.phone) {
this.type = 1
} else {
this.type = 2
}
}
})
},
//查询助力信息
getHelpInfo() {
queryHelpInfo({
winnerId: this.winnerId
}).then(resp => {
if (resp.code == 200) {
this.drawNum = resp.data.helpNum;
const list = resp.data.helpUsers.map(item => ({
...item,
avatarUrl: 'https://jwl.ahduima.com' + item.avatarUrl
}));
this.diffNum = (this.drawNum - list.length) < 0 ? 0 : (this.drawNum - list.length);
const arr = new Array(this.diffNum).fill({})
this.helpUserList = [...list,...arr]
}
})
},
//点击助力
handleHelp(e) {
this.disBtn = false
uni.login({
provider: 'weixin', //使用微信登录
success: (loginRes) => {
console.log(loginRes);
uni.uploadFile({
url: 'https://jwl.ahduima.com/activity/applet/activity/help/save',
// url: 'http://192.168.1.6:8089/applet/activity/help/save',
filePath: e.detail.avatarUrl,
name: 'file',
formData: {
'code': loginRes.code,
'winnerId': this.winnerId,
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
let resp = JSON.parse(uploadFileRes.data);
console.log(resp);
if (resp.code == 200) {
uni.showToast({
icon: 'none',
title: `助力成功`
})
this.disBtn = true
} else {
uni.showToast({
icon: 'error',
title: resp.msg
})
this.disBtn = true
}
}
});
}
});
},
},
}
</script>
<style scoped lang="scss">
.img {
top: -130rpx !important;
}
.tip {
height: 75px;
font-family: PingFang SC;
font-weight: 400;
color: #FEFEFE;
line-height: 48px;
top: -520rpx;
text-align: center;
font-size: 35rpx;
}
.avatar-text {
border-radius: 50%;
border: 1px dashed #ccc;
}
.help_div {
width: 710rpx;
height: 996rpx;
top: -560rpx;
margin-left: 20rpx;
margin-right: 20rpx;
background: linear-gradient(0deg, #F33D2F 100%, rgba(197, 18, 27, 0.01) 0%);
border-radius: 40rpx;
.help_card {
width: 630rpx;
height: 886rpx;
margin: 0rpx 39rpx;
top: 55rpx;
background: #FFFFFF;
border-radius: 24rpx;
.help_tip {
text-align: center;
font-size: 32rpx;
font-family: PingFang SC;
font-weight: 400;
color: #010101;
line-height: 55rpx;
top: 15rpx;
}
.help_list {
margin: 68rpx 25rpx 25rpx 20rpx;
height: 580rpx;
}
.help_btn {
text-align: center;
margin: 0 75rpx;
margin-bottom: 30rpx;
width: 500rpx;
height: 86rpx;
background: linear-gradient(0deg, #DE4224 0%, #B81706 100%);
border-radius: 43rpx;
.help_btn_font {
font-size: 32rpx;
font-family: PingFang SC;
font-weight: 400;
color: #FFFFFF;
line-height: 86rpx;
background: center;
}
}
}
}
</style>

View File

@@ -2,16 +2,19 @@
<view class="bc-f5">
<!-- <view class="wp100" style="background-color: #333;height: 205px;"></view> -->
<view class="relative" style="height: 205px;">
<image src="/static/image/mine/mine_bg.png" mode="widthFix" style="width: 100%;"></image>
<image src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/vip%E8%83%8C%E6%99%AF%E7%BB%BF_20230831010645.png" mode="widthFix" style="width: 100%;"></image>
<view class="info flex ai-c" v-if="isLogin">
<u-avatar class="br-p50 overflow-h" :size="64" mp-avatar shape="circle"></u-avatar>
<view class="ml12">
<view class="flex ai-c fs18 cor-333 fwb">
<text class="mr10">{{ user.userName }}{{user.userId}}</text>
<image v-if="vipOn.length" src="/static/image/mine/vip.png" mode="widthFix" style="width: 18px;"></image>
<text class="mr10">{{ user.userName }}{{ user.userId }}</text>
<image v-if="vipOn.length" src="../../static/image/mine/vip.png" mode="widthFix" style="width: 18px;"></image>
</view>
<view class="mt5 fs14 cor-666">陪您学车 {{ user.days }}</view>
</view>
<view v-if="canRecieve" class="ml20 p20" @tap="handleScan">
<u-icon name="scan" size="40"></u-icon>
</view>
</view>
<view class="info flex ai-c" v-else @tap="toLogin">
<u-avatar class="br-p50 overflow-h" :size="64" src="@/static/image/mine/default_avatar.png" shape="circle"></u-avatar>
@@ -25,7 +28,7 @@
</view>
<view class="p15lr" style="transform: translateY(-90px);">
<view class="relative mb10" @tap="handleVip">
<image src="/static/image/mine/vip_bg.png" mode="widthFix" style="width: 100%;"></image>
<image src="https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/vip%E8%83%8C%E6%99%AF%E9%BB%841_20230831010645.png" mode="widthFix" style="width: 100%;"></image>
<view class="absolute p15lr p10tb flex ai-c jc-sb" style="left: 0;top: 0;right: 0;height: 40px;">
<view class="flex ai-c">
<view class="p3 br-p50" style="background-color: #873E1D;">
@@ -33,22 +36,26 @@
</view>
<text class="ml5 fs16 fwb" style="color: #7E4012FF;">VIP会员</text>
</view>
<text v-if="vipOn.length" class="fs12" style="color: #7E4012FF;">{{expireTime}}到期</text>
<text v-if="!isLogin || !vipOn.length" class="fs12" style="color: #7E4012FF;">您还不是VIP会员</text>
<text v-else-if="vipOn.length" class="fs12" style="color: #7E4012FF;">{{ expireTime }}到期</text>
</view>
<view class="absolute flex ai-c jc-c" style="left: 0;top: 40px;right: 0;bottom: 0;">
<view class="text-center">
<view v-if="vipOn.length" class="fs18 fwb" style="color: #7E4012FF;">{{vipText}}</view>
<view class="study fs16 text-center" style="margin: 25px auto 0;color: #F6E99FFF;">
{{ vipOn.length?'马上学习':'开通会员'}}
</view>
<view v-if="!isLogin || !vipOn.length" class="text-center">
<view class="fs18 fwb" style="color: #7E4012FF;">开通VIP尊享以下权益</view>
<view class="fs15" style="color: #7E4012FF;">精选500题 / 真实模考 / 考前密卷</view>
<view class="study fs16 text-center" style="margin: 25px auto 0;color: #F6E99FFF;">{{ isIOS ? 'iOS暂不可用' : '立即开通' }}</view>
</view>
<view v-else-if="vipOn.length" class="text-center">
<view class="fs18 fwb" style="color: #7E4012FF;">{{ vipText }}</view>
<view class="study fs16 text-center" style="margin: 25px auto 0;color: #F6E99FFF;">马上学习</view>
</view>
</view>
</view>
<view class="br8 bc-fff p15 z-index2">
<view v-if="isLogin" class="br8 bc-fff p15 z-index2">
<text class="fs16 cor-333">我的驾校</text>
<view v-if="user.schoolId">
<view v-if="user?.schoolId">
<div class="mt12 flex ai-c jc-sb">
<text class="fs18 cor-000 fwb">{{user.schoolName}}</text>
<text class="fs18 cor-000 fwb">{{ user.schoolName }}</text>
<u-button text="切换驾校" shape="circle" @click="handleChangeSchool"></u-button>
</div>
<u-line margin="14px 0 18px 0"></u-line>
@@ -57,10 +64,11 @@
<img src="/static/image/mine/phone.png" style="width: 12px;height: 12px;">
<text class="ml2 fs12 cor-fff">客服热线</text>
</view>
<text class="ml5 fs26 cor-333 fwb" style="line-height: 26px;">{{user.schoolPhone}}</text>
<text class="ml5 fs26 cor-333 fwb" style="line-height: 26px;">{{ user.schoolPhone }}</text>
</view>
</view>
<view v-else class="pt30 pb15">
<view v-else class="p15tb flex ai-c jc-sb">
<view class="fs20 cor-333 fwb">尚未绑定驾校</view>
<u-button text="绑定驾校" shape="circle" @click="handleChangeSchool"></u-button>
</view>
</view>
@@ -71,16 +79,21 @@
<img src="/static/image/mine/wdzl.png" style="width: 24px;height: 24px;">
</template>
</u-cell>
<u-cell size="large" title="我的体检" isLink @tap="handleTJ">
<u-cell size="large" title="我的奖品" isLink @tap="handleGift">
<template #icon>
<img src="/static/image/mine/wdtj.png" style="width: 24px;height: 24px;">
<u-icon size="24" name="gift"></u-icon>
</template>
</u-cell>
<u-cell size="large" title="我的题库" value="小车">
<u-cell size="large" title="我的题库" :value="carName" @tap="toChangeCarType">
<template #icon>
<img src="/static/image/mine/wdtk.png" style="width: 24px;height: 24px;">
</template>
</u-cell>
<u-cell size="large" title="联系我们" @tap="callPhoneNumber">
<template #icon>
<img src="/static/image/mine/callme.png" style="width: 24px;height: 24px;">
</template>
</u-cell>
</u-cell-group>
</view>
<view v-if="isLogin" class="flex ai-c jc-c mt12 br8 bc-fff" style="height: 50px;" @tap="handleLogout">
@@ -91,8 +104,9 @@
</template>
<script>
import useUserStore from '@/jtools/store/user'
import storage from '@/jtools/storage';
import { receiveWinner,canRecieveGift } from '@/jtools/api/activity'
export default {
components: {},
computed: {
isLogin() {
return useUserStore().isLogin
@@ -104,49 +118,78 @@ export default {
return useUserStore().vipOnList
},
expireTime() {
if(this.vipOn.length) {
if (this.vipOn.length) {
const t = this.vipOn.reduce((pre, cur) => {
if(Date.parse(pre) > Date.parse(cur.endDate)) {
if (Date.parse(pre) > Date.parse(cur.endDate)) {
return cur.endDate
}
return pre
}, '2099-12-31')
return t.split(' ')[0]
}else {
} else {
return ''
}
},
vipText() {
if(this.vipOn.length) {
if (this.vipOn.length) {
const t = this.vipOn.reduce((pre, cur) => {
return [...pre, ...cur.subjects.split(',').map(it =>['','一','二','三','四'][it])]
return [...pre, ...cur.subjects.split(',').map(it => ['', '一', '二', '三', '四'][it])]
}, [])
let val = Array.from(new Set(t))
val = val.length == 4 ? val.join('')+'全部':val.join('')
val = val.length == 4 ? val.join('') + '全部' : val.join('')
return `尊享科目${val}付费权益`
}else {
} else {
return ''
}
}
},
data() {
return {
};
carName: storage.get('carName') || '小车C1/C2/C3',
isIOS: true,
canRecieve: false
}
},
onShow() {
this.isIOS = this.$platform.device().includes('ios')
this.carName = storage.get('carName') || '小车C1/C2/C3'
this.searchActivityAuth()
},
methods: {
handleVip() {
if(this.isLogin) {
if(this.vipOn.length) {
uni.navigateTo({
url: '/pages/me/vip'
})
} else {
uni.navigateTo({
url: '/pages/index/videoVip'
})
searchActivityAuth() {
canRecieveGift({
phone: useUserStore().userInfo?.phone || ''
}).then(resp => {
if(resp.code == 200) {
this.canRecieve = resp.data
}
})
},
// 拨打电话
callPhoneNumber() {
uni.makePhoneCall({
phoneNumber: '15105693067'
});
},
toChangeCarType() {
uni.navigateTo({
url: "/pages/me/changeCarType"
})
},
handleVip() {
if (this.isIOS) {
return
}
if (this.isLogin) {
// if (this.vipOn.length) {
uni.navigateTo({
url: '/pages/me/vip'
})
// } else {
// uni.navigateTo({
// url: '/pages/index/videoVip'
// })
// }
} else {
this.toLogin()
}
@@ -157,7 +200,7 @@ export default {
})
},
handleChangeSchool() {
if(this.isLogin) {
if (this.isLogin) {
uni.navigateTo({
url: '/pages/me/school'
})
@@ -166,7 +209,7 @@ export default {
}
},
handleInfo() {
if(this.isLogin) {
if (this.isLogin) {
uni.navigateTo({
url: '/pages/me/info'
})
@@ -174,15 +217,6 @@ export default {
this.toLogin()
}
},
handleTJ() {
if(this.isLogin) {
uni.navigateTo({
url: '/pages/me/tijian'
})
} else {
this.toLogin()
}
},
toLogin() {
uni.navigateTo({
url: '/pages/login/login'
@@ -191,6 +225,30 @@ export default {
handleLogout() {
useUserStore().logout()
},
handleGift() {
uni.navigateTo({
url: '/pages/me/myGift'
})
},
handleScan() {
uni.scanCode({
scanType: ['qrCode'],
success(res) {
console.log('条码内容:' + res.result);
receiveWinner({
id: res.result,
receiveUser: useUserStore().userInfo?.phone || []
}).then(resp => {
if(resp.code == 200) {
uni.showToast({
icon: 'none',
title: '核销成功!'
})
}
})
}
})
}
}
}
</script>

View File

@@ -1,29 +1,36 @@
<template>
<view class="p15 bc-f5">
<view class="br8 bc-fff p15lr">
<view class="flex ai-c bb1" style="height: 110rpx;">
<view class="flex jc-sb ai-c bb1" style="height: 110rpx;">
<view class="title">联系电话</view>
<view class="m30lr fs14 cor-333 fl1">15122305568</view>
<u-icon name="arrow-right" color="#999" />
<view class="flex">
<view class="m30lr fs14 cor-333">15122305568</view>
<u-icon name="arrow-right" color="#999" />
</view>
</view>
<view class="flex ai-c" style="height: 110rpx;">
<view class="flex jc-sb ai-c bb1" style="height: 110rpx;">
<view class="title">地址</view>
<view class="m30lr fs14 cor-333 fl1">安徽省合肥市包河区</view>
<u-icon name="arrow-right" color="#999" />
<view class="flex">
<view class="m30lr fs14 cor-333">安徽省合肥市包河区</view>
<u-icon name="arrow-right" color="#999" />
</view>
</view>
</view>
</view>
</template>
<script>
import storage from '@/jtools/storage';
export default {
data() {
return {
sfzNum:storage.get('sfzNum') || ''
}
},
onShow(){
this.sfzNum=storage.get('sfzNum') || ''
},
methods: {
}
}
</script>

96
src/pages/me/myGift.vue Normal file
View File

@@ -0,0 +1,96 @@
<template>
<view class="p10lr p20tb">
<u-list @scrolltolower="loadmore">
<u-list-item v-for="(item, index) in list" :key="index" class="item">
<view class="relative">
<img src="/static/image/mine/giftitem.png" style="width: 100%;" mode="widthFix" alt="" />
<view class="ab_full df ai-c jcc">{{item.awards}}</view>
</view>
<view class="df ai-c jcsb p20tb p10lr">
<view class="item-label">
<view>活动名称{{ item.activityName }}</view>
<view>参与时间{{ item.createTime }}</view>
<view>有效期至{{ item.endTime }}</view>
</view>
<view class="ml20" style="width: 120rpx;">
<view v-if="item.status == 0" class="btn" @tap="handleHelp(item)">助力</view>
<view v-else-if="item.status == 1" class="btn" @tap="handleWriteoff(item)">核销</view>
<img v-else-if="item.status == 2" src="/static/image/mine/writeoff.png" style="width: 120rpx;height: 120rpx;" />
<img v-else src="/static/image/mine/outtime.png" style="width: 120rpx;height: 120rpx;" />
</view>
</view>
</u-list-item>
</u-list>
</view>
</template>
<script>
import useUserStore from '@/jtools/store/user'
import { getLuckyRecord } from '@/jtools/api/activity'
export default {
data() {
return {
pageNum: 1,
list: []
}
},
onShow() {
this.pageNum = 1
this.list = []
this.handleSearch()
},
methods: {
handleSearch() {
getLuckyRecord({
phone: useUserStore().userInfo.phone,
pageSize: 10,
pageNum: this.pageNum
}).then(resp => {
if(resp.code == 200) {
if(resp.rows && resp.rows.length) {
this.list = [...this.list, ...resp.rows]
} else {
this.pageNum = this.pageNum > 1 ? this.pageNum-1 : 1
}
}
})
},
loadmore() {
this.handleSearch(this.pageNum++)
},
handleWriteoff(item) {
uni.navigateTo({
url: `/pages/me/qrCode?id=${item.id}`
})
},
handleHelp(item){
uni.navigateTo({
url: `/pages/me/help?id=${item.id}`
})
}
}
}
</script>
<style lang="scss" scoped>
.item {
margin-bottom: 30rpx;
border-radius: 36rpx;
background-color: #fff;
.item-label {
font-size: 28rpx;
color: #666;
line-height: 48rpx;
}
.btn {
width: 120rpx;
height: 68rpx;
text-align: center;
line-height: 68rpx;
border-radius: 34rpx;
background-color: #BE1200;
color: #fff;
font-size: 28rpx;
}
}
</style>

26
src/pages/me/qrCode.vue Normal file
View File

@@ -0,0 +1,26 @@
<template>
<view class="df jcc" style="padding-top: 100px;">
<qrcode v-if="value" :value="value" :size="200"/>
</view>
</template>
<script>
import qrcode from '/src/uni_modules/lime-qrcode/components/l-qrcode/l-qrcode.vue'
export default {
components: {
qrcode
},
data() {
return {
value: ''
}
},
onLoad(option) {
this.value = option.id
},
}
</script>
<style>
</style>

View File

@@ -1,42 +0,0 @@
<template>
<view class="p15 bc-f5">
<view class="br8 bc-fff p15lr">
<view class="flex ai-c bb1" style="height: 110rpx;">
<view class="title">体检结果</view>
<view class="ml30 fs14 cor-333 fl1">通过</view>
</view>
<view class="flex ai-c" style="height: 110rpx;">
<view class="title">体检时间</view>
<view class="ml30 fs14 cor-333 fl1">2023-08-10 14:35:23</view>
</view>
<view class="flex ai-fs" style="height: 110rpx;">
<view class="title">体检时间</view>
<image class="ml30" src="/static/image/mine/tijian.png" style="width: 333rpx;" mode="widthFix"></image>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.title {
width: 120rpx;
font-size: 14px;
color: #666;
}
.bb1 {
border-bottom: 1px solid #eee;
}
</style>

226
src/pages/me/uploadPic.vue Normal file
View File

@@ -0,0 +1,226 @@
<template>
<view class="">
<view class="wp100 bc-fff p14">
<view class="title fontColor">第一步 上传学员图像</view>
<view class="mt15">
<!-- <u-upload width="165" height="165" :file-list=" fileList1" multiple :max-count="1" @afterRead="afterRead" @delete="deletePic" /> -->
<!-- <u-upload ref="uUpload" class="mt25" :size-type="['compressed']" :file-list="fileList1" deletable :multiple="false" :max-count="1" width="165rpx" height="165rpx" @afterRead="afterRead" @delete="deletePic" /> -->
<view style="width: 320rpx;height:300rpx;background-color: rgb(247, 255, 255);border-radius: 20rpx;">
<view style="width: 320rpx;height:240rpx;" class="flex jc-c ai-c">
<image v-if="fileList&&fileList.length" style="width: 240rpx;height: 240rpx;" :src="fileList[0].url">
</image>
<u-avatar v-else class="br-p50 overflow-h" :size="64" mp-avatar shape="circle"></u-avatar>
</view>
<u-upload :fileList="fileList1" :maxSize="500 * 1024" @oversize="oversize" @afterRead="afterRead"
@delete="deletePic" multiple :maxCount="1" width="150" height="150">
<view
style="width: 320rpx;height:60rpx;line-height:60rpx;background-color: #05C341;border-radius: 0 0 20rpx 20rpx;"
class="text-center cor-fff">
点击
</view>
</u-upload>
</view>
</view>
<view class="mt20">
<view class="title fontColor">第二步 核实后再提交</view>
<u--form labelPosition="left" labelWidth="80" :model="form" :rules="rules" ref="form1">
<u-form-item label="姓名" :required="true" prop="idCardName" borderBottom ref="item1">
<u--input v-model="form.idCardName" border="none"></u--input>
</u-form-item>
<u-form-item label="身份证号" :required="true" prop="sfzmhm" borderBottom ref="item2">
<u--input v-model="form.sfzmhm" border="none"></u--input>
</u-form-item>
</u--form>
</view>
<view style="margin-top: 20px;">
<u-button type="primary" :style="{width: '100%',borderRadius:'40rpx',backgroundColor:'#05C341'}"
:disabled="saving" text="提交" @click="submit" />
</view>
</view>
</view>
</template>
<script>
import storage from '@/jtools/storage';
import {
addInfo,
} from '@/jtools/api/index';
export default {
data() {
const shenfenzhen = (rule, value, callback) => {
/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value) ? callback() : callback(
new Error('请输入正确的身份证号'))
}
return {
form: {
idCardName: '',
sfzmhm: storage.get('sfzNum') || ''
},
driverLicenseImg: '',
fileList: [],
fileList1: [],
uploadList: [],
saving: false,
rules: {
idCardName: [{
required: true,
message: '请输入姓名',
trigger: ['blur', 'change']
}],
sfzmhm: [{
required: true,
message: '请输入身份证号',
trigger: ['blur', 'change']
}, {
// 自定义验证函数,见上说明
validator: shenfenzhen,
message: '身份证号码不正确',
// 触发器可以同时用blur和change
trigger: ['change', 'blur'],
}]
}
};
},
onReady() {
this.$refs.form1.setRules(this.rules);
},
methods: {
// 文件超出大小限制
oversize() {
uni.showToast({
title: "图片最大不能超过500k",
icon: 'none'
})
},
// 删除图片
deletePic(event) {
this.fileList1.splice(event.index, 1);
this.uploadList.splice(event.index, 1);
},
// 新增图片
async afterRead(event) {
let imageInfoObj = await uni.getImageInfo({
src: event.file[0].url
})
console.log(imageInfoObj);
if (imageInfoObj.width != 260 && imageInfoObj.height != 378) {
uni.showToast({
icon: 'error',
title: '证件照尺寸有误'
})
this.fileList = []
return false
}
this.driverLicenseImg = await this.urlTobase64(event.file[0].url)
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
const lists = [].concat(event.file);
this.fileList = lists
this.fileList1 = [];
uni.showToast({
title: '上传成功!'
})
},
// 提交
submit() {
this.$refs.form1.validate().then((valid) => {
if (valid) {
const param = {
driverLicenseImg: this.driverLicenseImg,
...this.form,
schoolOrgCode: '340103000700',
operater: '1d08daf852cf4ee28f67cb583f538cbf'
}
storage.set('sfzNum', this.form.sfzmhm)
uni.request({
url: 'https://www.hfcgs.cn:20223/driver/addInfo',
method: 'POST',
data: param,
success: res => {
console.log(res);
uni.showToast({
title: "提交成功!",
duration: 2000,
})
setTimeout(() => {
uni.navigateBack()
}, 1000)
},
fail: () => {},
});
// addInfo(param).then(resp=>{
// if(resp.code==='0000'){
// uni.showToast({
// title:"提交成功!",
// duration:2000,
// })
// setTimeout(()=>{
// uni.navigateBack()
// },1000)
// }
// })
} else {
console.log('验证失败');
}
});
},
urlTobase64(url) {
let base64 = ''
console.log(url);
return new Promise((resolve, reject) => {
uni.getFileSystemManager().readFile({
filePath: url, //选择图片返回的相对路径
encoding: 'base64', //编码格式
success: res => { //成功的回调
console.log(res);
base64 = 'data:image/jpeg;base64,' + res.data //不加上这串字符,在页面无法显示的哦
resolve(base64);
},
fail: (e) => {
console.log("图片转换失败");
reject(e)
}
})
});
}
}
};
</script>
<style lang="scss" scoped>
.upload-img {
width: 165rpx;
height: 165rpx;
border: 1px dashed #c4c4c4;
display: flex;
justify-content: center;
align-items: center;
}
.fontColor {
color: #383838;
font-weight: 400;
}
::v-deep .u-textarea__count {
background-color: #f9faf9 !important;
}
::v-deep .u-upload__button>.u-icon>.u-icon__icon {
font-size: 90rpx !important;
}
::v-deep .u-button--square {
border-radius: 40rpx !important;
}
::v-deep .u-button--primary {
background-color: #05C341 !important;
border-color: #05C341 !important;
}
</style>

View File

@@ -1,312 +1,398 @@
<template>
<view class="flex fld-c p15">
<u-sticky>
<view class="flex ai-c">
<view v-for="(item, index) in vipAllList" :key="index" class="km-item" :class="{ actived: index == current }"
@click="current = index">
{{ getKmTitle(item.subjects) }}
</view>
</view>
</u-sticky>
<view class="mt15">
<swiper class="swiper" :current="current" style="height: 120px;" :autoplay="false" :display-multiple-items="1.45"
:disable-programmatic-animation="true" @change="onChange">
<swiper-item v-for="(item, index) in vipAllList" :key="index">
<view class="relative">
<image src="../../static/image/mine/vip_card.png" mode="widthFix" style="width:95%;"></image>
<view class="vip-info">
<u-avatar class="br-p50 overflow-h" style="border: 3px solid #873E1D;" :size="35" mp-avatar></u-avatar>
<view class="ml10">
<view class="fs16 fwb" style="color: #7E4012;line-height: 16px;">
{{ item.memberName }}
</view>
<view class="mt5 fs12" style="color: #7E4012;line-height: 12px;">
{{ getExpireText(item) }}
</view>
</view>
</view>
<view v-if="vipHasOpened(item)" class="corner">
VIP已开通
</view>
<view v-if="vipHasOpened(item)" class="renew">
{{ item.price }}元立即续费
</view>
<view v-else class="buy">
立即充值
</view>
</view>
</swiper-item>
<swiper-item>
</swiper-item>
</swiper>
</view>
<view class="mt20">
<swiper class="swiper" :current="current" style="height: 300px;" :autoplay="false"
:disable-programmatic-animation="true" @change="onChange">
<swiper-item v-for="(item, index) in vipAllList" :key="index">
<view v-if="index == 0 || index == 3" class="p15 br8 cor-fff">
<view class="fs18 cor-000 fwb">
3步轻松学{{ getKmTitle(item.subjects) }}
</view>
<view class="mt25 flex ai-c jc-sb">
<view class="flex ai-c">
<image src="../../static/image/mine/1.png" mode="widthFix" style="width:25px;"></image>
<view class="ml7">
<view class="fs16 cor-000 fwb" style="line-height: 16px;">
精简500题
</view>
<view class="mt7 fs12 cor-666" style="line-height: 12px;">
题目全部做对视为完成
</view>
</view>
</view>
<view class="study" @tap="to500(item)">
去学习
</view>
</view>
<view class="mt45 flex ai-c jc-sb">
<view class="flex ai-c">
<image src="../../static/image/mine/2.png" mode="widthFix" style="width:25px;"></image>
<view class="ml7">
<view class="fs16 cor-000 fwb" style="line-height: 16px;">
真实考场模拟
</view>
<view class="mt7 fs12 cor-666" style="line-height: 12px;">
10次95分以上视为完成
</view>
</view>
</view>
<view class="study" @tap="toRealExam(item)">
去学习
</view>
</view>
<view class="mt45 flex ai-c jc-sb">
<view class="flex ai-c">
<image src="../../static/image/mine/3.png" mode="widthFix" style="width:25px;"></image>
<view class="ml7">
<view class="fs16 cor-000 fwb" style="line-height: 16px;">
考前密卷
</view>
<view class="mt7 fs12 cor-666" style="line-height: 12px;">
2套试卷95分以上视为完成
</view>
</view>
</view>
<view class="study" @tap="toSpecExam(item)">
去学习
</view>
</view>
</view>
<view v-else style="margin-top: 30rpx;">
<view class="video-box">
<view class="flex jc-sb ai-c wp100">
<text style="color: #873E1D;font-size: 36rpx;">考场实况</text>
<text class="cor-666 fs12">全部 ></text>
</view>
<view class="flex ai-c mt20">
<image src="../../static/image/index/index_bg.png" mode="widthFix" style="flex: 1;border-radius: 33rpx;"></image>
<view class="ml18 text-center">
<u-button :customStyle="{ width: '200rpx', height: '66rpx', borderRadius: '33rpx' }" iconColor="#fff"
text="去看视频" color="linear-gradient(90deg, #E66501 0%, #F8A42C 100%)" icon="play-circle" @click="toPlaceLive(item)">
</u-button>
<view class="cor-333 fs15 mt17">真实考场模拟</view>
</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</view>
<view>
<u-loading-page :loading="getLoading" loading-text="题库更新中..."></u-loading-page>
<view class="flex fld-c p15" v-if="!getLoading">
<u-sticky>
<view class="flex ai-c">
<view v-for="(item, index) in vipAllList" :key="index" class="km-item" :class="{ actived: index == current }"
@click="current = index">
{{ getKmTitle(item.subjects) }}
</view>
</view>
</u-sticky>
<view class="mt15">
<swiper class="swiper" :current="current" style="height: 120px;" :autoplay="false"
:display-multiple-items="1.45" :disable-programmatic-animation="true" @change="onChange">
<swiper-item v-for="(item, index) in vipAllList" :key="index">
<view class="relative"
style="background-image: url(https://oss-bq.ahduima.com/%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%9B%BE%E7%89%87/vip%E8%83%8C%E6%99%AF_20230831010348.png);width: 95%;height: 204rpx;background-size: 100% 100%;">
<!-- <image src="" mode="widthFix" style="width:95%;"></image> -->
<view class="vip-info">
<u-avatar class="br-p50 overflow-h" style="border: 3px solid #873E1D;" :size="35" mp-avatar></u-avatar>
<view class="ml10">
<view class="fs16 fwb" style="color: #7E4012;line-height: 16px;">
{{ item.memberName }}
</view>
<view class="mt5 fs12" style="color: #7E4012;line-height: 12px;">
{{ getExpireText(item) }}
</view>
</view>
</view>
<view v-if="vipHasOpened(item)" class="corner">
VIP已开通
</view>
<view v-if="vipHasOpened(item)" @tap="chargeVip(item)" class="renew">
{{ item.price }}元立即续费
</view>
<view v-else class="buy" @tap="chargeVip(item)">
立即充值
</view>
</view>
</swiper-item>
<swiper-item>
</swiper-item>
</swiper>
</view>
<view class="mt20">
<swiper class="swiper" :current="current" style="height: 300px;" :autoplay="false"
:disable-programmatic-animation="true" @change="onChange">
<swiper-item v-for="(item, index) in vipAllList" :key="index">
<view v-if="index == 0 || index == 3" class="p15 br8 cor-fff bc-fff">
<view class="fs18 cor-000 fwb">
3步轻松学{{ getKmTitle(item.subjects) }}
</view>
<view class="mt25 flex ai-c jc-sb">
<view class="flex ai-c">
<image src="../../static/image/mine/1.png" mode="widthFix" style="width:25px;"></image>
<view class="ml7">
<view class="fs16 cor-000 fwb" style="line-height: 16px;">
精简500题
</view>
<view class="mt7 fs12 cor-666" style="line-height: 12px;">
题目全部做对视为完成
</view>
</view>
</view>
<view class="study" @tap="to500(item)">
去学习
</view>
</view>
<view class="mt45 flex ai-c jc-sb">
<view class="flex ai-c">
<image src="../../static/image/mine/2.png" mode="widthFix" style="width:25px;"></image>
<view class="ml7">
<view class="fs16 cor-000 fwb" style="line-height: 16px;">
真实考场模拟
</view>
<view class="mt7 fs12 cor-666" style="line-height: 12px;">
10次95分以上视为完成
</view>
</view>
</view>
<view class="study" @tap="toRealExam(item)">
去学习
</view>
</view>
<view class="mt45 flex ai-c jc-sb">
<view class="flex ai-c">
<image src="../../static/image/mine/3.png" mode="widthFix" style="width:25px;"></image>
<view class="ml7">
<view class="fs16 cor-000 fwb" style="line-height: 16px;">
考前密卷
</view>
<view class="mt7 fs12 cor-666" style="line-height: 12px;">
2套试卷95分以上视为完成
</view>
</view>
</view>
<view class="study" @tap="toSpecExam(item)">
去学习
</view>
</view>
</view>
<view v-else style="margin-top: 30rpx;">
<view class="video-box">
<view class="flex jc-sb ai-c wp100">
<text style="color: #873E1D;font-size: 36rpx;">考场实况</text>
<text class="cor-666 fs12">全部 ></text>
</view>
<view class="flex ai-c mt20">
<view class="contain-box relative">
<image class="contain-box" src="../../../static/image/index/jpsp.png"></image>
<image class="play_btn_2" src="../../static/image/index/play.png" />
</view>
<view class="ml15 text-center">
<u-button :customStyle="{width:'200rpx',height:'66rpx',borderRadius: '33rpx'}" iconColor="#fff"
text="去看视频" color="linear-gradient(90deg, #E66501 0%, #F8A42C 100%)" icon="play-circle"
@click="toPlaceLive(item)">
</u-button>
<view class="cor-333 fs15 fw600 mt10">真实考场模拟</view>
</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</view>
</view>
</template>
<script>
import useUserStore from '@/jtools/store/user'
export default {
computed: {
vipAllList() {
return useUserStore().vipAllList.filter(it => [1, 2, 3, 4].includes(Number(it.subjects)))
},
vipOnList() {
return useUserStore().vipOnList
},
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import useUserStore from '@/jtools/store/user'
import {
queryQuestionId,
getTestQuestionId
} from '@/jtools/api/question';
import storage from '@/jtools/storage';
export default {
computed: {
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1", "version"]), //映射函数取出tagslist
getLoading() {
return this.loading_subject4 && this.loading_subject1
},
vipAllList() {
return useUserStore().vipAllList.filter(it => [1, 2, 3, 4].includes(Number(it.subjects)))
},
vipOnList() {
return useUserStore().vipOnList
},
},
data() {
return {
current: 0
}
},
methods: {
onChange(e) {
this.current = e.detail.current
},
getKmTitle(km) {
return {
'1': '科一',
'2': '科二',
'3': '科三',
'4': '科四',
}[km]
},
getExpireText(item) {
const vipOn = this.vipOnList.find(it => it.memberId == item.memberId)
if (vipOn) {
return `${vipOn.endDate.split(' ')[0]}到期`
} else {
return '开通vip助您快速拿证'
}
},
vipHasOpened(item) {
return !!this.vipOnList.find(it => it.memberId == item.memberId)
},
// 去精选500题 item=> 当前科目vip信息
to500(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
},
// 去真实考场 item=> 当前科目vip信息
toRealExam(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
},
// 去秘卷 item=> 当前科目vip信息
toSpecExam(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
},
// 去考场实况 item=> 当前科目vip信息
toPlaceLive(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
}
}
}
},
data() {
return {
current: 0
}
},
methods: {
...mapActions(useQuestionStore, ['getOrderQuestion_sub1', 'getOrderQuestion_sub4', 'getAllQuestion']),
chargeVip(item) {
uni.navigateTo({
url: "/pages/index/videoVip?subject=" + item.subjects
})
},
onChange(e) {
this.current = e.detail.current
},
getKmTitle(km) {
return {
'1': '科一',
'2': '科二',
'3': '科三',
'4': '科四',
} [km]
},
getExpireText(item) {
const vipOn = this.vipOnList.find(it => it.memberId == item.memberId)
if (vipOn) {
return `${vipOn.endDate.split(' ')[0]}到期`
} else {
return '开通vip助您快速拿证'
}
},
vipHasOpened(item) {
;
return !!this.vipOnList.some(it => it.subjects.includes(item.subjects))
},
// 去精选500题 item=> 当前科目vip信息
to500(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
queryQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: item.subjects,
isVip: '1'
}).then(async (resp) => {
if (resp.code === '0000') {
const arr = resp.data
if (arr && arr.length) {
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/questionBank?navTitle=精简500题&subject=" + item.subjects +
"&questionIdList=" + listJson
})
} else {
uni.showToast({
title: '暂无题目',
icon: 'none'
})
}
} else if (resp.code === '4001') {
uni.showToast({
title: '当前题库非最新版,请更新~',
icon: 'none'
})
this.getAllQuestion()
}
})
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
},
// 去真实考场 item=> 当前科目vip信息
toRealExam(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
uni.navigateTo({
url: "/pages/index/trueTest?subject=" + item.subjects
})
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
},
// 去秘卷 item=> 当前科目vip信息
toSpecExam(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
uni.navigateTo({
url: "/pages/index/secretPapers?subject=" + item.subjects
})
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
},
// 去考场实况 item=> 当前科目vip信息
toPlaceLive(item) {
// 当前vip是否已开通
if (this.vipHasOpened(item)) {
// 跳转
uni.showToast({
title: '敬请期待',
icon: 'none'
})
} else {
uni.showToast({
title: `请先充值${this.getKmTitle(item.subjects)}vip`,
icon: 'none'
})
}
}
}
}
</script>
<style lang="scss" scoped>
.km-item {
margin-right: 8px;
width: 72px;
height: 30px;
line-height: 30px;
font-size: 12px;
color: #333;
text-align: center;
border-radius: 15px;
border: 1px solid #CCCCCC;
}
.km-item {
margin-right: 8px;
width: 72px;
height: 30px;
line-height: 30px;
font-size: 12px;
color: #333;
text-align: center;
border-radius: 15px;
border: 1px solid #CCCCCC;
}
.actived {
background: linear-gradient(90deg, #E66501 0%, #F8A42C 100%);
color: #fff;
}
.actived {
background: linear-gradient(90deg, #E66501 0%, #F8A42C 100%);
color: #fff;
}
.km-item:last-of-type {
margin-right: 0;
}
.km-item:last-of-type {
margin-right: 0;
}
.vip-info {
position: absolute;
top: 15px;
left: 10px;
display: flex;
align-items: center;
}
.vip-info {
position: absolute;
top: 15px;
left: 10px;
display: flex;
align-items: center;
z-index: 1;
}
.corner {
position: absolute;
bottom: 0;
left: 0;
width: 77px;
height: 23px;
background: linear-gradient(0deg, #E66501 0%, #F8A42C 100%);
opacity: 0.86;
border-radius: 0px 8px 0px 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
color: #fff;
}
.corner {
position: absolute;
bottom: 0;
left: 0;
width: 77px;
height: 23px;
background: linear-gradient(0deg, #E66501 0%, #F8A42C 100%);
opacity: 0.86;
border-radius: 0px 8px 0px 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
color: #fff;
z-index: 1;
}
.renew {
position: absolute;
right: 10%;
bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
width: 185rpx;
height: 52rpx;
background: #873E1D;
border-radius: 26rpx;
font-size: 12px;
color: #F6E99F;
}
.renew {
position: absolute;
right: 10%;
bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
width: 185rpx;
height: 52rpx;
background: #873E1D;
border-radius: 26rpx;
font-size: 12px;
color: #F6E99F;
z-index: 1;
}
.buy {
position: absolute;
left: 45%;
transform: translateX(-50%);
bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
width: 200rpx;
height: 60rpx;
background: #873E1D;
border-radius: 30rpx;
font-size: 14px;
color: #F6E99F;
}
.buy {
position: absolute;
left: 45%;
transform: translateX(-50%);
bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
width: 200rpx;
height: 60rpx;
background: #873E1D;
border-radius: 30rpx;
font-size: 14px;
color: #F6E99F;
z-index: 1;
}
.study {
display: flex;
align-items: center;
justify-content: center;
width: 161rpx;
height: 67rpx;
background: #F6E99F;
border-radius: 34rpx;
font-size: 12px;
color: #873E1D;
}
.study {
display: flex;
align-items: center;
justify-content: center;
width: 161rpx;
height: 67rpx;
background: #F6E99F;
border-radius: 34rpx;
font-size: 12px;
color: #873E1D;
}
.video-box {
padding: 20rpx;
width: 694rpx;
height: 369rpx;
background: #F9F3E7;
border: 2rpx solid #CF8B6D;
border-radius: 16rpx;
}
.video-box {
padding: 20rpx;
width: 694rpx;
height: 369rpx;
background: #F9F3E7;
border: 2rpx solid #CF8B6D;
border-radius: 16rpx;
}
.contain-box {
width: 406rpx;
height: 228rpx;
background: #00B74F;
border-radius: 16rpx;
}
.play_btn_2 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 165.5rpx;
top: 78rpx
}
</style>

View File

@@ -1,18 +1,22 @@
<template>
<view>
<j-navbar>基本操作</j-navbar>
<u-sticky bgColor="#fff">
<!-- <u-sticky bgColor="#fff">
<u-tabs :list="categoryList" :scrollable="false" @click="changeCategory"></u-tabs>
</u-sticky>
</u-sticky> -->
<view class="p14">
<view class="flex ai-c">
<!-- <view class="flex ai-c">
<view class="car_item mr10" v-for="(item,index) of carTypeList" :key="index" @tap="chooseCar(item.value)" :class="item.value===tCar?'checked_car':'unchecked_car'">{{item.label}}</view>
</view>
<view class="flex p14 bc-fff mt10" style="border-radius: 16rpx;" v-for="(item,index) of videoList" :key="index" @tap="toDetail">
<image class="pic" src="../../static/image/index/index_bg.png"></image>
</view> -->
<view class="flex p14lr p20tb bc-fff mb10" style="border-radius: 10rpx;"
v-for="(item,index) of videoList" :key="index" @tap="toOperateDetail(item.videoId)">
<view class="pic relative hide" style="overflow: hidden;">
<image class="pic" style="position: absolute;left: 0;top:0" mode="widthFix" :src="item.videoUrl+'?x-oss-process=video/snapshot,t_0,f_jpg'"></image>
<image class="play_btn_2" src="../../static/image/index/play.png" />
</view>
<view class="ml10">
<text class="fs16 cor-000 fw600">上车下车的方法</text>
<view class="fs14 mt5 cor-666">上车下车的方法</view>
<text class="fs16 cor-000 fw600">{{allVideoList[0]?.description}}</text>
<view class="fs14 mt5 cor-666">{{item.description}}</view>
</view>
</view>
</view>
@@ -20,42 +24,92 @@
</template>
<script>
import {
querySysConfigList,
queryProjectList
} from '@/jtools/api/question';
import storage from '@/jtools/storage';
export default {
data(){
return{
type:'2',
subject:'1',
tCar:0,
categoryList:[{
name:'手动挡C1'
},{
name:'自动挡C2'
}],
carTypeList:[{
label:'捷达',
value:0
},{
label:'新桑塔纳',
value:1
},{
label:'爱丽舍',
value:2
}],
videoList:[{
label:"111"
},{
label:'222'
},{
label:'333'
},{
label:'444'
}]
allVideoList:[],
videoList:[]
}
},
onLoad(op){
if(op.subject){
this.subject=op.subject
}
if(op.type){
this.type=op.type
}
this.getDiverType()
},
methods:{
formateTime(time) {
const h = parseInt(time / 3600)
const minute = parseInt(time / 60 % 60)
const second = Math.ceil(time % 60)
const hours = h < 10 ? '0' + h : h
const formatSecond = second > 59 ? 59 : second
return `${hours > 0 ? `${hours}:` : ''}${minute < 10 ? '0' + minute : minute}:${formatSecond < 10 ? '0' + formatSecond : formatSecond}`
},
toOperateDetail(val){
let arr = JSON.parse(JSON.stringify(this.allVideoList[0].videoList))
arr = arr.map(item => {
return {
...item,
subDesc:this.allVideoList[0].description,
projectId:item.videoId,
videoTime:this.formateTime(item.videoTime)
}
})
let jsonString = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/videoDetail?videoList=" + jsonString + "&subject=" + this.subject +
"&projectId=" + val + "&type=2"
})
},
getOperateList() {
queryProjectList({
"carTypeId": storage.get('carType') || '1001',
"subject": String(this.subject),
"type": this.type
}).then(resp => {
if(resp.code==='0000'){
this.videoList=resp.data[0]?resp.data[0].videoList:[]
this.allVideoList=resp.data
}
})
},
getDiverType() {
const carTypeId = storage.get('carType') || '1001'
querySysConfigList(carTypeId, 'DriveType').then(resp => {
if (resp.code === '0000') {
this.categoryList=resp.data.map(item=>{
return {
...item,
name:item.configItemName
}
})
this.getOperateList()
}
})
},
chooseCar(val){
this.tCar=val
},
changeCategory(val){
this.tCar=val.index
this.getOperateList()
},
toDetail(){
uni.navigateTo({
@@ -91,6 +145,19 @@
width: 300rpx;
height: 169rpx;
background: #00B74F;
border-radius: 8rpx;
border-radius: 10rpx;
}
.play_btn_2 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 117.5rpx;
top: 52rpx
}
.hide {
backface-visibility: hidden;
transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
}
</style>

View File

@@ -1,28 +1,78 @@
<template>
<view>
<view class="chapter_item p14" v-for="(item,index) of chapterList" :key="index" @tap="toQuestion(item.configItemCode)">
{{item.configItemName}}
<u-loading-page :loading="getLoading" loading-text="题库更新中..."></u-loading-page>
<view v-if="!getLoading">
<view class="chapter_item p14" v-for="(item,index) of chapterList" :key="index" @tap="toQuestion(item.configItemCode)">
{{item.configItemName}}
</view>
</view>
</view>
</template>
<script>
import {
querySysConfigList
querySysConfigList,
queryQuestionId
} from '@/jtools/api/question';
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import storage from '@/jtools/storage';
export default {
data() {
return {
chapterList:[]
chapterList:[],
subject:'1'
}
},
onLoad(){
onLoad(op){
if(op.subject){
this.subject=op.subject
}
this.getChapterList()
},
computed: {
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1", "version"]), //映射函数取出tagslist
getLoading() {
return this.loading_subject4 && this.loading_subject1
}
},
methods:{
...mapActions(useQuestionStore, ['getAllQuestion']),
getQuestion(param,title) {
queryQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
...param,
}).then(async (resp) => {
if (resp.code === '0000') {
if(resp.data&&resp.data.length){
const arr = resp.data
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/questionBank?navTitle=" + title + "&subject=" + this.subject + "&questionIdList=" + listJson
})
}else{
uni.showToast({
title: '暂无题目',
icon: 'none'
})
}
}else if (resp.code === '4001') {
uni.showToast({
title: '当前题库非最新版,请更新~',
icon: 'none'
})
this.getAllQuestion()
}
})
},
getChapterList(){
const carTypeId=storage.get('carType') || '1001'
const key=this.subject=='1'?'ChapterOfSubjectOne':'ChapterOfSubjectFour'
querySysConfigList(carTypeId,'ChapterOfSubjectOne').then(resp=>{
if(resp.code==='0000'){
this.chapterList=resp.data
@@ -30,9 +80,7 @@
})
},
toQuestion(code){
uni.navigateTo({
url:"/pages/questionBank/questionBank?navTitle=章节技巧&chapter="+code
})
this.getQuestion({chapter:code},'章节技巧')
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,14 +8,14 @@
<view class="wp100 text-center" style="margin-top: -153rpx;">
<text v-if="score>=90">太棒了正确率很高了</text>
<text v-else>很遗憾考试不及格</text>
<button class="centerBtn">马上提分</button>
<button class="centerBtn" @click="toVip">马上提分</button>
<view class="flex ai-c jc-c mt10">
<view class="text-center wp33">
<view>{{doNotNum}}</view>
<text>未做题</text>
</view>
<view class="text-center wp33" @tap="toQuestionBank">
<view>{{wrongList.length}}</view>
<view>{{wrongList?.length}}</view>
<text>看错题</text>
</view>
<view class="text-center wp33 flex jc-c ai-c" style="flex-direction: column;" @tap="toExams">
@@ -48,10 +48,15 @@
</template>
<script>
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useUserStore from '@/jtools/store/user'
import GradesChart from "./components/GradesChart.vue"
import storage from '@/jtools/storage';
import {
testTotal
testTotal,getTestQuestionId
} from '@/jtools/api/question';
export default {
components: {
@@ -103,6 +108,7 @@
this.doNotNum=op.doNotNum
}
if(op.wrongList){
console.log(op.wrongList);
this.wrongList=JSON.parse(op.wrongList) || []
}
if(op.score){
@@ -119,7 +125,31 @@
onReady() {
this.getServerData();
},
onUnload() {
//#ifdef MP-WEIXIN
uni.reLaunch({
url:"/pages/index/index"
})
//#endif
},
computed: {
...mapState(useUserStore, ["vipOnList"])
},
methods: {
...mapActions(useUserStore, ['searchUserVip']),
async toVip(){
await this.searchUserVip()
const res = this.vipOnList.some(item => item.subjects.includes(this.subject))
if(res){
uni.navigateTo({
url: '/pages/me/vip'
})
}else{
uni.navigateTo({
url:"/pages/index/videoVip?subject="+this.subject
})
}
},
getServerData() {
testTotal({
"carTypeId": storage.get('carType') || '1001',
@@ -144,16 +174,36 @@
})
},
toQuestionBank(){
const list =JSON.stringify(this.wrongList)
uni.navigateTo({
url:"/pages/questionBank/questionBank?navTitle=错题&subject="+this.subject+"&questionList="+list
})
if(this.wrongList.length==0){
uni.showToast({
title:'当前无错题~',
icon:'none'
})
}else{
const list =JSON.stringify(this.wrongList)
uni.navigateTo({
url:"/pages/questionBank/questionBank?navTitle=错题&subject="+this.subject+"&questionIdList="+list
})
}
},
//重新考试
toExams(){
uni.navigateTo({
url:"/pages/questionBank/practiceExams?subject="+this.subject
getTestQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
}).then(async (resp) => {
if (resp.code === '0000') {
const arr = resp.data
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/practiceExams?title=模拟考试&subject=" + this.subject + "&questionIdList=" + listJson
})
}
})
// uni.navigateTo({
// url:"/pages/questionBank/practiceExams?subject="+this.subject
// })
},
},
}

View File

@@ -1,42 +1,48 @@
<template>
<view class="p14">
<view class="flex jc-sb">
<view class="relative mr5" @tap="toIconSkill">
<image style="width: 336rpx;height: 152rpx;" src="../../static/image/practice/errorprone_bg.png">
</image>
<view style="position: absolute;left: 0;top: 0;" class="p10">
<view style="color: #04B13B;font-size: 18px;">图标技巧</view>
<text style="color: #04B13B;font-size: 14px;">快速记忆</text>
</view>
</view>
<view class="relative ml5" @tap="toChapterSkill">
<image style="width: 363rpx;height: 170rpx;" src="../../static/image/practice/chapter_bg.png"></image>
<view style="position: absolute;left: 0;top: 0;" class="p10">
<view style="color: #FF6E02;font-size: 18px;">章节练习</view>
<text style="color: #FF6E02;font-size: 14px;">共5章</text>
</view>
</view>
</view>
<view class="bc-fff pt14" style="border-radius: 20rpx;">
<u-grid :border="false" col="4">
<u-grid-item v-for="(listItem,listIndex) in list" :key="listIndex" @click="toAnswer(listItem.title)">
<view style="width: 84rpx;height: 84rpx;">
<image style="width: 84rpx;" mode="widthFix" :src="listItem.image"></image>
<view>
<u-loading-page :loading="getLoading" loading-text="题库更新中..."></u-loading-page>
<view class="p14" v-if="!getLoading">
<view class="flex jc-sb">
<view class="relative mr5" @tap="toIconSkill">
<image style="width: 336rpx;height: 152rpx;" src="../../static/image/practice/errorprone_bg.png">
</image>
<view style="position: absolute;left: 0;top: 0;" class="p10">
<view style="color: #04B13B;font-size: 18px;">图标技巧</view>
<text style="color: #04B13B;font-size: 14px;">快速记忆</text>
</view>
</view>
<view class="relative ml5" @tap="toChapterSkill">
<image style="width: 363rpx;height: 170rpx;" src="../../static/image/practice/chapter_bg.png"></image>
<view style="position: absolute;left: 0;top: 0;" class="p10">
<view style="color: #FF6E02;font-size: 18px;">章节练习</view>
<text style="color: #FF6E02;font-size: 14px;">{{chapterNum}}</text>
</view>
</view>
</view>
<view class="bc-fff pt14" style="border-radius: 20rpx;">
<u-grid :border="false" col="4">
<u-grid-item v-for="(listItem,listIndex) in list" :key="listIndex"
@click="toAnswer(listItem.title,listItem.isError,listItem.isNew)">
<view class="mb5" style="width: 84rpx;height: 84rpx;">
<image style="width: 84rpx;height:84rpx;" mode="heightFix" :src="listItem.image"></image>
</view>
<text class="grid-text fs14 cor-000">{{listItem.title}}</text>
<text class="grid-text mb10 fs12 cor-999">{{listItem.subTitle}}</text>
</u-grid-item>
</u-grid>
</view>
<view class="mt14 p14 bc-fff" style="border-radius: 20rpx;">
<text class="fs18 cor-000 fw600">常见考点</text>
<view class="flex ai-c wp100 mt10" style="flex-wrap: wrap;">
<view class="wp50 flex ai-c p15tb" style="border-bottom: 1rpx solid #DDDCDC;"
v-for="(item,index) of testCenterList" :key="index" @tap="toQuestionBank(item)">
<view class="dot_item">{{index+1}}</view>
<text class="ml5 topic_cont_text" style="width: calc(100% - 65rpx);">{{item.configItemName}}</text>
</view>
<text class="grid-text fs14 cor-000">{{listItem.title}}</text>
<text class="grid-text mb10 fs12 cor-999">{{listItem.subTitle}}</text>
</u-grid-item>
</u-grid>
</view>
<view class="mt14 p14 bc-fff" style="border-radius: 20rpx;">
<text class="fs18 cor-000 fw600">常见考点</text>
<view class="flex ai-c wp100 mt10" style="flex-wrap: wrap;">
<view class="wp50 flex ai-c mb10" v-for="(item,index) of testCenterList" :key="index">
<view class="dot_item">{{index+1}}</view>
<text class="ml5">{{item.label}}</text>
</view>
</view>
</view>
</view>
</template>
@@ -44,76 +50,260 @@
import errorIcon from "../../static/image/practice/error_icon.png"
import newRulesIcon from "../../static/image/practice/newRules_icon.png"
import neverWriteIcon from "../../static/image/practice/neverWrite_icon.png"
import danxuanIcon from "../../static/image/index/danxuan.png"
import panduanIcon from "../../static/image/index/panduan.png"
import tupianIcon from "../../static/image/index/tupian.png"
import {
querySysConfigList,
querySpecialNum,
queryQuestionId
} from '@/jtools/api/question';
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import storage from '@/jtools/storage';
export default {
data() {
return {
chapterNum:0,
errorIcon,
newRulesIcon,
neverWriteIcon,
list:[{
title:'新规题',
subTitle:'392题',
image:newRulesIcon
},{
title:'易错题',
subTitle:'392题',
image:errorIcon
},{
title:'未做题',
subTitle:'392题',
image:neverWriteIcon
},{
title:'单选题',
subTitle:'392题',
image:newRulesIcon
},{
title:'判断题',
subTitle:'392题',
image:errorIcon
},{
title:'图片题',
subTitle:'392题',
image:neverWriteIcon
list: [{
title: '新规题',
subTitle: '392题',
isNew: 1,
isError: 0,
image: newRulesIcon
}, {
title: '易错题',
isNew: 0,
isError: 1,
subTitle: '392题',
image: errorIcon
}, {
title: '单选题',
subTitle: '392题',
isNew: 0,
isError: 0,
image: danxuanIcon
}, {
title: '判断题',
subTitle: '392题',
isNew: 0,
isError: 0,
image: panduanIcon
}, {
title: '图片题',
subTitle: '392题',
isNew: 0,
isError: 0,
image: tupianIcon
}],
testCenterList:[
{label:'驾驶证申请相关'},
{label:'驾驶证申请相关'},
{label:'驾驶证登记处罚'},
{label:'机动车强制报废'},
{label:'其他考点'},
{label:'驾驶证登记处罚'},
{label:'机动车强制报废'},
{label:'其他考点'}]
testCenterList: [],
subject: '1'
}
},
onLoad(op) {
if (op.subject) {
this.subject = op.subject
}
this.getExamPoint()
this.getQuestionNum()
this.getChapterList()
},
computed: {
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1", "version"]), //映射函数取出tagslist
getLoading() {
return this.loading_subject4 && this.loading_subject1
}
},
methods: {
toAnswer(title) {
uni.navigateTo({
url:"/pages/questionBank/questionBank?navTitle="+title
...mapActions(useQuestionStore, ['getAllQuestion']),
getChapterList(){
const carTypeId=storage.get('carType') || '1001'
const key=this.subject=='1'?'ChapterOfSubjectOne':'ChapterOfSubjectFour'
querySysConfigList(carTypeId,'ChapterOfSubjectOne').then(resp=>{
if(resp.code==='0000'&&resp.data){
this.chapterNum=resp.data.length
}
})
},
toIconSkill(){
uni.navigateTo({
url:"/pages/index/iconSkill"
getQuestionNum() {
querySpecialNum({
carTypeId: storage.get('carType') || '1001',
subject: this.subject
}).then(resp => {
if (resp.code === '0000') {
if (this.subject == '1') {
this.list = [{
title: '新规题',
subTitle: resp.data.newQuestionNum + '题',
isNew: 1,
isError: 0,
image: newRulesIcon,
}, {
title: '易错题',
isNew: 0,
isError: 1,
subTitle: resp.data.errorQuestionNum + '题',
image: errorIcon,
}, {
title: '单选题',
subTitle: resp.data.radioQuestionNum + '题',
isNew: 0,
isError: 0,
image: danxuanIcon,
}, {
title: '判断题',
subTitle: resp.data.judgeQuestionNum + '题',
isNew: 0,
isError: 0,
image: panduanIcon,
}, {
title: '图片题',
subTitle: resp.data.imageQuestionNum + '题',
isNew: 0,
isError: 0,
image: tupianIcon,
}]
} else {
this.list = [{
title: '新规题',
subTitle: resp.data.newQuestionNum + '题',
isNew: 1,
isError: 0,
image: newRulesIcon
}, {
title: '易错题',
isNew: 0,
isError: 1,
subTitle: resp.data.errorQuestionNum + '题',
image: errorIcon,
}, {
title: '单选题',
subTitle: resp.data.radioQuestionNum + '题',
isNew: 0,
isError: 0,
image: danxuanIcon,
}, {
title: '多选题',
subTitle: resp.data.multipleChoiceQuestionNum + '题',
isNew: 0,
isError: 0,
image: neverWriteIcon
}, {
title: '判断题',
subTitle: resp.data.judgeQuestionNum + '题',
isNew: 0,
isError: 0,
image: panduanIcon,
}, {
title: '图片题',
subTitle: resp.data.imageQuestionNum + '题',
isNew: 0,
isError: 0,
image: tupianIcon,
}]
}
}
})
},
toChapterSkill(){
uni.navigateTo({
url:"/pages/questionBank/chapterExercise"
getExamPoint() {
const carTypeId = storage.get('carType') || '1001'
const examKey = this.subject == '1' ? 'ExamKeysOfSubjectOne' : 'ExamKeysOfSubjectFour'
querySysConfigList(carTypeId, examKey).then(resp => {
if (resp.code === '0000') {
this.testCenterList = resp.data
}
})
},
getQuestion(param,title) {
queryQuestionId({
versionId: this.version,
carTypeId: storage.get('carType') || '1001',
subject: this.subject,
...param,
}).then(async (resp) => {
if (resp.code === '0000') {
if(resp.data&&resp.data.length){
const arr = resp.data
const listJson = JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/questionBank?navTitle=" + title + "&subject=" + this.subject + "&questionIdList=" + listJson
})
}else{
uni.showToast({
title: '暂无题目',
icon: 'none'
})
}
}else if (resp.code === '4001') {
uni.showToast({
title: '当前题库非最新版,请更新~',
icon: 'none'
})
this.getAllQuestion()
}
})
},
toAnswer(title, isError, isNew) {
if (title == '单选题') {
this.getQuestion({type:'2'},title)
} else if (title == '多选题') {
this.getQuestion({type:'3'},title)
} else if (title == '判断题') {
this.getQuestion({type:'1'},title)
} else if (title == '图片题') {
this.getQuestion({isImage:'1'},title)
} else {
this.getQuestion({isNew:isNew,isError:isError},title)
}
},
toQuestionBank(val) {
this.getQuestion({examKey:val.configItemCode},val.configItemName)
},
toIconSkill() {
uni.navigateTo({
url: "/pages/index/iconSkill"
})
},
toChapterSkill() {
uni.navigateTo({
url: "/pages/questionBank/chapterExercise?subject="+this.subject
})
}
}
}
</script>
<style scoped>
.dot_item{
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
color: #fff;
text-align: center;
background: #0BD032;
border-radius: 50%;
}
</style>
.dot_item {
width: 40rpx;
height: 40rpx;
line-height: 41rpx;
color: #fff;
text-align: center;
background: #0BD032;
border-radius: 50%;
}
.topic_cont_text {
height: 45rpx;
overflow: hidden;
word-break: break-all;
/* break-all(允许在单词内换行。) */
text-overflow: ellipsis;
/* 超出部分省略号 */
display: -webkit-box;
/** 对象作为伸缩盒子模型显示 **/
-webkit-box-orient: vertical;
/** 设置或检索伸缩盒对象的子元素的排列方式 **/
-webkit-line-clamp: 1;
/** 显示的行数 **/
}
</style>

View File

@@ -2,14 +2,21 @@
<view>
<!-- <u-navbar title="模拟考试" @rightClick="rightClick" :autoBack="true">
</u-navbar> -->
<j-navbar :isDefineBack="true" @toBack="toBack">模拟考试</j-navbar>
<Question ref="question" :tabsList="tabsList" v-model:isSubmit="isSubmit" type="exam" :subject="subject" navTitle="模拟考试" />
<j-navbar :isDefineBack="true" @toBack="toBack">{{title}}</j-navbar>
<Question ref="question" :tabsList="tabsList" v-model:isSubmit="isSubmit" :type="type" :isShowAll="isShowAll" @changeTab="changeTab" />
</view>
</template>
<script>
import {
getTestQuestion
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import useUserStore from '@/jtools/store/user'
import {
getTestQuestion,
queryQuestionId
} from '@/jtools/api/question';
import storage from '@/jtools/storage';
import Question from './components/Question.vue';
@@ -19,52 +26,96 @@
},
data() {
return {
subject:1,
isSubmit:false,
tabsList:[{
label:"模拟考试",
value:0
},{
label:"考前密卷",
value:1
type: '',
collectList: storage.get(`collectList_subject${this.subject}`) || [],
questionArr: [],
isShowAll: true,
title: "模拟考试",
subject: 1,
isSubmit: false,
tabsList: [{
label: "模拟考试",
value: 0
}, {
label: "考前秘卷",
value: 1
}]
}
},
onLoad(op) {
if(op.subject){
this.subject=op.subject
getTestQuestion({
carTypeId: storage.get('carType') || '1001',
subject: this.subject
}).then(resp=>{
if(resp.code==='0000'){
this.$refs.question.getQuestionList(JSON.stringify(resp.data))
}
if (op.title) {
this.title = op.title
}
if (op.subject) {
this.subject = op.subject
const param = {}
if (op.isExam1) {
param.isExam1 = op.isExam1
}
if (op.needVip) {
this.isShowAll = op.needVip
}
let arr = []
arr = [...this[`orderQuestion_subject${this.subject}`]]
let questionObj = {}
arr.forEach(item => {
item.isChoose = false
questionObj[item.questionId] = item
})
if (op.questionIdList) {
const idList = JSON.parse(op.questionIdList)
if (idList && idList.length > 0) {
idList.forEach(item => {
this.questionArr.push(questionObj[item])
})
}
}
this.type = 'exam'
this.$refs.question.getQuestionList(JSON.stringify(this.questionArr), this.title,this.subject)
}
},
computed: {
...mapState(useUserStore, ["vipOnList", "token"]),
...mapState(useQuestionStore, ["orderQuestion_subject1", "orderQuestion_subject4", "version"]), //映射函数取出tagslist
},
methods: {
toBack(){
...mapActions(useUserStore, ['searchUserVip']),
toBack() {
this.$refs.question.submitPaper()
},
async changeTab(val) {
if (val == 1) {
await this.searchUserVip()
const result = this.vipOnList.some(item => item.subjects.includes(this.subject))
if (result) {
uni.navigateTo({
url: "/pages/index/secretPapers?subject=" + this.subject
})
} else {
uni.navigateTo({
url: "/pages/index/videoVip?subject=" + this.subject
})
}
}
}
}
}
</script>
<style scoped>
::v-deep .u-count-down{
::v-deep .u-count-down {
font-size: 28rpx;
color:#fff !important;
color: #fff !important;
display: inline-block !important;
}
::v-deep .u-count-down__text{
::v-deep .u-count-down__text {
font-size: 28rpx;
color:#fff !important;
color: #fff !important;
}
::v-deep .balckColor .u-count-down__text{
::v-deep .balckColor .u-count-down__text {
font-size: 28rpx;
color:#333 !important;
color: #333 !important;
}
</style>
</style>

View File

@@ -5,8 +5,9 @@
<view class="p14 wp100">
<GradesChart :titleName="rightPencentDesc" :actualValue="Number(rightPencent)" />
<view class="top_box flex jc-c" style="flex-direction: column;">
<view class="wp100 text-center" >
<text>太棒了正确率很高了</text>
<view class="wp100 text-center" style="margin-top: -80px;">
<text v-if="Number(rightPencent * 100)>=90">太棒了正确率很高了</text>
<text v-else>继续努力吧正确率有点低~</text>
<view class="flex ai-c jc-c mt10">
<view class="text-center wp50" @tap="toQuestionBank">
<view>{{wrongList.length}}/{{allDoNum}}</view>
@@ -25,7 +26,7 @@
<view class="flex ai-c jc-sb">
<view>
<text class="fs18 cor-000 fw600">累计练题</text>
<text class="fs14 cor-666 ml10">33</text>
<text class="fs14 cor-666 ml10">{{allRightList.length+allWrongList.length}}</text>
</view>
<text class="fs14 cor-666">未做题{{getNotDoNum}}</text>
</view>
@@ -80,20 +81,27 @@
}
if(op.wrongList){
this.wrongList=JSON.parse(op.wrongList)
this.rightPencent=((this.allDoNum-this.wrongList.length)/this.allDoNum).toFixed(2)
this.rightPencent=this.allDoNum>0?((this.allDoNum-this.wrongList.length)/this.allDoNum).toFixed(2):0
this.rightPencentDesc=(this.rightPencent*100).toFixed(0)+'%'
}
if(op.subject){
this.subject=op.subject
this.allRightList=storage.get(`rightList_subject${this.subject}`) || []
this.allWrongList=storage.get(`wrongList_subject${this.subject}`) || []
this.percent=(((this.allRightList.length+this.wrongList.length) / this.orderQuestion.length)*100).toFixed(0)
this.percent=(((this.allRightList.length+this.wrongList.length) / this[`orderQuestion_subject${this.subject}`].length)*100).toFixed(0)
}
},
onUnload() {
//#ifdef MP-WEIXIN
uni.reLaunch({
url:"/pages/index/index"
})
//#endif
},
computed: {
...mapState(useQuestionStore, ["orderQuestion"]), //映射函数取出tagslist
...mapState(useQuestionStore, ["orderQuestion_subject1","orderQuestion_subject4"]), //映射函数取出tagslist
getNotDoNum(){
return this.orderQuestion.length-(this.allRightList.length+this.allWrongList.length)
return this[`orderQuestion_subject${this.subject}`].length-(this.allRightList.length+this.allWrongList.length)
}
},
methods: {

View File

@@ -1,11 +1,13 @@
<template>
<view>
<!-- <u-navbar :title="navTitle" @rightClick="rightClick" :autoBack="true">
</u-navbar> -->
<j-navbar>{{navTitle}}</j-navbar>
<Question ref="question" :tabsList="tabsList" :isShowAll="isShowAll" :subject="subject" :navTitle="navTitle"></Question>
<u-loading-page :loading="loading" :loading-text="loadTxt"></u-loading-page>
<view v-if="!loading">
<j-navbar>{{navTitle}}</j-navbar>
<Question ref="question" :tabsList="tabsList" :isShowAll="isShowAll" :subject="subject" :navTitle="navTitle"
@changeTab="changeTab"></Question>
</view>
</template>
</view>
</template>
<script>
import {
@@ -16,7 +18,8 @@
import useUserStore from '@/jtools/store/user'
import Question from './components/Question.vue';
import {
queryQuestion
queryQuestion,
queryQuestionId
} from '@/jtools/api/question';
import storage from '@/jtools/storage';
export default {
@@ -25,74 +28,83 @@
},
data() {
return {
isShowAll:true,
needVip:false,
subject:1,
navTitle:'',
tabsList:[{
label:"答题",
value:0
},{
label:"题",
value:1
loadTxt: '加载中...',
collectList: storage.get(`collectList_subject${this.subject}`) || [],
loading: false,
isShowAll: true,
needVip: false,
subject: 1,
navTitle: '',
tabsList: [{
label: "题",
value: 0
}, {
label: "背题",
value: 1
}],
questionArr:[]
questionArr: []
}
},
async onLoad(op) {
if(op.needVip){
this.needVip=op.needVip
this.loading = true
if (op.needVip) {
this.needVip = op.needVip
}
if(op&&op.navTitle){
this.navTitle=op.navTitle
const param={}
if(this.navTitle==='顺序答题'||this.navTitle==='精简500题'){
this.questionArr=[...this.orderQuestion]
if(this.needVip==='true'){
if(this.token){
await this.searchUserVip()
const res=this.vipOnList.some(item=>item.subject==this.subject)
if(!res){
this.questionArr=this.questionArr.slice(0,3)
this.isShowAll=false
}
}else{
uni.redirectTo({
url: '/pages/login/login'
});
}
}
this.$refs.question.getQuestionList(JSON.stringify(this.questionArr))
}else{
if(this.navTitle==='错题本'){
param.questionIdList=storage.get(`wrongList_subject${this.subject}`) || []
}else if(this.navTitle==='收藏夹'){
param.questionIdList=storage.get(`collectList_subject${this.subject}`) || []
}
if(op.questionList){
param.questionIdList=JSON.parse(op.questionList)
}
if(op.chapter){
param.chapter=op.chapter
}
queryQuestion(param).then(res => {
if (res.code == '0000') {
this.questionArr = res.data
this.$refs.question.getQuestionList(JSON.stringify(this.questionArr))
}
})
if (op.subject) {
this.subject = op.subject
}
if (op && op.navTitle) {
this.navTitle = op.navTitle
let arr = []
let param = {}
if (op.needVip) {
this.isShowAll = !Boolean(op.needVip == 'true')
}
}
if(op.subject){
this.subject=op.subject
arr = [...this[`orderQuestion_subject${this.subject}`]]
let questionObj={}
arr.forEach(item => {
item.isChoose=false
questionObj[item.questionId]=item
})
if(op.navTitle==='顺序答题'){
this.questionArr=arr
}else if (op.questionIdList) {
const idList = JSON.parse(op.questionIdList)
if(idList&&idList.length>0){
idList.forEach(item=>{
this.questionArr.push(questionObj[item])
})
}
}
this.loading = false
this.$refs.question.getQuestionList(JSON.stringify(this.questionArr), this.navTitle , this.subject)
this.$refs.question.getOriginArr(JSON.stringify(this.questionArr))
}
},
computed: {
...mapState(useQuestionStore, ["orderQuestion"]) ,//映射函数取出tagslist
...mapState(useUserStore, ["vipOnList","token"])
...mapState(useQuestionStore, ["orderQuestion_subject1", "orderQuestion_subject4", "version"]), //映射函数取出tagslist
...mapState(useUserStore, ["vipOnList", "token"]),
},
methods: {
...mapActions(useUserStore,['searchUserVip']),
...mapActions(useUserStore, ['searchUserVip']),
...mapActions(useQuestionStore, ['getAllQuestion']),
changeTab(val) {
if (val == 1) {
let list = JSON.parse(JSON.stringify(this.questionArr))
list = list.map(item => {
return {
...item,
clickAnswer: item.trueAnswer,
isChoose: true,
}
})
this.$refs.question.isShowBest(true)
this.$refs.question.getQuestionList(JSON.stringify(list), this.navTitle)
} else {
this.$refs.question.isShowBest(false)
this.$refs.question.getQuestionList()
}
},
rightClick() {
console.log('返回');
},
@@ -102,4 +114,4 @@
<style scoped>
</style>
</style>

View File

@@ -1,14 +1,15 @@
<template>
<view>
<sunny-video style="width: 100%" videoHeight="422rpx" ref="sunny-video" title="测试视频" src="https://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/%E7%AC%AC1%E8%AE%B2%EF%BC%88uni-app%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D%EF%BC%89-%20DCloud%E5%AE%98%E6%96%B9%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B@20200317.mp4" @timeupdate="timeupdate" />
<view class="p14 bc-fff">
<u-scroll-list :indicator="false" v-if="videoType=='test'">
<view class="flex ai-c jc-sb mt15">
<view class="tab_iem mr15" :class="videoIndex===item.value?'checked_tab':''" v-for="(item,index) of testList" :key="index" @tap="checkTest(item.value)">{{item.label}}</view>
<sunny-video style="width: 100%" videoHeight="422rpx" ref="sunny-video" :src="videoList[currentIndex].videoUrl" />
<view class="p14tb bc-fff">
<view class="skill-sequence-panel-content-wrapper pr14" v-if="videoType=='test'">
<scroll-view class="skill-sequence-panel-content" scroll-x>
<view class="skill-sequence-skill-wrapper tab_iem" :class="videoIndex===item.value?'checked_tab':''"
v-for="(item,index) of testList" :key="index" @tap="checkTest(item.value)">{{item.label}}</view>
</scroll-view>
</view>
</u-scroll-list>
<view class="flex ai-c jc-sb mt10 wp100">
<text class="fs18 fw600 cor-000">C1捷达-基础操作视频讲解</text>
<view class="flex ai-c jc-sb mt10 wp100 p14">
<text class="fs18 fw600 cor-000">{{title}}</text>
<view class="flex" @tap="popupShow=true" v-if="videoType!='test'">
<text class="fs14 cor-666">更多</text>
<u-icon color="#666" name="arrow-right" size="18"></u-icon>
@@ -18,20 +19,26 @@
<view>
</view>
</view>
<view class="pl14 bc-fff">
<u-scroll-list :indicator="false" class="mr15">
<view v-for="(item, index) in videoList" :key="index" class="mr15" @click="checkVideo(item.id)">
<view>
<view class="mb10 relative">
<image class="contain-box" src="../../static/image/index/index_bg.png"></image>
<view v-if="nowVideo===item.id" class="playLogo">播放中</view>
<image class="play_btn" src="../../static/image/index/play.png" />
<text style="position: absolute;right: 8rpx;bottom: 8rpx;color:#fff">13:14</text>
</view>
<text :style="{color:nowVideo===item.id?'#FF6E02':'#333'}">正确的驾驶姿势</text>
<view class="bc-fff pl14 pb10">
<view class="skill-sequence-panel-content-wrapper">
<scroll-view class="skill-sequence-panel-content" scroll-x :scroll-left="getScrollLeft">
<view class="skill-sequence-skill-wrapper" v-for="(item, index) in videoList" :key="index"
@tap="checkVideo(item.projectId)">
<view>
<view class="mb10 relative contain-box hide" style="overflow: hidden;">
<image class="contain-box" style="position: absolute;left: 0;top: 0;" mode="widthFix"
:src="item.videoUrl+'?x-oss-process=video/snapshot,t_0,f_jpg'"></image>
<view v-if="projectId==item.projectId" class="playLogo">播放中</view>
<image class="play_btn" src="../../static/image/index/play.png" />
<text style="position: absolute;right: 8rpx;bottom: 8rpx;color:#fff">{{item.videoTime}}</text>
</view>
</view>
</u-scroll-list>
<view class="topic_cont_text" :style="{color:projectId==item.projectId?'#FF6E02':'#333'}">
{{item.description}}
</view>
</view>
</view>
</scroll-view>
</view>
</view>
<u-popup :show="popupShow" mode="bottom" :closeOnClickOverlay="true" @close="popupShow=false">
<view class="p14 flex ai-c jc-sb">
@@ -39,15 +46,16 @@
<text class="fs16 cor-666" @tap="popupShow=false">收起</text>
</view>
<view style="max-height: 800rpx;overflow-y: scroll;" class="p14lr">
<view class="flex bc-fff mt10" style="border-radius: 16rpx;" v-for="(item,index) of videoList" :key="index" @tap="toDetail">
<view class="pic relative">
<image class="pic" src="../../static/image/index/index_bg.png"></image>
<view class="flex bc-fff mb15" style="border-radius: 16rpx;" v-for="(item,index) of videoList" :key="index"
@tap="checkVideo(item.projectId)">
<view class="pic relative hide" style="overflow: hidden;">
<image class="pic" style="position: absolute;left: 0;top: 0;" mode="widthFix" :src="item.videoUrl+'?x-oss-process=video/snapshot,t_0,f_jpg'"></image>
<image class="play_btn_2" src="../../static/image/index/play.png" />
<text style="position: absolute;right: 8rpx;bottom: 8rpx;color:#fff">13:14</text>
<text style="position: absolute;right: 8rpx;bottom: 8rpx;color:#fff">{{item.videoTime}}</text>
</view>
<view class="ml10">
<text class="fs16 cor-000 fw600">上车下车的方法</text>
<view class="fs14 mt5 cor-666">上车下车的方法</view>
<text class="fs16 cor-000 fw600">{{item.description}}</text>
<view class="fs14 mt5 cor-666">{{item.subDesc}}</view>
</view>
</view>
</view>
@@ -56,73 +64,153 @@
</template>
<script>
export default{
data(){
return{
videoIndex:0,
testList:[{
label:"八一考场",
value:0,
},{
label:"富凯考场",
value:1
},{
label:"新亚考场",
value:2
},{
label:"庐江考场",
value:3
},{
label:"富凯考场",
value:4
},{
label:"新亚考场",
value:5
},{
label:"庐江考场",
value:6
}],
videoType:'',
popupShow:false,
nowVideo:0,
videoList:[{
title:'正确的驾驶姿势',
time:'13:14',
id:0
},{
title:'正确的驾驶姿势',
time:'13:14',
id:1
},{
title:'正确的驾驶姿势',
time:'13:14',
id:2
},{
title:'正确的驾驶姿势',
time:'13:14',
id:3
},{
title:'正确的驾驶姿势',
time:'13:14',
id:4
},{
title:'正确的驾驶姿势',
time:'13:14',
id:5
}]
import {
queryProjectList
} from '@/jtools/api/question';
import storage from '@/jtools/storage';
export default {
data() {
return {
title: '',
currentIndex: 0,
videoIndex: 0,
testList: [{
label: "八一考场",
value: 0,
}, {
label: "富凯考场",
value: 1
}, {
label: "新亚考场",
value: 2
}, {
label: "庐江考场",
value: 3
}, {
label: "富凯考场",
value: 4
}, {
label: "新亚考场",
value: 5
}, {
label: "庐江考场",
value: 6
}],
driveType:'',
videoType: '',
popupShow: false,
videoList: [{
title: '正确的驾驶姿势',
time: '13:14',
id: 0
}, {
title: '正确的驾驶姿势',
time: '13:14',
id: 1
}, {
title: '正确的驾驶姿势',
time: '13:14',
id: 2
}, {
title: '正确的驾驶姿势',
time: '13:14',
id: 3
}, {
title: '正确的驾驶姿势',
time: '13:14',
id: 4
}, {
title: '正确的驾驶姿势',
time: '13:14',
id: 5
}],
projectId: undefined,
param: {}
}
},
onLoad(op){
if(op.type){
this.videoType=op.type
onLoad(op) {
if(op.driveType){
this.driveType=op.driveType
this.param.driveType=op.driveType
}
if (op.type) {
this.videoType = op.type
}
if (op.projectId) {
this.projectId = op.projectId
}
if (op.subject) {
this.param.subject = op.subject
}
if (op.type) {
this.param.type = op.type
this.getVideoList()
}
if (op.type == '1') {
if (this.param.subject == '2') {
this.title = '科二基础项目讲解'
} else {
this.title = '科三基础项目讲解'
}
} else {
this.title = '基础操作讲解'
}
},
computed: {
getScrollLeft() {
const index = this.currentIndex - 1 < 0 ? 0 : this.currentIndex - 1
return 164 * index
}
},
methods:{
checkTest(val){
this.videoIndex=val
methods: {
formateTime(time) {
const h = parseInt(time / 3600)
const minute = parseInt(time / 60 % 60)
const second = Math.ceil(time % 60)
const hours = h < 10 ? '0' + h : h
const formatSecond = second > 59 ? 59 : second
return `${hours > 0 ? `${hours}:` : ''}${minute < 10 ? '0' + minute : minute}:${formatSecond < 10 ? '0' + formatSecond : formatSecond}`
},
checkVideo(val){
this.nowVideo=val
getVideoList() {
queryProjectList({
"carTypeId": storage.get('carType') || '1001',
...this.param,
}).then(resp => {
if(resp.code==='0000'){
let arr=[]
if(this.param.type=='1'){
arr = JSON.parse(JSON.stringify(resp.data))
arr = arr.map(item => {
return {
...item,
videoUrl: item.videoList[0]?.videoUrl,
videoTime: this.formateTime(item.videoList[0]?.videoTime)
}
})
}else{
arr = JSON.parse(JSON.stringify(resp.data[0].videoList))
arr = arr.map(item => {
return {
...item,
projectId: item.videoId,
subDesc: resp.data[0].description,
videoTime: this.formateTime(item.videoTime)
}
})
}
this.videoList = arr
this.currentIndex = this.videoList.findIndex(item => item.projectId == this.projectId)
}
})
},
checkTest(val) {
this.videoIndex = val
},
checkVideo(val) {
this.popupShow = false
this.projectId = val
this.currentIndex = this.videoList.findIndex(item => item.projectId == this.projectId)
}
}
}
@@ -135,7 +223,23 @@
background: #00B74F;
border-radius: 8rpx;
}
.playLogo{
.topic_cont_text {
width: 260rpx;
height:45rpx;
overflow: hidden;
word-break: break-all;
/* break-all(允许在单词内换行。) */
text-overflow: ellipsis;
/* 超出部分省略号 */
/* display: -webkit-box; */
white-space: nowrap;
-webkit-box-orient: vertical; /** 设置或检索伸缩盒对象的子元素的排列方式 **/
-webkit-line-clamp:1; /** 显示的行数 **/
}
.playLogo {
width: 90rpx;
height: 40rpx;
background: #FF6E02;
@@ -146,39 +250,67 @@
font-size: 12px;
position: absolute;
left: 0;
top:0
top: 0
}
.play_btn{
.play_btn {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 97.5rpx;
top:39.5rpx
top: 39.5rpx
}
.play_btn_2{
.play_btn_2 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 117.5rpx;
top:52rpx
top: 52rpx
}
.pic{
.pic {
width: 300rpx;
height: 169rpx;
background: #00B74F;
border-radius: 8rpx;
}
.tab_iem{
.tab_iem {
width: 145rpx;
height: 56rpx;
line-height: 56rpx;
text-align: center;
background: #F5F5F5;
border-radius: 10rpx;
color:#333
}
.checked_tab{
color: #333
}
.checked_tab {
background: linear-gradient(90deg, #11DF20 0%, #01B74F 100%);
color:#fff
color: #fff
}
/*scroll-view外层*/
.skill-sequence-panel-content-wrapper {
position: relative;
white-space: nowrap;
}
/*scroll-view本身*/
.skill-sequence-panel-content {
min-width: 100%;
}
/*scroll-view内层*/
.skill-sequence-skill-wrapper {
display: inline-block;
margin-right: 15px;
}
.hide {
backface-visibility: hidden;
transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
}
</style>

View File

@@ -1,144 +1,188 @@
<template>
<view>
<u-sticky bgColor="#fff">
<u-tabs :list="categoryList" :scrollable="false" @click="tabChange"></u-tabs>
<u-tabs :list="categoryList" :scrollable="false" @click="tabChange"></u-tabs>
</u-sticky>
<view class="p14">
<view class="top_box">
<view class="tip_box flex ai-c jc-sb" v-if="tIndex==0">
<view class="flex ai-c">
<u-icon name="error-circle-fill" color="#FF6E02" size="18"></u-icon>
<text class="ml10 fs12" style="color: #FF6E02;">{{title}}</text>
</view>
<u-icon name="close" color="#FF6E02" size="18"></u-icon>
<view class="tip_box flex ai-c jc-sb" v-if="tIndex==0&&showTip">
<view class="flex ai-c">
<u-icon name="error-circle-fill" color="#FF6E02" size="18"></u-icon>
<text class="ml10 fs12" style="color: #FF6E02;">{{title}}</text>
</view>
<view class="p14">
<text class="fs18 cor-000 fw600">{{tIndex==0?'错题':'收藏'}}情况</text>
<view class="total_box mt10">
<view class="flex ai-c jc-sb">
<view class="text-center">
<view style="width: 111rpx;" class="fs30 cor-000">{{tIndex==0?wrongList.length:collectList.length}}</view>
</view>
<view style="text-align: right;flex-direction: column;justify-content: right" class="flex ai-c" @tap="toPractice">
<u-icon name="arrow-right" size="18"></u-icon>
<u-icon name="close" color="#FF6E02" size="18" @tap="showTip=false"></u-icon>
</view>
<view class="p14">
<text class="fs18 cor-000 fw600">{{tIndex==0?'错题':'收藏'}}情况</text>
<view class="total_box mt10" @tap="toPractice">
<view class="flex ai-c jc-sb">
<view class="text-center">
<view style="width: 111rpx;" class="fs30 cor-000">{{tIndex==0?wrongList.length:collectList.length}}
</view>
</view>
<view class="flex ai-c jc-sb mt5">
<view class="text-center">
<text class="fs14 cor-666">全部{{tIndex==0?'错题':'收藏'}}</text>
</view>
<view style="text-align: right;flex-direction: column;justify-content: right" class="flex ai-c">
<text v-if="tIndex==0" class="fs14 cor-666">{{wrongList.length}}/已做{{wrongList.length+rightList.length}}</text>
</view>
<view style="text-align: right;flex-direction: column;justify-content: right" class="flex ai-c">
<u-icon name="arrow-right" size="18"></u-icon>
</view>
</view>
<view class="yellow_box" v-if="tIndex==0&&getPercent>10">
<view class="flex jc-sb ai-c">
<view>
<text class="fs24 fw600" style="color: #FF6E02;">{{getPercent}}%</text><text class="fs18 cor-000 fw600">错题率</text>
<view class="fs14 cor-000">错题率有点高快去提升吧</view>
</view>
<!-- <view style="width: 156rpx;">
<view class="flex ai-c jc-sb mt5">
<view class="text-center">
<text class="fs14 cor-666">全部{{tIndex==0?'错题':'收藏'}}</text>
</view>
<view style="text-align: right;flex-direction: column;justify-content: right" class="flex ai-c">
<text v-if="tIndex==0"
class="fs14 cor-666">{{wrongList.length}}/已做{{wrongList.length+rightList.length}}</text>
</view>
</view>
</view>
<view class="yellow_box" v-if="tIndex==0&&getPercent>10">
<view class="flex jc-sb ai-c">
<view>
<text class="fs24 fw600" style="color: #FF6E02;">{{getPercent}}%</text><text
class="fs18 cor-000 fw600">错题率</text>
<view class="fs14 cor-000">错题率有点高快去提升吧</view>
</view>
<!-- <view style="width: 156rpx;">
<button class="riseBtn">马上提升</button>
</view> -->
</view>
</view>
<view class="flex jc-sb ai-c mt10" v-if="tIndex==0">
<text>答对后自动移除错题</text>
<u-switch v-model="isMoveWrong" activeColor="#0BD032" ></u-switch>
</view>
</view>
<!-- <view class="flex jc-sb ai-c mt10" v-if="tIndex==0">
<text>答对后自动移除错题</text>
<u-switch v-model="isMoveWrong" activeColor="#0BD032"></u-switch>
</view> -->
</view>
<!-- <view class="ml15 text-center">
<u-button :customStyle="{width:'200rpx',height:'66rpx',borderRadius: '33rpx'}" iconColor="#fff"
text="去看视频" color="linear-gradient(90deg, #11DF20 0%, #00B74F 100%)" icon="play-circle">
</u-button>
<view class="cor-333 fs15 fw600 mt10">{{subject==1?'一':'四'}}易错试题</view>
</view> -->
</view>
<view style="margin-top: 30rpx;" v-if="tIndex==0">
<view class="video-box">
<view class="flex jc-sb ai-c wp100">
<text style="color: #05C341;font-size: 36rpx;">{{subject==1?'一':'四'}}精品视频课</text>
<text class="cor-666 fs12">全部10节课 ></text>
</view>
<view class="flex ai-c mt20">
<image class="contain-box" src="../../static/image/index/index_bg.png"></image>
<view class="ml15 text-center">
<u-button :customStyle="{width:'200rpx',height:'66rpx',borderRadius: '33rpx'}" iconColor="#fff"
text="去看视频" color="linear-gradient(90deg, #11DF20 0%, #00B74F 100%)" icon="play-circle">
</u-button>
<view class="cor-333 fs15 fw600 mt10">{{subject==1?'一':'四'}}易错试题</view>
</view>
</view>
</view>
</view>
</view>
<view class="top_box mt15 p14">
<view class="top_box mt15 p14" v-if="typeList&&typeList.length">
<view class="flex jc-sb aic">
<text class="fs18 cor-000 fw600">{{tIndex==0?'错题':'收藏题'}}分类</text>
<u-icon name="arrow-right" size="18"></u-icon>
<!-- <u-icon name="arrow-right" size="18"></u-icon> -->
</view>
<view class="flex ai-c jc-sb" style="flex-wrap: wrap;">
<view v-for="(item,index) of typeList" :key="index" class="category_item p14 flex jc-sb ai-c mb10">
<text class="cor-000">{{item.categoryName}}</text>
<view class="flex ai-c jc-sb mt10" style="flex-wrap: wrap;">
<!-- 这个点击效果没加 -->
<view v-for="(item,index) of typeList" :key="index" class="category_item p14 flex jc-sb ai-c mb10" @tap="toCategoryQuestion(item)">
<view class="topic_cont_text" style="max-width: 75%;">
<text class="cor-000">{{item.categoryName}}</text>
</view>
<text class="cor-666">{{item.num}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapActions
} from 'pinia' //引入映射函数
import useQuestionStore from '@/jtools/store/question' //引入store
import storage from '@/jtools/storage';
import {
questionCategory
} from '@/jtools/api/question';
export default{
data(){
return{
collectList:[],
rightList:storage.get(`rightList_subject${this.subject}`) || [],
wrongList:storage.get(`wrongList_subject${this.subject}`) || [],
subject:0,
tIndex:0,
isMoveWrong:true,
title:'重要提示:所有错题做对,再去考试!',
categoryList:[{
name:'错题本'
},{name:'收藏夹'}],
typeList:[]
export default {
data() {
return {
showTip: true,
collectList: [],
rightList: storage.get(`rightList_subject${this.subject}`) || [],
wrongList: storage.get(`wrongList_subject${this.subject}`) || [],
subject: 0,
tIndex: 0,
isMoveWrong: true,
title: '重要提示:所有错题做对,再去考试!',
categoryList: [{
name: '错题本'
}, {
name: '收藏夹'
}],
typeList: []
}
},
onLoad(op){
if(op.subject){
this.subject=op.subject
this.rightList=storage.get(`rightList_subject${this.subject}`) || []
this.wrongList=storage.get(`wrongList_subject${this.subject}`) || []
this.collectList=storage.get(`collectList_subject${this.subject}`) || []
onLoad(op) {
if (op.subject) {
this.subject = op.subject
this.rightList = storage.get(`rightList_subject${this.subject}`) || []
this.wrongList = storage.get(`wrongList_subject${this.subject}`) || []
this.collectList = storage.get(`collectList_subject${this.subject}`) || []
this.getQuestionCategory()
}
},
computed:{
getPercent(){
return ((this.wrongList.length/(this.wrongList.length+this.rightList.length))*100).toFixed(0)
computed: {
...mapState(useQuestionStore, ["orderQuestion_subject1", "orderQuestion_subject4"]), //映射函数取出tagslist
getPercent() {
return ((this.wrongList.length / (this.wrongList.length + this.rightList.length)) * 100).toFixed(0)
}
},
methods:{
getQuestionCategory(){
const param={}
if(this.tIndex==0){
param.questionIdList=this.wrongList
}else{
param.questionIdList=this.collectList
methods: {
getQuestionCategory() {
const param = {}
if (this.tIndex == 0) {
param.questionIdList = this.wrongList
} else {
param.questionIdList = this.collectList
}
questionCategory(param).then(resp=>{
this.typeList=resp.data
questionCategory(param).then(resp => {
this.typeList = resp.data
})
},
tabChange(val){
this.tIndex=val.index
tabChange(val) {
this.tIndex = val.index
this.getQuestionCategory()
},
toPractice(){
const navTitle=this.tIndex==0?'错题本':'收藏夹'
toCategoryQuestion(item){
const jsonString = JSON.stringify(item.errorQuestionIdList)
console.log(item);
uni.navigateTo({
url:"/pages/questionBank/questionBank?navTitle="+navTitle+"&subject="+this.subject
url: "/pages/questionBank/questionBank?navTitle=" + item.categoryName + "&questionIdList=" + jsonString+"&subject="+this.subject
})
},
toPractice() {
const navTitle = this.tIndex == 0 ? '错题本' : '收藏夹'
let arr=[]
if (navTitle == '错题本') {
arr = this.wrongList
if (!this.wrongList.length) {
uni.showModal({
title: '提示',
content: '当前无错题,继续保持吧~',
showCancel: false,
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
}
}
});
return
}
} else if (navTitle == '收藏夹') {
arr=this.collectList
if (!this.collectList.length) {
uni.showModal({
title: '提示',
content: '当前无收藏题~',
showCancel: false,
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
}
}
});
return
}
}
const listJson=JSON.stringify(arr)
uni.navigateTo({
url: "/pages/questionBank/questionBank?navTitle=" + navTitle + "&subject=" + this.subject+"&questionIdList="+listJson
})
}
}
@@ -147,65 +191,94 @@
<style scoped>
::v-deep .u-tabs__wrapper__nav__line {
background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%) !important;
bottom: 14rpx !important;
}
.top_box{
width: 100%;
background: #FDFDFD;
border-radius: 20rpx;
}
.tip_box{
width: 100%;
background: #FFE6D4;
border-radius: 20rpx 20rpx 0rpx 0rpx;
padding: 10px 14px;
}
.total_box{
width: 100%;
background: #F5F5F5;
border-radius: 20rpx;
padding: 14px;
}
.yellow_box{
margin-top: 10px;
padding: 14px;
width: 100%;
background: linear-gradient(90deg, #FBF2D4 0%, #F7E4B5 100%);
border-radius: 20rpx;
}
.riseBtn{
width: 156rpx;
height: 56rpx;
text-align: center;
line-height: 56rpx;
font-size: 12px;
background-color: #F7E4B5;
border: 1px solid #FF6E02;
color: #FF6E02;
border-radius: 28rpx;
}
.video-box {
padding: 20rpx;
width: 694rpx;
height: 369rpx;
background: #DEEFE5;
border: 2px solid #47DB87;
border-radius: 16rpx;
}
.contain-box {
width: 406rpx;
height: 228rpx;
background: #00B74F;
border-radius: 16rpx;
}
.category_item{
width: 312rpx;
height: 90rpx;
text-align: center;
line-height: 90rpx;
background: #F5F5F5;
border-radius: 20rpx;
}
background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%) !important;
bottom: 14rpx !important;
}
.top_box {
width: 100%;
background: #FDFDFD;
border-radius: 20rpx;
}
.tip_box {
width: 100%;
background: #FFE6D4;
border-radius: 20rpx 20rpx 0rpx 0rpx;
padding: 10px 14px;
}
.total_box {
width: 100%;
background: #F5F5F5;
border-radius: 20rpx;
padding: 14px;
}
.yellow_box {
margin-top: 10px;
padding: 14px;
width: 100%;
background: linear-gradient(90deg, #FBF2D4 0%, #F7E4B5 100%);
border-radius: 20rpx;
}
.riseBtn {
width: 156rpx;
height: 56rpx;
text-align: center;
line-height: 56rpx;
font-size: 12px;
background-color: #F7E4B5;
border: 1px solid #FF6E02;
color: #FF6E02;
border-radius: 28rpx;
}
.video-box {
padding: 20rpx;
width: 694rpx;
height: 369rpx;
background: #DEEFE5;
border: 2px solid #47DB87;
border-radius: 16rpx;
}
.contain-box {
width: 406rpx;
height: 228rpx;
background: #00B74F;
border-radius: 16rpx;
}
.category_item {
width: 310rpx;
height: 90rpx;
text-align: center;
line-height: 90rpx;
background: #F5F5F5;
border-radius: 20rpx;
}
.play_btn_2 {
width: 65rpx;
height: 65rpx;
position: absolute;
left: 165.5rpx;
top: 78rpx
}
.topic_cont_text {
overflow: hidden;
word-break: break-all;
/* break-all(允许在单词内换行。) */
text-overflow: ellipsis;
/* 超出部分省略号 */
display: -webkit-box;
/** 对象作为伸缩盒子模型显示 **/
-webkit-box-orient: vertical;
/** 设置或检索伸缩盒对象的子元素的排列方式 **/
-webkit-line-clamp: 1;
/** 显示的行数 **/
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -0,0 +1,11 @@
## 1.0.42022-12-07
修改判断在APP端不监听document的滚动
## 1.0.32022-12-05
新增:支持视频预览,视频图片混用
新增支持预览单张handlePreviewImg方法直接传入图片或视频地址即可单张预览
## 1.0.22022-12-05
## 1.0.12022-12-05
文档错误修改
## 1.0.02022-11-29
初始化插件

View File

@@ -0,0 +1,235 @@
<template>
<view class="pos">
<uni-transition :mode-class="modeClass" :show="show">
<!-- 多张图片预览 -->
<view class="content" @tap="closedPreview">
<swiper
class="swiper"
circular
:current="curDot"
@change="swiperChange"
:indicator-dots="false"
>
<swiper-item v-for="(item, idx) in selfImgList" :key="idx">
<movable-area scale-area>
<movable-view
:scale="!disabledScale"
direction="all"
scale="true"
scale-min="0.5"
scale-max="5"
:scale-value="1"
damping="150"
friction="15"
>
<image v-if="isImg(item)" :src="item" mode="widthFix"></image>
<view class="video-preview" v-else>
<video
:autoplay="true"
:src="item"
:enable-progress-gesture="false"
:show-fullscreen-btn="false"
></video>
</view>
</movable-view>
</movable-area>
</swiper-item>
</swiper>
</view>
<!-- 指示器 -->
<slot name="indicator" v-if="imgList.length > 1 && !indicatorDotsType">
<view class="current-dot">
<view class="change-buttom" @tap.stop="previousImg">
<uni-icons class="font-white" type="back" size="30"></uni-icons>
</view>
<view class="font-white cur">
{{ curDot + 1 }}/{{ imgList.length }}
</view>
<view class="change-buttom" @tap.stop="nextImg">
<uni-icons class="font-white" type="forward" size="30"></uni-icons>
</view>
</view>
</slot>
</uni-transition>
</view>
</template>
<script>
export default {
props: {
// 过渡效果
modeClass: {
type: Array,
default: ['fade', 'zoom-out'],
},
// 指示器类型 true 圆点 false 数字
indicatorDotsType: {
type: Boolean,
default: true,
},
// 图片列表
imgList: {
type: Array,
default: () => [],
},
// 是否禁止放大缩小 禁止后swiper可以滑动切换
disabledScale: {
type: Boolean,
default: false,
},
},
data() {
return {
show: false,
curDot: 0,
selfImgList: [],
};
},
computed: {
isImg() {
return (src) => {
return src.indexOf('.mp4') === -1 ? true : false;
};
},
},
watch: {
//监听打开时阻止下面元素的滚动事件
/* #ifdef APP-PLUS*/
show(val) {
if (val) {
document
.getElementsByClassName('pos')[0]
.addEventListener('touchmove', function (e) {
e.preventDefault();
});
}
},
/* #endif */
imgList: {
handler(val) {
if (val.length) {
this.selfImgList = val.concat();
}
},
},
},
methods: {
handlePreviewImg(param) {
this.show = !this.show;
if (typeof param === 'string') {
this.selfImgList = [param];
} else {
if (param) {
this.curDot = param;
}
}
this.$emit('preview', this.show);
},
closedPreview() {
this.show = !this.show;
this.curDot = 0;
this.$emit('preview', this.show);
},
swiperChange(e) {
this.curDot = e.detail.current;
this.$emit('changeImg', e.detail.current);
},
previousImg() {
let num = this.imgList.length - 1;
if (this.curDot <= 0) {
this.curDot = num;
} else {
this.curDot--;
}
},
nextImg() {
let num = this.imgList.length - 1;
if (this.curDot >= num) {
this.curDot = 0;
} else {
this.curDot++;
}
},
},
};
</script>
<style lang="scss" scoped>
movable-view {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
movable-area {
height: 100%;
width: 100%;
position: fixed;
overflow: hidden;
}
movable-view image {
width: 100%;
}
.content {
height: 100vh;
width: 100vw;
display: flex;
align-items: center;
background: #00000076;
}
.pos {
position: absolute;
top: 0;
left: 0;
z-index: 9999;
}
.swiper {
height: 100%;
width: 100%;
}
.current-dot {
position: absolute;
bottom: 10%;
left: 25%;
width: 50%;
display: flex;
align-items: center;
justify-content: space-around;
.change-buttom {
padding: 10rpx;
border-radius: 50%;
background: #3f3f3f;
}
.cur {
font-size: 20rpx;
}
}
.font-white {
color: #fff !important;
}
::v-deep {
.uni-swiper-dots-horizontal {
bottom: 12%;
}
.uni-swiper-dot {
width: 10rpx;
height: 10rpx;
}
uni-video {
width: 100vw;
height: 100vh;
}
}
.video-preview {
position: relative;
.video-close {
position: absolute;
right: 50rpx;
top: 50rpx;
}
}
</style>

View File

@@ -0,0 +1,84 @@
{
"id": "g-preview-img",
"displayName": "g-preview-img一款兼容vue2vue3的图片预览插件视频预览支持单张多张左右滑动放大缩小",
"version": "1.0.4",
"description": "g-preview-img一款兼容vue2vue3的图片预览插件视频预览支持单张多张左右滑动放大缩小",
"keywords": [
"vue2",
"vue3",
"图片预览",
"视频预览"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@@ -0,0 +1,64 @@
![image](https://deaon-saasvideo.oss-cn-shanghai.aliyuncs.com/11111.gif)
### 一款兼容vue2vue3的图片预览插件视频预览支持图片视频混用支持单张多张左右滑动放大缩小
### 基础使用方法
```javascript
<template>
<image v-for="(item,idx) in imgList" :src="item" :key="idx" @tap="handleClick(idx)"></image>
<g-preview-img :imgList="imgList" ref="preview"><g-preview-img>
</template>
<script setup>
import { ref } from 'vue'
const preview = ref(null)
const imgList = ['图片路径1','图片路径2']
const handleClick = (idx)=>{
// idx为要打开的图片的索引也可以不传默认打开第一张
// handlePreviewImg的参数支持传入单张图片地址或单个视频地址
preview.value.handlePreviewImg(idx)
}
</script>
```
| 属性名/事件 | 类型 | 默认值 | 说明 |
| ----------------- | ------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| modeClass | Array/String | \['fade', 'zoom-out'] | uni-transition组件过渡效果可选值见 <https://uniapp.dcloud.net.cn/component/uniui/uni-transition.html#mode-class-%E5%86%85%E7%BD%AE%E8%BF%87%E6%B8%A1%E5%8A%A8%E7%94%BB%E7%B1%BB%E5%9E%8B%E8%AF%B4%E6%98%8E> |
| indicatorDotsType | Boolean | false | 多张图片的指示器ture为圆点false数字当图片列表只有一张图片时默认不展示指示器 |
| imgList | Array | | 图片列表 |
| disabledScale | Boolean | false | 是否禁止双指放大缩小 |
| @preview | 打开关闭事件 | | 接受一个参数ture为开启false为关闭 |
| @changeImg | 图片切换的事件 | | 参数为当前的图片索引 |
#### 插槽,自定义翻页按钮
```js
<g-preview-img :imgList="imgList" ref="preview">
<template>
<!--你的翻页按钮-->
<view @tap.stop="previousImg">上一页</view>
<view @tap.stop="nextImg">下一页</view>
</template>
</g-preview-img>
<script>
const preview = ref(null)
//上一页的方法
const previousImg = ()=>{
preview.value.previousImg()
}
//下一页的方法
const previousImg = ()=>{
preview.value.nextImg()
}
</script>
```
#### 支持uniapp原生swiper的属性
插件内部swiper标签上绑定了$attrs,所以在使用时可以传入一些swiper的属性
注意不要传disable-touch这个属性会有意想不到的错误
**插件bug会及时修复**

View File

@@ -0,0 +1,25 @@
## 0.1.22023-12-14
- fix: uvue 引入 API 自定义包出错
## 0.1.12023-12-11
- chore: uvue的二维码API独立需要单独下载
## 0.1.02023-12-07
- fix: 修复因utssdk目录导致无法运行
## 0.0.92023-12-06
- feat: 支持uvue
## 0.0.82023-12-06
- feat: 支持uvue
## 0.0.72023-12-06
- feat: 支持uvue
## 0.0.62023-12-06
- feat: 支持uvue
## 0.0.52023-07-30
- fix: 修复再次生成前没有清空,导致图形叠加
## 0.0.42023-07-27
- fix: 修复相同尺寸无法再次生成
## 0.0.32023-06-09
- feat: 支持通过`@vue/composition-api``vue2`上使用
- chore: 更新文档
## 0.0.22023-06-08
- chore: 更新文档
## 0.0.12023-06-08
- 首次

View File

@@ -0,0 +1,179 @@
<template>
<view class="l-qrcode" ref="l-qrcode" :style="[styles]">
<image class="l-qrcode__icon" v-if="icon !=''" :src="icon" :style="[iconStyle]"></image>
</view>
</template>
<script lang="ts">
import { type PropType } from 'vue'
import { QRCodeCanvas, QRCodePropsTypes , ImageSettings } from '@/uni_modules/lime-qrcodegen'
// import { addUnit } from '@/uni_modules/lime-shared/addUnit'
// import { unitConvert } from '@/uni_modules/lime-shared/unitConvert'
import { addUnit, unitConvert } from './utils'
import { TakeSnapshotFailCallback, TakeSnapshotCompleteCallback, TakeSnapshotSuccessCallback} from './type'
const name = 'l-qrcode'
export default {
name,
props: {
value: {
type: String,
default: ''
},
icon: {
type: String,
default: ''
},
size: {
type: Object,
default: 160
},
iconSize: {
type: Object,
default: 40
},
marginSize: {
type: Number,
default: 0
},
color: {
type: String,
default: '#000'
},
bgColor: {
type: String,
default: 'transparent'
},
bordered: {
type: Boolean,
default: true
},
errorLevel: {
type: String as PropType<'L' | 'M' | 'Q' | 'H'>,
default: 'M' // 'L' | 'M' | 'Q' | 'H'
},
useCanvasToTempFilePath: {
type: Boolean,
default: false
}
// status: {
// type: String as PropType<'active'|'expired'|'loading'>,
// default: 'active' // active | expired | loading
// }
},
emits: ['success'],
data() {
return {
qrcode: null as QRCodeCanvas | null
}
},
computed: {
styles() : Map<string, any> {
const style = new Map<string, any>()
const size = addUnit(this.size);
style.set('width', size)
style.set('height', size)
style.set('background', this.bgColor)
return style
},
iconStyle() : Map<string, any> {
const style = new Map<string, any>()
const size = addUnit(this.iconSize);
style.set('width', size)
style.set('height', size)
return style
},
qrCodeProps() : QRCodePropsTypes {
const param = {
value: this.value,
size: unitConvert(this.size),
fgColor: this.color,
level: ['L', 'M', 'Q', 'H'].includes(this.errorLevel) ? this.errorLevel : 'M',
marginSize: this.marginSize,
imageSettings: null,
includeMargin: this.bordered,
} as QRCodePropsTypes
if(this.iconSize != '' && this.icon != ''){
const size = unitConvert(this.iconSize)
param.imageSettings = {
width: size,
height: size,
excavate: true
} as ImageSettings
}
return param
}
},
methods: {
canvasToTempFilePath(options :UTSJSONObject) : void {
const el = (this.$refs['l-qrcode'] as Element);
const format = options.getString('format') ?? 'png';
const fail = options.get('fail') as TakeSnapshotFailCallback | null;
const complete = options.get('complete') as TakeSnapshotCompleteCallback | null;
const success = options.get('success') as TakeSnapshotSuccessCallback | null;
const newOptions = {
format,
fail,
complete,
success,
} as TakeSnapshotOptions
el.takeSnapshot(newOptions)
}
},
mounted() {
const el = (this.$refs['l-qrcode'] as Element)
const ctx = el.getDrawableContext();
if (ctx == null) return
this.qrcode = new QRCodeCanvas(ctx)
const render = (v : QRCodePropsTypes) => {
this.qrcode!.render(v);
if (this.useCanvasToTempFilePath) {
setTimeout(() => {
this.canvasToTempFilePath({
success: (res: TakeSnapshotSuccess) => {
this.$emit('success', res.tempFilePath)
},
fail: (_: TakeSnapshotFail) => {
uni.showToast({
icon: 'error',
title: '截图失败'
})
}
})
// TakeSnapshotOptions
},200)
}
}
this.$watch('qrCodeProps', (v: QRCodePropsTypes) => {
render(v)
}, {immediate: true})
}
}
</script>
<style lang="scss">
.l-qrcode {
position: relative;
background-color: aqua;
justify-content: center;
align-items: center;
&-mask {
position: absolute;
// inset: 0;
// inset-block-start: 0;
// inset-inline-start: 0;
z-index: 10;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
// width: 100%;
// height: 100%;
color: rgba(0, 0, 0, 0.88);
line-height: 1.5714285714285714;
background: rgba(255, 255, 255, 0.96);
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,223 @@
<template>
<view class="l-qrcode" :style="[styles]">
<!-- #ifndef APP-NVUE -->
<canvas :style="styles" type="2d" :canvas-id="canvasId" :id="canvasId"></canvas>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<web-view
ref="qrcodeRef"
@pagefinish="onFinished"
@error="onError"
@onPostMessage="onMessage"
:style="styles" src="/uni_modules/lime-qrcode/hybrid/html/index.html?v=1"></web-view>
<!-- #endif -->
<!-- <view class="l-qrcode-mask" v-if="['loading', 'expired'].includes(props.status)">
<l-loading v-if="props.status == 'loading'"></l-loading>
<view class="l-qrcode-expired" v-if="props.status == 'expired'">
<slot></slot>
</view>
</view> -->
</view>
</template>
<script lang="ts">
// @ts-nocheck
import { computed, defineComponent, getCurrentInstance, watch, onUnmounted, onMounted } from '@/uni_modules/lime-shared/vue';
import QRCodeProps from './props'
// #ifndef APP-NVUE
import { getCanvas, isCanvas2d } from './useCanvas'
import { QRCodeCanvas } from './qrcode.js';
// #endif
import { addUnit } from '@/uni_modules/lime-shared/addUnit'
import { createImage } from '@/uni_modules/lime-shared/createImage'
import { unitConvert } from '@/uni_modules/lime-shared/unitConvert'
import { isBase64 } from '@/uni_modules/lime-shared/isBase64'
import { pathToBase64 } from '@/uni_modules/lime-shared/pathToBase64'
import { debounce } from '@/uni_modules/lime-shared/debounce'
const name = 'l-qrcode'
export default defineComponent({
name,
props: QRCodeProps,
emits: ['success'],
setup(props, {emit}) {
const context = getCurrentInstance();
const canvasId = `l-qrcode${context.uid}`
const styles = computed(() => `width: ${addUnit(props.size)}; height: ${addUnit(props.size)};`)
let qrcode = null
let canvas = null
const qrCodeProps = computed(() => {
const { value, icon, size, color, bgColor, bordered, iconSize, errorLevel, marginSize } = props
const imageSettings = {
src: icon,
x: undefined,
y: undefined,
height: unitConvert(iconSize),
width: unitConvert(iconSize),
excavate: true,
}
return {
value,
size: unitConvert(size),
level: errorLevel,
bgColor,
fgColor: color,
imageSettings: icon ? imageSettings : undefined,
includeMargin: bordered,
marginSize: marginSize ?? 0
}
})
// #ifdef APP-NVUE
const stacks = new Map()
// #endif
const canvasToTempFilePath = debounce((args: UniNamespace.CanvasToTempFilePathRes) => {
if(!canvas) return
// #ifndef APP-NVUE
const copyArgs = Object.assign({
canvasId,
canvas: null
}, args)
if (isCanvas2d) {
copyArgs.canvas = canvas
}
if ('toTempFilePath' in canvas) {
canvas.toTempFilePath(copyArgs)
} else {
uni.canvasToTempFilePath(copyArgs, context);
}
// #endif
// #ifdef APP-NVUE
if(!stacks.size) {
const flie = 'file-' + Math.random();
const stack = {args, time: +new Date()}
stacks.set(`${flie}`, stack)
canvas.toDataURL(flie)
setTimeout(() => {
const stack = stacks.get(flie)
if(stack && 'fail' in stack.args) {
stack.args.fail({
error: '超时'
})
stacks.delete(flie)
}
},5000)
}
// #endif
})
const useCanvasToTempFilePath = () => {
if(props.useCanvasToTempFilePath) {
canvasToTempFilePath({
success(res: UniNamespace.CanvasToTempFilePathRes) {
emit('success', res.tempFilePath)
}
})
}
}
// #ifdef APP-NVUE
const onFinished = () => {
const { pixelRatio } = uni.getSystemInfoSync()
canvas = {
toDataURL(flie: string) {
const ref: any = context.refs['qrcodeRef'];
if(ref) {
ref?.evalJS(`toDataURL('${flie}')`)
}
}
};
qrcode = {
async render(props: any) {
const ref: any = context.refs['qrcodeRef'];
const { src } = props.imageSettings || { };
if(!ref) return
if(src && !isBase64(src) && !/^http/.test(src) && /^\/static/.test(src)) {
props.imageSettings.src = await pathToBase64(src)
}
const _props = JSON.stringify(Object.assign({}, props, {pixelRatio}));
ref?.evalJS(`render(${_props})`);
}
}
qrcode.render(qrCodeProps.value)
useCanvasToTempFilePath()
}
const onError = () => {
console.warn('lime-qrcode 加载失败')
}
const onMessage = (e: any) => {
const {detail:{data: [res]}} = e
if(res.event == 'toDataURL') {
const {file, image, msg} = res.data;
const stack = stacks.get(file)
if(stack && image && 'success' in stack.args) {
stack.args.success({tempFilePath: image})
stacks.delete(file)
} else if(stack && 'fails' in stack.args) {
stack.args.fail({error: msg})
stacks.delete(file)
}
}
}
// #endif
const propsWatch = watch(props, () => {
if (qrcode) {
qrcode.render(qrCodeProps.value)
useCanvasToTempFilePath()
}
})
onMounted(() => {
// #ifndef APP-NVUE
getCanvas(canvasId, { context }).then(res => {
canvas = res
qrcode = new QRCodeCanvas(res, {
// #ifdef H5
path2D: false,
// #endif
pixelRatio: isCanvas2d ? uni.getSystemInfoSync().pixelRatio : 1,
createImage
})
qrcode.render(qrCodeProps.value)
useCanvasToTempFilePath()
})
// #endif
})
onUnmounted(() => {
propsWatch && propsWatch()
})
return {
canvasId,
styles,
props,
canvasToTempFilePath,
// #ifdef APP-NVUE
onFinished,
onError,
onMessage
// #endif
}
}
})
</script>
<style lang="scss">
.l-qrcode {
position: relative;
&-mask {
position: absolute;
inset: 0;
// inset-block-start: 0;
// inset-inline-start: 0;
z-index: 10;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
// width: 100%;
// height: 100%;
color: rgba(0, 0, 0, 0.88);
line-height: 1.5714285714285714;
background: rgba(255, 255, 255, 0.96);
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,36 @@
// @ts-nocheck
// import type { PropType } from './vue'
export default {
value: String,
icon: String,
size: {
type: [Number, String],
default: 160
},
iconSize: {
type: [Number, String],
default: 40
},
marginSize: Number,
color: {
type: String,
default: '#000'
},
bgColor: {
type: String,
default: 'transparent'
},
bordered: {
type: Boolean,
default: true
},
errorLevel: {
type: String as PropType<'L'|'M'|'Q'|'H'>,
default: 'M' // 'L' | 'M' | 'Q' | 'H'
},
useCanvasToTempFilePath: Boolean
// status: {
// type: String as PropType<'active'|'expired'|'loading'>,
// default: 'active' // active | expired | loading
// }
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
export type ImageSettings = {
width: number
height: number
x?: number
y?: number
excavate: boolean
}
export type QRCodePropsTypes = {
value?: string
size?: number
fgColor?: string
level?: string
marginSize: number
includeMargin: boolean
imageSettings?: ImageSettings
}
export type QRCodeCallback = (cells : boolean[][]) => void
export type Excavation = {
x: number
y: number
h: number
w: number
}

View File

@@ -0,0 +1,78 @@
// @ts-nocheck
import type { ComponentInternalInstance } from './vue'
import { getRect } from '@/uni_modules/lime-shared/getRect'
import { canIUseCanvas2d } from '@/uni_modules/lime-shared/canIUseCanvas2d'
export const isCanvas2d = canIUseCanvas2d()
export async function getCanvas(canvasId: string, options: {context: ComponentInternalInstance}) {
let { context } = options
// #ifdef MP || VUE2
if (context.proxy) context = context.proxy
// #endif
return getRect('#' + canvasId, {context, type: isCanvas2d ? 'fields': 'boundingClientRect'}).then(res => {
if(res.node){
return res.node
} else {
const ctx = uni.createCanvasContext(canvasId, context)
return {
getContext(type: string) {
if(type == '2d') {
return ctx
}
},
width: res.width,
height: res.height,
}
// #ifdef H5
// canvas.value = context.proxy.$el.querySelector('#'+ canvasId)
// #endif
}
})
}
// #ifndef H5 || APP-NVUE
class Image {
currentSrc: string | null = null
naturalHeight: number = 0
naturalWidth: number = 0
width: number = 0
height: number = 0
tagName: string = 'IMG'
path: any = ''
crossOrigin: any = ''
referrerPolicy: any = ''
onload: () => void
onerror: () => void
constructor() {}
set src(src) {
this.currentSrc = src
uni.getImageInfo({
src,
success: (res) => {
this.path = res.path
this.naturalWidth = this.width = res.width
this.naturalHeight = this.height = res.height
this.onload()
},
fail: () => {
this.onerror()
}
})
}
get src() {
return this.currentSrc
}
}
// #endif
export function createImage(canvas: WechatMiniprogram.Canvas) {
if(canvas && canvas.createImage) {
return canvas.createImage()
} else if(typeof window != 'undefined' && window.Image) {
return new window.Image()
}
// #ifndef H5 || APP-NVUE
return new Image()
// #endif
}

View File

@@ -0,0 +1,35 @@
export function addUnit(value: any|null):string{
if(value == null){
return ''
}
value = `${value}`
return /^(-)?\d+(\\.\d+)?$/.test(value) ? `${value}px` : value
}
export function unitConvert(value: any|null): number{
if(typeof value == 'number'){
return value as number
}
if(typeof value == 'string'){
value = `${value}`
if(/^(-)?\d+(\\.\d+)?$/.test(value)){
return parseFloat(value);
}
const reg = /^-?([0-9]+)?([.]{1}[0-9]+){0,1}(em|rpx|px|%)$/g;
const results = reg.exec(value);
if (results == null) {
return 0;
}
const unit = results[3];
const v = parseFloat(value);
if (unit == 'rpx') {
const { windowWidth } = uni.getWindowInfo()
return windowWidth / 750 * v;
}
if (unit == 'px') {
return v;
}
}
return 0;
}

View File

@@ -0,0 +1,134 @@
<template>
<view class="demo-block">
<text class="demo-block__title-text ultra">QRCode</text>
<text class="demo-block__desc-text">QRCode</text>
<view class="demo-block__body">
<view class="demo-block">
<text class="demo-block__title-text large">基础</text>
<view class="demo-block__body">
<l-qrcode value="https://limeui.qcoon.cn" size="300rpx"></l-qrcode>
</view>
</view>
<view class="demo-block">
<text class="demo-block__title-text large">icon</text>
<view class="demo-block__body">
<image v-if="image !=''" :src="image" style="width: 300rpx;" mode="widthFix"></image>
<view style="flex-direction: row; justify-content: space-between">
<l-qrcode ref="qrcodeRef" value="https://limeui.qcoon.cn" size="300rpx" icon="https://img10.360buyimg.com/img/jfs/t1/182127/16/37474/11761/64659c31F0cd84976/21f25b952f03a49a.jpg" iconSize="70rpx"></l-qrcode>
<l-qrcode :useCanvasToTempFilePath="true" @success="success" value="https://limeui.qcoon.cn" size="300rpx" icon="https://img10.360buyimg.com/img/jfs/t1/182127/16/37474/11761/64659c31F0cd84976/21f25b952f03a49a.jpg" iconSize="70rpx"></l-qrcode>
</view>
<button @click="onClick">生成图片</button>
</view>
</view>
<view class="demo-block">
<text class="demo-block__title-text large">颜色</text>
<view class="demo-block__body">
<view style="flex-direction: row; justify-content: space-between">
<l-qrcode value="https://limeui.qcoon.cn" size="300rpx" color="rgb(82,196,26)"></l-qrcode>
<l-qrcode value="https://limeui.qcoon.cn" size="300rpx" color="rgb(22,119,255)" bgColor="rgb(245,245,245)"></l-qrcode>
</view>
</view>
</view>
<view class="demo-block">
<text class="demo-block__title-text large">纠错比例</text>
<view class="demo-block__body">
<l-qrcode value="img10.360buyimg.com/img/jfs/t1/182127/16/37474/11761/64659c31F0cd84976/21f25b952f03a49a.jpg" size="300rpx" :errorLevel="levels[index]"></l-qrcode>
<button @click="onToggle">切换纠错等级:{{levels[index]}}</button>
</view>
</view>
<view class="demo-block">
<text class="demo-block__title-text large">动态</text>
<view class="demo-block__body">
<l-qrcode :value="text" size="300rpx" :marginSize="1" bgColor="white"></l-qrcode>
<button @click="update">更新</button>
</view>
</view>
</view>
</view>
</template>
<script>
// import {ComponentPublicInstance} from 'vue'
export default {
name: 'lime-qrcode',
data() {
return {
text: 'qcoon.com.cn',
image: '',
index: 0,
levels: ['L', 'M', 'Q', 'H']
}
},
methods:{
success(src: string) {
console.log(`src`, src)
},
update() {
this.text = `qcoon.cn?v=${Math.random()}`
},
onToggle() {
this.index++
this.index = this.index % this.levels.length
},
onClick() {
const el:LQrcodeComponentPublicInstance = this.$refs['qrcodeRef'] as LQrcodeComponentPublicInstance
el.canvasToTempFilePath({
success:(res: TakeSnapshotSuccess)=>{
this.image = res.tempFilePath
}
})
}
},
mounted() {
}
}
</script>
<style lang="scss">
.demo-block {
margin: 32px 20px 0;
overflow: visible;
&__title {
margin: 0;
margin-top: 8px;
&-text {
color: rgba(0, 0, 0, 0.6);
font-weight: 400;
font-size: 14px;
line-height: 16px;
&.large {
color: rgba(0, 0, 0, 0.9);
font-size: 18px;
font-weight: 700;
line-height: 26px;
}
&.ultra {
color: rgba(0, 0, 0, 0.9);
font-size: 24px;
font-weight: 700;
line-height: 32px;
}
}
}
&__desc-text {
color: rgba(0, 0, 0, 0.6);
margin: 8px 16px 0 0;
font-size: 14px;
line-height: 22px;
}
&__body {
margin: 16px 0;
overflow: visible;
.demo-block {
// margin-top: 0px;
margin: 0;
}
}
}
</style>

View File

@@ -0,0 +1,79 @@
<template>
<demo-block title="QRCode" type="ultra">
<demo-block title="基础">
<l-qrcode value="https://limeui.qcoon.cn" size="300rpx"></l-qrcode>
</demo-block>
<demo-block title="icon">
<view style="display: flex; gap: 10px">
<image v-if="image" :src="image" style="width: 300rpx;" mode="widthFix"></image>
<l-qrcode ref="qrcodeRef" value="https://limeui.qcoon.cn" size="300rpx" icon="https://img10.360buyimg.com/img/jfs/t1/182127/16/37474/11761/64659c31F0cd84976/21f25b952f03a49a.jpg" iconSize="70rpx"></l-qrcode>
<l-qrcode useCanvasToTempFilePath @success="success" value="https://limeui.qcoon.cn" size="300rpx" icon="https://img10.360buyimg.com/img/jfs/t1/182127/16/37474/11761/64659c31F0cd84976/21f25b952f03a49a.jpg" iconSize="70rpx"></l-qrcode>
</view>
<button @click="onClick">生成图片</button>
</demo-block>
<demo-block title="颜色">
<view style="display: flex; gap: 10px">
<l-qrcode value="https://limeui.qcoon.cn" size="300rpx" color="rgb(82,196,26)"></l-qrcode>
<l-qrcode value="https://limeui.qcoon.cn" size="300rpx" color="rgb(22,119,255)" bgColor="rgb(245,245,245)"></l-qrcode>
</view>
</demo-block>
<demo-block title="纠错比例">
<l-qrcode value="img10.360buyimg.com/img/jfs/t1/182127/16/37474/11761/64659c31F0cd84976/21f25b952f03a49a.jpg" size="300rpx" :errorLevel="levels[index]"></l-qrcode>
<button @click="onToggle">切换纠错等级{{levels[index]}}</button>
</demo-block>
<demo-block title="动态">
<l-qrcode :value="text" size="300rpx" marginSize="20rpx" bgColor="white"></l-qrcode>
<button @click="update">更新</button>
</demo-block>
</demo-block>
</template>
<script>
import {ref, defineComponent} from '../l-qrcode/vue'
export default defineComponent({
setup() {
const qrcodeRef = ref(null)
const image = ref(null)
const text = ref('qcoon.com.cn')
const levels = ['L', 'M', 'Q', 'H']
let index = ref(0)
const onToggle = () => {
index.value++
index.value = index.value % levels.length
}
const onClick = () => {
if(qrcodeRef.value) {
qrcodeRef.value.canvasToTempFilePath({
success(res) {
image.value = res.tempFilePath
console.log('success:::', res)
},
fail(err) {
console.log('err:::', err)
}
})
}
}
const success = (res) => {
console.log('res', res)
}
const update = () =>{
text.value = `qcoon.cn?v=${Math.random()}`
}
return {
levels,
index,
image,
text,
qrcodeRef,
onClick,
update,
success,
onToggle,
}
}
})
</script>
<style>
</style>

View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lime-qrcode</title>
<style>
html,body,canvas {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
pointer-events: none;
/* background-color: rgba(255,0,0,0.1) */
}
</style>
</head>
<body>
<canvas id="lime-qrcode"></canvas>
<script type="text/javascript" src="./uni.webview.1.5.3.js"></script>
<script type="text/javascript" src="./qrcode.min.js"></script>
<script>
var canvas = document.querySelector('#lime-qrcode')
var pixelRatio = window.devicePixelRatio || 1
function appendWatermark(image) {
emit('append', mark.toDataURL())
}
var qrcode = new lime.QRCodeCanvas(canvas, {
pixelRatio,
})
function render(props) {
if(props.pixelRatio) {
pixelRatio = props.pixelRatio
}
if(qrcode) {
qrcode.render(props)
}
}
function toDataURL(file) {
if(qrcode && canvas) {
try{
const image = canvas.toDataURL()
emit('toDataURL', {
file,
image
})
}catch(e){
emit('toDataURL', {
file,
msg: e
})
}
}
}
function emit(event, data) {
postMessage({
event,
data
});
};
function postMessage(data) {
uni.postMessage({
data
});
};
// render({
// content: ['Lime UI'],
// // rotate: -22,
// // baseSize: 2,
// // fontGap: 3
// })
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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