Compare commits
32 Commits
287f123ac7
...
jwl-gift
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d6252d5cb | |||
|
|
056ca965b3 | ||
| 4fd6a21f35 | |||
| 7b1db47383 | |||
| 79236493e6 | |||
| 59c49bfdf2 | |||
| 110e9d4adc | |||
|
|
b533581a5d | ||
| ac8acdccda | |||
| f4b6f96649 | |||
| 9ba3f6ed48 | |||
| 253ab2a80d | |||
| bfdbd3f7f3 | |||
| e3544ee06e | |||
| 7e15974ea6 | |||
| 46972d5bff | |||
| 851319e24c | |||
| 19616d56c5 | |||
| 89c4b2148e | |||
| e68a422cc8 | |||
| 2e93ad93e9 | |||
| c783ff969d | |||
| 4526430a38 | |||
| 3a0545852f | |||
| 0410e5dda9 | |||
| 0c230fa5f1 | |||
| ded28b62fb | |||
| 6834b3f9fe | |||
| 3379a9b18e | |||
| 9e871e4079 | |||
| 728fefac03 | |||
| bf05f771f7 |
@@ -6,6 +6,5 @@ VITE_APP_ENV = 'development'
|
||||
|
||||
# 金武联驾校/开发环境
|
||||
VITE_APP_BASE_API = 'https://jwl.ahduima.com/'
|
||||
|
||||
#
|
||||
VITE_WEB_BASE_URL = 'https://jwl.ahduima.com'
|
||||
14
src/App.vue
14
src/App.vue
@@ -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()
|
||||
useQuestionStore().getAllQuestion()
|
||||
if (useUserStore().isLogin) {
|
||||
useUserStore().getUserInfo()
|
||||
useUserStore().searchUserVip()
|
||||
}
|
||||
},
|
||||
onShow: function () {
|
||||
useQuestionStore().getAllQuestion()
|
||||
console.log('App Show')
|
||||
},
|
||||
onHide: function () {
|
||||
@@ -23,5 +28,8 @@ export default {
|
||||
/*每个页面公共css */
|
||||
@import "uni_modules/uview-plus/index.scss";
|
||||
@import "static/style/index.scss";
|
||||
button::after{ border: none;}
|
||||
|
||||
button::after {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
1404
src/components/yan-qr/qrcode.js
Normal file
1404
src/components/yan-qr/qrcode.js
Normal file
File diff suppressed because it is too large
Load Diff
95
src/components/yan-qr/yan-qr.md
Normal file
95
src/components/yan-qr/yan-qr.md
Normal 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>
|
||||
```
|
||||
115
src/components/yan-qr/yan-qr.vue
Normal file
115
src/components/yan-qr/yan-qr.vue
Normal 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>
|
||||
@@ -8,3 +8,20 @@ export function getAliCompanyInfo(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
|
||||
});
|
||||
}
|
||||
@@ -50,7 +50,14 @@ export function querySysConfigList(carTypeId, configKey) {
|
||||
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({
|
||||
|
||||
@@ -64,7 +64,8 @@ export default class JtoolsPay {
|
||||
"description": this.order.description,
|
||||
"money": this.order.money,
|
||||
"outTradeNo": this.order.outTradeNo,
|
||||
"userId": this.order.userId
|
||||
"userId": this.order.userId,
|
||||
"tradeType":'1'
|
||||
}
|
||||
if (uni.getStorageSync('openId')) {
|
||||
params.openId = uni.getStorageSync('openId');
|
||||
|
||||
@@ -29,7 +29,7 @@ function service(options = {}) {
|
||||
title: res?.data?.message || '请重新登录',
|
||||
icon: 'none'
|
||||
});
|
||||
useUserStore().logout()
|
||||
useUserStore().logoutWithoutToken()
|
||||
//请求成功
|
||||
resolved(res.data);
|
||||
} else if(res.data.code != '0000'&&res.data.code !='4001') {
|
||||
|
||||
@@ -4,7 +4,8 @@ import {
|
||||
import http from '@/jtools/request/index';
|
||||
import {
|
||||
queryQuestion,
|
||||
getVersion
|
||||
getVersion,
|
||||
querySysConfig
|
||||
} from '@/jtools/api/question';
|
||||
import storage from '@/jtools/storage';
|
||||
|
||||
@@ -12,6 +13,7 @@ const question = defineStore({
|
||||
id: 'question',
|
||||
state: () => ({
|
||||
currentCartype: storage.get('carType') || '1001',
|
||||
currentCarName: storage.get('carName') || '小车C1/C2/C3',
|
||||
orderQuestion_subject1: storage.get('question_subject1') || [], //科目一顺序做题
|
||||
orderQuestion_subject4: storage.get('question_subject4') || [], //科目四顺序做题
|
||||
currentIndex_subject1: 0, //科目一索引 顺序做题
|
||||
@@ -23,18 +25,36 @@ const question = defineStore({
|
||||
}),
|
||||
|
||||
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)
|
||||
this.getOrderQuestion_sub4(true)
|
||||
this.getOrderQuestion_sub1(true, urlOne)
|
||||
this.getOrderQuestion_sub4(true, urlFour)
|
||||
} else {
|
||||
this.getOrderQuestion_sub1()
|
||||
this.getOrderQuestion_sub4()
|
||||
this.getOrderQuestion_sub1(false, urlOne)
|
||||
this.getOrderQuestion_sub4(false, urlOne)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -53,21 +73,17 @@ const question = defineStore({
|
||||
storage.set('curSubject', val)
|
||||
},
|
||||
// 获取顺序做题科目1
|
||||
getOrderQuestion_sub1(isUpdate) {
|
||||
getOrderQuestion_sub1(isUpdate, url) {
|
||||
if (isUpdate) {
|
||||
this.loading_subject1 = true
|
||||
queryQuestion({
|
||||
carTypeId: this.currentCartype,
|
||||
subject: '1',
|
||||
// questionIdList:[10982,10983,10985,10986]
|
||||
}).then(res => {
|
||||
if (res.code == '0000') {
|
||||
this.loading_subject1=false
|
||||
uni.showToast({
|
||||
title:'题库加载完成!'
|
||||
})
|
||||
this.orderQuestion_subject1 = res.data
|
||||
const diveList=this.divideArray(this.orderQuestion_subject1,5)
|
||||
const that = this
|
||||
uni.request({
|
||||
url: url,
|
||||
success(resp) {
|
||||
if (resp.data) {
|
||||
that.orderQuestion_subject1 = resp.data.data
|
||||
const diveList = that.divideArray(that.orderQuestion_subject1, 5)
|
||||
that.loading_subject1 = false
|
||||
uni.setStorageSync('questionOneSub1', diveList[0])
|
||||
uni.setStorageSync('questionOneSub2', diveList[1])
|
||||
uni.setStorageSync('questionOneSub3', diveList[2])
|
||||
@@ -77,7 +93,7 @@ const question = defineStore({
|
||||
const trueList = storage.get('rightList_subject1') || []
|
||||
const falseArr = []
|
||||
const rightArr = []
|
||||
this.orderQuestion_subject1.forEach(item=>{
|
||||
that.orderQuestion_subject1.forEach(item => {
|
||||
if (falseList.includes(item.questionId)) {
|
||||
falseArr.push(item.questionId)
|
||||
}
|
||||
@@ -88,6 +104,7 @@ const question = defineStore({
|
||||
storage.set('wrongList_subject1', falseArr)
|
||||
storage.set('rightList_subject1', rightArr)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const list1 = uni.getStorageSync('questionOneSub1') || []
|
||||
@@ -100,18 +117,14 @@ const question = defineStore({
|
||||
|
||||
} else {
|
||||
this.loading_subject1 = true
|
||||
queryQuestion({
|
||||
carTypeId: this.currentCartype,
|
||||
subject: '1',
|
||||
// questionIdList:[10982,10983,10985,10986]
|
||||
}).then(res => {
|
||||
if (res.code == '0000') {
|
||||
this.loading_subject1=false
|
||||
uni.showToast({
|
||||
title:'题库加载完成!'
|
||||
})
|
||||
this.orderQuestion_subject1 = res.data
|
||||
const diveList=this.divideArray(this.orderQuestion_subject1,5)
|
||||
const that = this
|
||||
uni.request({
|
||||
url: url,
|
||||
success(resp) {
|
||||
if (resp.data) {
|
||||
that.orderQuestion_subject1 = resp.data.data
|
||||
const diveList = that.divideArray(that.orderQuestion_subject1, 5)
|
||||
that.loading_subject1 = false
|
||||
uni.setStorageSync('questionOneSub1', diveList[0])
|
||||
uni.setStorageSync('questionOneSub2', diveList[1])
|
||||
uni.setStorageSync('questionOneSub3', diveList[2])
|
||||
@@ -121,7 +134,7 @@ const question = defineStore({
|
||||
const trueList = storage.get('rightList_subject1') || []
|
||||
const falseArr = []
|
||||
const rightArr = []
|
||||
this.orderQuestion_subject1.forEach(item=>{
|
||||
that.orderQuestion_subject1.forEach(item => {
|
||||
if (falseList.includes(item.questionId)) {
|
||||
falseArr.push(item.questionId)
|
||||
}
|
||||
@@ -132,23 +145,23 @@ const question = defineStore({
|
||||
storage.set('wrongList_subject1', falseArr)
|
||||
storage.set('rightList_subject1', rightArr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取顺序做题科目4
|
||||
getOrderQuestion_sub4(isUpdate) {
|
||||
getOrderQuestion_sub4(isUpdate, url) {
|
||||
if (isUpdate) {
|
||||
this.loading_subject4 = true
|
||||
queryQuestion({
|
||||
carTypeId: this.currentCartype,
|
||||
subject: '4',
|
||||
// questionIdList:[10982,10983,10985,10986]
|
||||
}).then(res => {
|
||||
if (res.code == '0000') {
|
||||
this.loading_subject4=false
|
||||
this.orderQuestion_subject4 = res.data
|
||||
const diveList=this.divideArray(this.orderQuestion_subject4,5)
|
||||
const that = this
|
||||
uni.request({
|
||||
url: url,
|
||||
success(resp) {
|
||||
if (resp.data) {
|
||||
that.orderQuestion_subject4 = resp.data.data
|
||||
const diveList = that.divideArray(that.orderQuestion_subject4, 5)
|
||||
that.loading_subject4 = false
|
||||
uni.setStorageSync('questionFourSub1', diveList[0])
|
||||
uni.setStorageSync('questionFourSub2', diveList[1])
|
||||
uni.setStorageSync('questionFourSub3', diveList[2])
|
||||
@@ -158,7 +171,7 @@ const question = defineStore({
|
||||
const trueList = storage.get('rightList_subject4') || []
|
||||
const falseArr = []
|
||||
const rightArr = []
|
||||
this.orderQuestion_subject4.forEach(item=>{
|
||||
that.orderQuestion_subject4.forEach(item => {
|
||||
if (falseList.includes(item.questionId)) {
|
||||
falseArr.push(item.questionId)
|
||||
}
|
||||
@@ -169,6 +182,7 @@ const question = defineStore({
|
||||
storage.set('wrongList_subject4', falseArr)
|
||||
storage.set('rightList_subject4', rightArr)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const list1 = uni.getStorageSync('questionFourSub1') || []
|
||||
@@ -181,15 +195,14 @@ const question = defineStore({
|
||||
|
||||
} else {
|
||||
this.loading_subject4 = true
|
||||
queryQuestion({
|
||||
carTypeId: this.currentCartype,
|
||||
subject: '4',
|
||||
// questionIdList:[10982,10983,10985,10986]
|
||||
}).then(res => {
|
||||
if (res.code == '0000') {
|
||||
this.loading_subject4=false
|
||||
this.orderQuestion_subject4 = res.data
|
||||
const diveList=this.divideArray(this.orderQuestion_subject4,5)
|
||||
const that = this
|
||||
uni.request({
|
||||
url: url,
|
||||
success(resp) {
|
||||
if (resp.data) {
|
||||
that.orderQuestion_subject4 = resp.data.data
|
||||
const diveList = that.divideArray(that.orderQuestion_subject4, 5)
|
||||
that.loading_subject4 = false
|
||||
uni.setStorageSync('questionFourSub1', diveList[0])
|
||||
uni.setStorageSync('questionFourSub2', diveList[1])
|
||||
uni.setStorageSync('questionFourSub3', diveList[2])
|
||||
@@ -199,7 +212,7 @@ const question = defineStore({
|
||||
const trueList = storage.get('rightList_subject4') || []
|
||||
const falseArr = []
|
||||
const rightArr = []
|
||||
this.orderQuestion_subject4.forEach(item=>{
|
||||
that.orderQuestion_subject4.forEach(item => {
|
||||
if (falseList.includes(item.questionId)) {
|
||||
falseArr.push(item.questionId)
|
||||
}
|
||||
@@ -210,6 +223,7 @@ const question = defineStore({
|
||||
storage.set('wrongList_subject4', falseArr)
|
||||
storage.set('rightList_subject4', rightArr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -217,7 +231,6 @@ const question = defineStore({
|
||||
//获取索引
|
||||
getCurrentIndex(index, val) {
|
||||
this[`currentIndex_subject${val}`] = index
|
||||
console.log(`currentIndex_subject${val}`,this[`currentIndex_subject${val}`]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { login, logout, getInfo } from '@/jtools/api/login';
|
||||
import { queryVip,getVipList } from '@/jtools/api/vip'
|
||||
import { queryVip, getVipList } from '@/jtools/api/vip';
|
||||
import constants from '@/jtools/constants';
|
||||
import storage from '@/jtools/storage';
|
||||
|
||||
@@ -23,10 +23,11 @@ const useUserStore = defineStore({
|
||||
// 保存登录信息,用于重新登录
|
||||
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)
|
||||
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();
|
||||
@@ -39,44 +40,53 @@ const useUserStore = defineStore({
|
||||
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)
|
||||
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:'' })
|
||||
this.currentCartype = storage.get('carType') || '1001';
|
||||
const resp = await queryVip({ carTypeId: this.currentCartype, memberId: null, subject: '' });
|
||||
if (resp.code == '0000') {
|
||||
this.vipOnList = resp.data
|
||||
this.vipOnList = resp.data;
|
||||
}
|
||||
},
|
||||
// 查询所有的vip
|
||||
queryVipList() {
|
||||
this.currentCartype = storage.get('carType') || '1001';
|
||||
getVipList({ carTypeId: this.currentCartype, memberId: null, subject: '' }).then(resp => {
|
||||
if (resp.code == '0000') {
|
||||
this.vipAllList = resp.data
|
||||
this.vipAllList = resp.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default useUserStore;
|
||||
|
||||
18
src/package.json
Normal file
18
src/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"id": "yan-qr",
|
||||
"name": "动态生成二维码",
|
||||
"displayName": "动态生成二维码",
|
||||
"version": "1.0.0",
|
||||
"description": "动态生成二维码",
|
||||
"keywords": [
|
||||
"二维码",
|
||||
"生成二维码",
|
||||
"动态二维码"
|
||||
],
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,8 @@
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "金武联驾考"
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -104,6 +105,13 @@
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/testTip",
|
||||
"style": {
|
||||
"navigationBarTitleText": "模拟考试",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
@@ -158,6 +166,37 @@
|
||||
"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
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
26
src/pages/index/activity.vue
Normal file
26
src/pages/index/activity.vue
Normal 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>
|
||||
@@ -41,11 +41,11 @@
|
||||
<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>
|
||||
<view class="mt5">精简500题</view>
|
||||
<view class="mt5">精简{{titleNum}}题</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="wp33 flex ai-c jc-c" @tap="toExclusive">
|
||||
@@ -78,11 +78,10 @@
|
||||
</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">
|
||||
<view class="contain-box relative">
|
||||
@@ -97,7 +96,7 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -110,6 +109,7 @@
|
||||
import storage from '@/jtools/storage';
|
||||
import useQuestionStore from '@/jtools/store/question' //引入store
|
||||
import {
|
||||
querySysConfig,
|
||||
queryQuestionId,
|
||||
getTestQuestionId
|
||||
} from '@/jtools/api/question';
|
||||
@@ -127,11 +127,12 @@
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
titleNum:500,
|
||||
allQuestionNum: 0,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
this.getTitle()
|
||||
},
|
||||
computed: {
|
||||
...mapState(useUserStore, ["vipOnList", "token"]),
|
||||
@@ -143,6 +144,15 @@
|
||||
methods: {
|
||||
...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
|
||||
}
|
||||
})
|
||||
},
|
||||
async toTestRoom() {
|
||||
// uni.navigateTo({
|
||||
// url:"/pages/index/trueTest"
|
||||
@@ -161,11 +171,18 @@
|
||||
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: '当前题库非最新版,请更新~',
|
||||
@@ -207,7 +224,7 @@
|
||||
})
|
||||
},
|
||||
toAnswer(title, val) {
|
||||
if (title == '精简500题') {
|
||||
if (title == `精简${this.titleNum}题`) {
|
||||
queryQuestionId({
|
||||
versionId: this.version,
|
||||
carTypeId: storage.get('carType') || '1001',
|
||||
@@ -218,23 +235,38 @@
|
||||
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
|
||||
"&needVip=" + !result + "&questionIdList=" + listJson
|
||||
})
|
||||
}else{
|
||||
if (resp.data && resp.data.length > 3) {
|
||||
const arr = resp.data.slice(0, 3)
|
||||
} else {
|
||||
const arr = resp.data
|
||||
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
|
||||
"&needVip=" + !result + "&questionIdList=" + listJson
|
||||
})
|
||||
}else{
|
||||
uni.showToast({
|
||||
title: '暂无题目',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uni.redirectTo({
|
||||
@@ -268,7 +300,7 @@
|
||||
const arr = resp.data
|
||||
const listJson = JSON.stringify(arr)
|
||||
uni.navigateTo({
|
||||
url: "/pages/questionBank/practiceExams?title=" + title + "&subject=" + this.subject + "&questionIdList=" + listJson
|
||||
url: "/pages/index/testTip?subject=" + this.subject + "&questionIdList=" + listJson
|
||||
})
|
||||
} else if (resp.code === '4001') {
|
||||
uni.showToast({
|
||||
@@ -287,6 +319,7 @@
|
||||
...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))
|
||||
@@ -296,13 +329,13 @@
|
||||
})
|
||||
} else {
|
||||
if (resp.data && resp.data.length > 3) {
|
||||
const arr = resp.data.slice(0, 3)
|
||||
arr = resp.data.slice(0, 3)
|
||||
} else {
|
||||
const arr = resp.data
|
||||
arr = resp.data
|
||||
}
|
||||
const listJson = JSON.stringify(arr)
|
||||
uni.navigateTo({
|
||||
url: "/pages/questionBank/practiceExams?title=" + title + "&subject=" + this.subject + "&questionIdList=" + listJson+"&needVip="+result
|
||||
url: "/pages/index/videoVip?subject=" + this.subject
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
await this.getDiverType()
|
||||
// await this.getDiverType()
|
||||
},
|
||||
computed: {
|
||||
...mapState(useUserStore, ["vipOnList", "token"])
|
||||
@@ -134,9 +134,9 @@
|
||||
"subject": String(this.subject),
|
||||
"type": "2"
|
||||
}).then(resp => {
|
||||
if (resp.code === '0000') {
|
||||
if (resp.code === '0000' && resp.data &&resp.data.length) {
|
||||
this.baseList = resp.data
|
||||
this.videoList = resp.data[0] ? resp.data[0].videoList.slice(0, 5) : []
|
||||
this.videoList = resp.data[0] && resp.data[0].videoList? resp.data[0].videoList.slice(0, 5) : []
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -148,7 +148,15 @@
|
||||
const formatSecond = second > 59 ? 59 : second
|
||||
return `${hours > 0 ? `${hours}:` : ''}${minute < 10 ? '0' + minute : minute}:${formatSecond < 10 ? '0' + formatSecond : formatSecond}`
|
||||
},
|
||||
toVideo() {
|
||||
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 {
|
||||
@@ -158,10 +166,17 @@
|
||||
}
|
||||
})
|
||||
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"
|
||||
"&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))
|
||||
@@ -186,8 +201,10 @@
|
||||
"subject": String(this.subject),
|
||||
"type": "1"
|
||||
}).then(resp => {
|
||||
if(resp.code==='0000'){
|
||||
this.operateList = resp.data
|
||||
this.projectId = this.operateList[0]?.projectId
|
||||
}
|
||||
})
|
||||
},
|
||||
getDiverType() {
|
||||
|
||||
147
src/pages/index/components/ggl/index.vue
Normal file
147
src/pages/index/components/ggl/index.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<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">您今日还剩1次刮奖机会,共有999人参加活动</view>
|
||||
<view class="scraping">
|
||||
<scraping-card :result="result" watermark="刮一刮" title="刮一刮赢取大奖" ref="reset" ></scraping-card>
|
||||
<view v-if="showBtn" class="gj">
|
||||
<view class="btn" @tap="handleScrap">
|
||||
点我刮奖
|
||||
</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">
|
||||
<view v-for="(item, index) in winningList" :key="index" class="card-item">
|
||||
<text class="item-text">188****8888</text>
|
||||
<text class="item-text">一等奖</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">
|
||||
<view class="item-text">1. 中奖率100%</view>
|
||||
<view class="item-text">2. 报名后可获得一次抽奖机会</view>
|
||||
<view class="item-text">3. 中奖用户请于"我的-我的奖品"中查看并核销</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ScrapingCard from './scraping.vue'
|
||||
export default {
|
||||
components: {
|
||||
ScrapingCard
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: '特等奖',
|
||||
showBtn: true,
|
||||
winningList: [1,2,3,4,5,6,7,8]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleScrap() {
|
||||
this.showBtn = !this.showBtn
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
}
|
||||
}
|
||||
</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>
|
||||
266
src/pages/index/components/ggl/scraping.vue
Normal file
266
src/pages/index/components/ggl/scraping.vue
Normal file
@@ -0,0 +1,266 @@
|
||||
<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>
|
||||
</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: 60,
|
||||
},
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
/** @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;
|
||||
}
|
||||
</style>
|
||||
@@ -1,11 +1,20 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-loading-page :loading="getLoading" loading-text="题库更新中..."></u-loading-page>
|
||||
<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 style="height: 100vh;background-color: rgb(245, 245, 245);">
|
||||
<view class="m10tb">
|
||||
<u-swiper :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>
|
||||
@@ -35,6 +44,7 @@
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show:false,
|
||||
subject: storage.get('curSubject') || '1',
|
||||
curTab: 0,
|
||||
searchValue: '',
|
||||
@@ -42,24 +52,42 @@
|
||||
categoryList: [],
|
||||
rightList: storage.get(`rightList_subject${this.subject}`) || [],
|
||||
wrongList: storage.get(`wrongList_subject${this.subject}`) || [],
|
||||
activityList: ['https://cdn.uviewui.com/uview/swiper/swiper1.png']
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.curTab=Number(this.curSubject)-1
|
||||
this.getSubjectConfig()
|
||||
},
|
||||
onShow() {
|
||||
this.show=true
|
||||
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()
|
||||
}
|
||||
},
|
||||
onHide(){
|
||||
this.show=false
|
||||
},
|
||||
computed: {
|
||||
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1","curSubject"]), //映射函数,取出tagslist
|
||||
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1","curSubject","orderQuestion_subject1","orderQuestion_subject4"]), //映射函数,取出tagslist
|
||||
getLoading() {
|
||||
return this.loading_subject4 && this.loading_subject1
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
getLoading(newVal){
|
||||
if(this.show){
|
||||
if(newVal){
|
||||
if(this.loading_subject4 && this.loading_subject1){
|
||||
uni.hideTabBar();
|
||||
}
|
||||
}else{
|
||||
uni.showTabBar()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useQuestionStore, ['getOrderQuestion_sub4', 'getOrderQuestion_sub1', 'changeSubject']),
|
||||
//获取科目配置
|
||||
@@ -73,6 +101,8 @@
|
||||
name: item.configItemName
|
||||
}
|
||||
})
|
||||
this.subject=storage.get('curSubject') || '1',
|
||||
this.curTab=this.categoryList.findIndex(item=>item.configItemCode==this.subject)
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -89,6 +119,12 @@
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
// 去活动
|
||||
handleToActivity(index) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/activity'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
83
src/pages/index/testTip.vue
Normal file
83
src/pages/index/testTip.vue
Normal 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>
|
||||
@@ -133,7 +133,7 @@
|
||||
onLoad(option) {
|
||||
this.subject = option.subject || 1
|
||||
if(option.questionIdList){
|
||||
const idList=JSON.parse(op.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,
|
||||
|
||||
@@ -1,36 +1,73 @@
|
||||
<template>
|
||||
<view class="relative" style="height: 100vh;">
|
||||
<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%A1%B5%E8%83%8C%E6%99%AF%E5%9B%BE_20230830214136.png"></image>
|
||||
<view class="p14">
|
||||
<view class="flex jc-sb ai-c wp100">
|
||||
<view class="option_tem relative" :class="checkedId===item.memberId?'checked_item':''" v-for="(item,index) of priceList" :key="index" @click="checkPrice(item.memberId,item.price)">
|
||||
<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">
|
||||
<view class="mt5" v-if="!isIOS">
|
||||
<text class="fs14" style="color: #FF6E02;">¥</text>
|
||||
<text class="fs30 fw600" style="color: #FF6E02;">{{ item.price }}</text>
|
||||
</view>
|
||||
<text class="fs12 cor-999">长期有效</text>
|
||||
<view class="bottom_box fs12 cor-333" :class="checkedId===item.memberId?'checked_bottom':''">赠送vip题库</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 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">
|
||||
</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 class="vip_item">含精简500题</view>
|
||||
</view>
|
||||
<view class="flex ai-c">
|
||||
<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 class="vip_item">含考前密卷2套</view>
|
||||
</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 p14" style="position: absolute;left: 0;bottom:20px" @tap="handlePay()">
|
||||
<view class="wp100 mt15" v-if="subject == '1' || subject == '4'">
|
||||
<image class="wp100" mode="widthFix" :src="picUrl"></image>
|
||||
</view>
|
||||
</view>
|
||||
</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>
|
||||
<image style="width: 276rpx;height: 88rpx;margin-top: -5px;" src="../../static/image/index/buy.png"></image>
|
||||
@@ -45,12 +82,15 @@
|
||||
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,
|
||||
@@ -59,22 +99,41 @@
|
||||
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
|
||||
@@ -93,9 +152,10 @@
|
||||
},
|
||||
getVipList() {
|
||||
getVipList({
|
||||
currentCartype: storage.get('carType') || '1001',
|
||||
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
|
||||
@@ -106,6 +166,7 @@
|
||||
item.all = true
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
checkPrice(val, price) {
|
||||
@@ -128,11 +189,12 @@
|
||||
border-radius: 16rpx 46rpx 16rpx 16rpx;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.checked_item {
|
||||
width: 228rpx;
|
||||
background: #FFF0E5;
|
||||
border: 4px solid #FF6E02;
|
||||
}
|
||||
|
||||
.bottom_box {
|
||||
width: 214rpx;
|
||||
height: 40rpx;
|
||||
@@ -144,12 +206,14 @@
|
||||
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;
|
||||
@@ -163,6 +227,7 @@
|
||||
left: 10rpx;
|
||||
top: -18rpx
|
||||
}
|
||||
|
||||
.intr_box {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@@ -170,6 +235,7 @@
|
||||
background: #FFF0E5;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.vip_item {
|
||||
width: 208rpx;
|
||||
height: 54rpx;
|
||||
@@ -179,6 +245,7 @@
|
||||
background: #F3D7C2;
|
||||
border-radius: 0rpx 10rpx 10rpx 10rpx;
|
||||
}
|
||||
|
||||
.sub_btn {
|
||||
width: 100%;
|
||||
height: 110rpx;
|
||||
@@ -188,4 +255,19 @@
|
||||
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>
|
||||
@@ -35,6 +35,7 @@
|
||||
login
|
||||
} from '@/jtools/api/login'
|
||||
import useUserStore from '@/jtools/store/user'
|
||||
import storage from '@/jtools/storage';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -80,7 +81,11 @@
|
||||
},
|
||||
bindLogin() {
|
||||
if (isPhone(this.login.phone) && this.login.code) {
|
||||
useUserStore().login(this.login).then(resp => {
|
||||
let params = { ...this.login }
|
||||
if (storage.get('companyId')) {
|
||||
params.id = storage.get('companyId')
|
||||
}
|
||||
useUserStore().login(params).then(resp => {
|
||||
if (resp.userId) {
|
||||
useUserStore().getUserInfo()
|
||||
useUserStore().searchUserVip()
|
||||
@@ -160,5 +165,4 @@
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
99
src/pages/me/changeCarType.vue
Normal file
99
src/pages/me/changeCarType.vue
Normal 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>
|
||||
@@ -40,7 +40,7 @@
|
||||
<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;">立即开通</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>
|
||||
@@ -75,17 +75,27 @@
|
||||
<template #icon>
|
||||
<img src="/static/image/mine/wdzl.png" style="width: 24px;height: 24px;">
|
||||
</template>
|
||||
</u-cell>
|
||||
<u-cell size="large" title="我的奖品" isLink @tap="handleGift">
|
||||
<template #icon>
|
||||
<u-icon size="24" name="gift"></u-icon>
|
||||
</template>
|
||||
</u-cell>
|
||||
<u-cell size="large" title="我的体检" isLink @tap="handleTJ">
|
||||
<template #icon>
|
||||
<img src="/static/image/mine/wdtj.png" style="width: 24px;height: 24px;">
|
||||
</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">
|
||||
@@ -96,6 +106,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import useUserStore from '@/jtools/store/user'
|
||||
import storage from '@/jtools/storage';
|
||||
export default {
|
||||
components: {},
|
||||
computed: {
|
||||
@@ -136,12 +147,30 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
carName: storage.get('carName') || '小车C1/C2/C3',
|
||||
isIOS: true
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.isIOS = this.$platform.device().includes('ios')
|
||||
this.carName = storage.get('carName') || '小车C1/C2/C3'
|
||||
},
|
||||
methods: {
|
||||
// 拨打电话
|
||||
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({
|
||||
@@ -181,8 +210,12 @@ export default {
|
||||
},
|
||||
handleTJ() {
|
||||
if (this.isLogin) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/me/tijian'
|
||||
// uni.navigateTo({
|
||||
// url: '/pages/me/tijian'
|
||||
// })
|
||||
uni.showToast({
|
||||
title: '敬请期待',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
this.toLogin()
|
||||
@@ -196,6 +229,11 @@ export default {
|
||||
handleLogout() {
|
||||
useUserStore().logout()
|
||||
},
|
||||
handleGift() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/me/myGift'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,28 +1,50 @@
|
||||
<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>
|
||||
<view class="flex">
|
||||
<view class="m30lr fs14 cor-333">15122305568</view>
|
||||
<u-icon name="arrow-right" color="#999" />
|
||||
</view>
|
||||
<view class="flex ai-c" style="height: 110rpx;">
|
||||
</view>
|
||||
<view class="flex jc-sb ai-c bb1" style="height: 110rpx;">
|
||||
<view class="title">地址</view>
|
||||
<view class="m30lr fs14 cor-333 fl1">安徽省合肥市包河区</view>
|
||||
<view class="flex">
|
||||
<view class="m30lr fs14 cor-333">安徽省合肥市包河区</view>
|
||||
<u-icon name="arrow-right" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="flex jc-sb ai-c bb1" style="height: 110rpx;">
|
||||
<view class="title">身份证号</view>
|
||||
<view class="m30lr fs14 cor-333">{{sfzNum}}</view>
|
||||
</view>
|
||||
<view class="flex ai-c" style="height: 110rpx;" @tap="toUploadPic">
|
||||
<view class="title">证件照</view>
|
||||
<view class="m30lr fs14 cor-333 fl1"></view>
|
||||
<u-icon name="arrow-right" color="#999" />
|
||||
</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: {
|
||||
toUploadPic(){
|
||||
uni.navigateTo({
|
||||
url: '/pages/me/uploadPic'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
67
src/pages/me/myGift.vue
Normal file
67
src/pages/me/myGift.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<view class="p10lr p20tb">
|
||||
<view 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">一等奖</view>
|
||||
</view>
|
||||
<view class="df ai-c jcsb p20tb p10lr">
|
||||
<view class="item-label">
|
||||
<view>活动名称:幸运刮刮乐开心赢大奖</view>
|
||||
<view>参与时间:2024-01-01 08:00</view>
|
||||
<view>有效期至:2024-03-01 08:00</view>
|
||||
</view>
|
||||
<view class="ml20" style="width: 120rpx;">
|
||||
<img v-if="index%2==0" src="/static/image/mine/writeoff.png" style="width: 120rpx;height: 120rpx;" />
|
||||
<view v-else class="btn" @tap="handleWriteoff(item)">核销</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.handleSearch()
|
||||
},
|
||||
methods: {
|
||||
handleSearch() {
|
||||
this.list = [1,2,3,4,5]
|
||||
},
|
||||
handleWriteoff(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/me/qrCode?item=${item}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
||||
29
src/pages/me/qrCode.vue
Normal file
29
src/pages/me/qrCode.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<view class="df jcc" style="padding-top: 100px;">
|
||||
<qrcode value="123" :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.item
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -24,11 +24,11 @@
|
||||
<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="name" borderBottom ref="item1">
|
||||
<u--input v-model="form.name" border="none"></u--input>
|
||||
<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="idNum" borderBottom ref="item2">
|
||||
<u--input v-model="form.idNum" border="none"></u--input>
|
||||
<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>
|
||||
@@ -42,6 +42,9 @@
|
||||
|
||||
<script>
|
||||
import storage from '@/jtools/storage';
|
||||
import {
|
||||
addInfo,
|
||||
} from '@/jtools/api/index';
|
||||
export default {
|
||||
data() {
|
||||
const shenfenzhen = (rule, value, callback) => {
|
||||
@@ -50,20 +53,21 @@
|
||||
}
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
idNum: ''
|
||||
idCardName: '',
|
||||
sfzmhm: ''
|
||||
},
|
||||
driverLicenseImg:'',
|
||||
fileList:[],
|
||||
fileList1: [],
|
||||
uploadList: [],
|
||||
saving: false,
|
||||
rules: {
|
||||
name: [{
|
||||
idCardName: [{
|
||||
required: true,
|
||||
message: '请输入姓名',
|
||||
trigger: ['blur', 'change']
|
||||
}],
|
||||
idNum: [{
|
||||
sfzmhm: [{
|
||||
required: true,
|
||||
message: '请输入身份证号',
|
||||
trigger: ['blur', 'change']
|
||||
@@ -78,13 +82,6 @@
|
||||
};
|
||||
},
|
||||
onReady() {
|
||||
if(storage.get('photoForm')){
|
||||
this.fileList=storage.get('photoForm').file
|
||||
this.form={
|
||||
name: storage.get('photoForm').name,
|
||||
idNum: storage.get('photoForm').idNum
|
||||
}
|
||||
}
|
||||
this.$refs.form1.setRules(this.rules);
|
||||
},
|
||||
methods: {
|
||||
@@ -95,7 +92,17 @@
|
||||
},
|
||||
// 新增图片
|
||||
async afterRead(event) {
|
||||
// this.compressImage(event.file);
|
||||
let imageInfoObj = await uni.getImageInfo({src: event.file[0].url})
|
||||
console.log(imageInfoObj);
|
||||
if(imageInfoObj.width!=720&&imageInfoObj.height!=720){
|
||||
uni.showToast({
|
||||
icon:'error',
|
||||
title:'证件照尺寸有误'
|
||||
})
|
||||
this.fileList=[]
|
||||
return false
|
||||
}
|
||||
this.driverLicenseImg = this.urlTobase64(event.file[0].url)
|
||||
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
|
||||
const lists = [].concat(event.file);
|
||||
this.fileList=lists
|
||||
@@ -129,10 +136,12 @@
|
||||
this.$refs.form1.validate().then((valid) => {
|
||||
if (valid) {
|
||||
const param={
|
||||
file:this.fileList,
|
||||
...this.form
|
||||
driverLicenseImg:this.driverLicenseImg,
|
||||
...this.form,
|
||||
schoolOrgCode:'340103000700',
|
||||
operater:'1d08daf852cf4ee28f67cb583f538cbf'
|
||||
}
|
||||
storage.set('photoForm',param)
|
||||
addInfo(param).then(resp=>{
|
||||
uni.showToast({
|
||||
title:"提交成功!",
|
||||
duration:2000,
|
||||
@@ -140,51 +149,34 @@
|
||||
setTimeout(()=>{
|
||||
uni.navigateBack()
|
||||
},1000)
|
||||
})
|
||||
} else {
|
||||
console.log('验证失败');
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
async compressImage(image) {
|
||||
const img = new Image();
|
||||
img.src = image.url;
|
||||
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)
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
img.onload = async () => {
|
||||
const canvas = document.createElement('canvas'); // 创建Canvas对象(画布)
|
||||
const context = canvas.getContext('2d');
|
||||
// 默认按比例压缩
|
||||
const cw = img.width;
|
||||
const ch = img.height;
|
||||
let w = img.width;
|
||||
let h = img.height;
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
if (cw > 400 && cw > ch) {
|
||||
w = 400;
|
||||
h = (400 * ch) / cw;
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
}
|
||||
if (ch > 400 && ch > cw) {
|
||||
h = 400;
|
||||
w = (400 * cw) / ch;
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
}
|
||||
// 生成canvas
|
||||
let base64;
|
||||
// 创建属性节点
|
||||
context.clearRect(0, 0, 0, w, h);
|
||||
context.drawImage(img, 0, 0, w, h);
|
||||
if (image.size > 2000000) {
|
||||
// 如果图片超过2m,则进行压缩
|
||||
base64 = canvas.toDataURL(image['type'], 0.5);
|
||||
}
|
||||
const result = await this.uploadFilePromise(base64 || image.url);
|
||||
this.uploadList.push(result);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
<!-- <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="fileList1&&fileList1.length" style="width: 240rpx;height: 240rpx;" :src="fileList1[0].url">
|
||||
<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" @afterRead="afterRead" @delete="deletePic" multiple :maxCount="1" width="150"
|
||||
height="150">
|
||||
<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: #3C9CFF;border-radius: 0 0 20rpx 20rpx;"
|
||||
style="width: 320rpx;height:60rpx;line-height:60rpx;background-color: #05C341;border-radius: 0 0 20rpx 20rpx;"
|
||||
class="text-center cor-fff">
|
||||
点击
|
||||
</view>
|
||||
@@ -24,17 +24,17 @@
|
||||
<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="name" borderBottom ref="item1">
|
||||
<u--input v-model="form.name" border="none"></u--input>
|
||||
<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="idNum" borderBottom ref="item2">
|
||||
<u--input v-model="form.idNum" border="none"></u--input>
|
||||
<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'}" :disabled="saving" text="提交"
|
||||
@click="submit" />
|
||||
<u-button type="primary" :style="{width: '100%',borderRadius:'40rpx',backgroundColor:'#05C341'}"
|
||||
:disabled="saving" text="提交" @click="submit" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -42,6 +42,9 @@
|
||||
|
||||
<script>
|
||||
import storage from '@/jtools/storage';
|
||||
import {
|
||||
addInfo,
|
||||
} from '@/jtools/api/index';
|
||||
export default {
|
||||
data() {
|
||||
const shenfenzhen = (rule, value, callback) => {
|
||||
@@ -50,19 +53,21 @@
|
||||
}
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
idNum: ''
|
||||
idCardName: '',
|
||||
sfzmhm: storage.get('sfzNum') || ''
|
||||
},
|
||||
driverLicenseImg: '',
|
||||
fileList: [],
|
||||
fileList1: [],
|
||||
uploadList: [],
|
||||
saving: false,
|
||||
rules: {
|
||||
name: [{
|
||||
idCardName: [{
|
||||
required: true,
|
||||
message: '请输入姓名',
|
||||
trigger: ['blur', 'change']
|
||||
}],
|
||||
idNum: [{
|
||||
sfzmhm: [{
|
||||
required: true,
|
||||
message: '请输入身份证号',
|
||||
trigger: ['blur', 'change']
|
||||
@@ -77,17 +82,17 @@
|
||||
};
|
||||
},
|
||||
onReady() {
|
||||
console.log(storage.get('photoForm'));
|
||||
if(storage.get('photoForm')){
|
||||
this.fileList1=storage.get('photoForm').file
|
||||
this.form={
|
||||
name: storage.get('photoForm').name,
|
||||
idNum: storage.get('photoForm').idNum
|
||||
}
|
||||
}
|
||||
this.$refs.form1.setRules(this.rules);
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 文件超出大小限制
|
||||
oversize() {
|
||||
uni.showToast({
|
||||
title: "图片最大不能超过500k",
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
// 删除图片
|
||||
deletePic(event) {
|
||||
this.fileList1.splice(event.index, 1);
|
||||
@@ -95,43 +100,44 @@
|
||||
},
|
||||
// 新增图片
|
||||
async afterRead(event) {
|
||||
// this.compressImage(event.file);
|
||||
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.fileList1 = lists;
|
||||
this.fileList = lists
|
||||
this.fileList1 = [];
|
||||
uni.showToast({
|
||||
title: '上传成功!'
|
||||
})
|
||||
},
|
||||
uploadFilePromise(url) {
|
||||
this.saving = true;
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: process.env.VUE_APP_BASE_API + 'mongodb/uploadFile', // 仅为示例,非真实的接口地址
|
||||
filePath: url,
|
||||
name: 'file',
|
||||
success: (res) => {
|
||||
// setTimeout(() => {
|
||||
resolve(JSON.parse(res.data).data);
|
||||
// }, 100);
|
||||
this.saving = false;
|
||||
},
|
||||
fail: () => {
|
||||
resolve(null);
|
||||
this.saving = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
// 提交
|
||||
submit() {
|
||||
this.$refs.form1.validate().then((valid) => {
|
||||
if (valid) {
|
||||
const param = {
|
||||
file:this.fileList1,
|
||||
...this.form
|
||||
driverLicenseImg: this.driverLicenseImg,
|
||||
...this.form,
|
||||
schoolOrgCode: '340103000700',
|
||||
operater: '1d08daf852cf4ee28f67cb583f538cbf'
|
||||
}
|
||||
storage.set('photoForm',param)
|
||||
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,
|
||||
@@ -139,51 +145,49 @@
|
||||
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('验证失败');
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
async compressImage(image) {
|
||||
const img = new Image();
|
||||
img.src = image.url;
|
||||
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)
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
img.onload = async () => {
|
||||
const canvas = document.createElement('canvas'); // 创建Canvas对象(画布)
|
||||
const context = canvas.getContext('2d');
|
||||
// 默认按比例压缩
|
||||
const cw = img.width;
|
||||
const ch = img.height;
|
||||
let w = img.width;
|
||||
let h = img.height;
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
if (cw > 400 && cw > ch) {
|
||||
w = 400;
|
||||
h = (400 * ch) / cw;
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
}
|
||||
if (ch > 400 && ch > cw) {
|
||||
h = 400;
|
||||
w = (400 * cw) / ch;
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
}
|
||||
// 生成canvas
|
||||
let base64;
|
||||
// 创建属性节点
|
||||
context.clearRect(0, 0, 0, w, h);
|
||||
context.drawImage(img, 0, 0, w, h);
|
||||
if (image.size > 2000000) {
|
||||
// 如果图片超过2m,则进行压缩
|
||||
base64 = canvas.toDataURL(image['type'], 0.5);
|
||||
}
|
||||
const result = await this.uploadFilePromise(base64 || image.url);
|
||||
this.uploadList.push(result);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -214,4 +218,9 @@
|
||||
::v-deep .u-button--square {
|
||||
border-radius: 40rpx !important;
|
||||
}
|
||||
|
||||
::v-deep .u-button--primary {
|
||||
background-color: #05C341 !important;
|
||||
border-color: #05C341 !important;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<view class="flex fld-c p15">
|
||||
<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 }"
|
||||
@@ -9,10 +11,11 @@
|
||||
</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 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%;">
|
||||
<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>
|
||||
@@ -110,7 +113,8 @@
|
||||
</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)">
|
||||
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>
|
||||
@@ -121,12 +125,27 @@
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
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)))
|
||||
},
|
||||
@@ -141,6 +160,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useQuestionStore, ['getOrderQuestion_sub1', 'getOrderQuestion_sub4', 'getAllQuestion']),
|
||||
chargeVip(item) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/index/videoVip?subject=" + item.subjects
|
||||
@@ -165,7 +185,8 @@ export default {
|
||||
return '开通vip助您快速拿证'
|
||||
}
|
||||
},
|
||||
vipHasOpened(item) {;
|
||||
vipHasOpened(item) {
|
||||
;
|
||||
return !!this.vipOnList.some(it => it.subjects.includes(item.subjects))
|
||||
},
|
||||
// 去精选500题 item=> 当前科目vip信息
|
||||
@@ -173,8 +194,33 @@ export default {
|
||||
// 当前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+"&needVip=true&isVip=1"
|
||||
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({
|
||||
@@ -204,7 +250,7 @@ export default {
|
||||
if (this.vipHasOpened(item)) {
|
||||
// 跳转
|
||||
uni.navigateTo({
|
||||
url:"/pages/questionBank/practiceExams?subject="+item.subjects+'&title=考前密卷&isExam1=1'
|
||||
url: "/pages/index/secretPapers?subject=" + item.subjects
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
@@ -334,12 +380,14 @@ export default {
|
||||
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;
|
||||
|
||||
@@ -49,11 +49,18 @@
|
||||
...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: '当前题库非最新版,请更新~',
|
||||
|
||||
@@ -7,18 +7,19 @@
|
||||
:class="tCurrent==item.value?'checked':'unchecked'" @tap="sectionChange(item.value)">{{item.label}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<swiper class="swiper mt20" :current="swiperIndex" :duration="duration" :autoplay="false"
|
||||
:disable-programmatic-animation="true" @change="onChange" @animationfinish="onAnimationfinish"
|
||||
@touchend="touchEnd">
|
||||
<swiper-item v-for="(quesItem,quesIndex) in swiperList" :key="quesIndex">
|
||||
<swiper class="swiper mt20" :current="swiperIndex" :duration="duration" :autoplay="false" @change="onChange"
|
||||
@animationfinish="onAnimationfinish" @touchend="touchEnd">
|
||||
<swiper-item v-for="(quesItem,quesIndex) in swiperList" :key="quesIndex.questionId">
|
||||
<scroll-view scroll-y="true" class="swiper-scroll">
|
||||
<view>
|
||||
<view class="m14lr">
|
||||
<text class="tag_box">{{getQuestType(quesItem.type)}}</text>
|
||||
<text class="fs18" style="line-height: 42rpx;vertical-align: middle;">{{quesItem.question}}</text>
|
||||
</view>
|
||||
<view class="p14" v-if="quesItem.imageUrl">
|
||||
<image style="width: 100%;" mode="widthFix" :src="quesItem.imageUrl"></image>
|
||||
<view class="p14 flex jc-c ai-c" v-if="quesItem.imageUrl">
|
||||
<image v-show="quesItem.imageUrl" style="width: auto;max-height:40vh;" mode="heightFix"
|
||||
:lazy-load="true" @load="onoff='1'" :src="quesItem.imageUrl" @click="preview(quesItem.imageUrl)">
|
||||
</image>
|
||||
</view>
|
||||
<template v-if="quesItem.type!='3'">
|
||||
<view class="flex m14lr ai-c mt20" v-for="(item,index) in quesItem.optionList" :key="item.op"
|
||||
@@ -41,7 +42,21 @@
|
||||
v-if="quesItem.clickAnswer&&!quesItem.trueAnswer.includes(quesItem.clickAnswer) || showBestAnswer">
|
||||
<view class="answer_box">
|
||||
<text class="fs18 fw600 cor-000">答案:{{getRightOp(quesItem.trueAnswer)}}</text>
|
||||
<view class="fs18 cor-000" style="text-indent:2em;"> {{quesItem.bestAnswer}}</view>
|
||||
<view v-if="showSkillInfo==='show'&&quesItem.skillInfo" class="fs18 cor-000 mt5">
|
||||
答题技巧:{{quesItem.skillInfo}}</view>
|
||||
</view>
|
||||
<view class="flex ai-c jc-c mt10">
|
||||
<view style="height: 6rpx;width: 120rpx;background-color: rgb(232, 232, 232);"></view>
|
||||
<view class="fs18 fw600 cor-000 p15lr">试题详解</view>
|
||||
<view style="height: 6rpx;width: 120rpx;background-color: rgb(232, 232, 232);"></view>
|
||||
</view>
|
||||
<view class="mt10">
|
||||
<view class="fw600 cor-000 mb10 flex ai-c">
|
||||
<view
|
||||
style="background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%);height: 36rpx;width: 8rpx;"
|
||||
class="mr5"></view>题目解析
|
||||
</view>
|
||||
<view style="text-indent:2em;">{{quesItem.bestAnswer}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -82,7 +97,21 @@
|
||||
<view class="m14lr mt30" v-if="isShowAnswer">
|
||||
<view class="answer_box">
|
||||
<text class="fs18 fw600 cor-000">答案:{{getRightOp(quesItem.trueAnswer)}}</text>
|
||||
<view class="fs18 cor-000" style="text-indent:2em;"> {{quesItem.bestAnswer}}</view>
|
||||
<view v-if="showSkillInfo==='show'&&quesItem.skillInfo" class="fs18 cor-000">
|
||||
答题技巧:{{quesItem.skillInfo}}</view>
|
||||
</view>
|
||||
<view class="flex ai-c jc-c mt10">
|
||||
<view style="height: 6rpx;width: 120rpx;background-color: rgb(232, 232, 232);"></view>
|
||||
<view class="fs18 fw600 cor-000 p15lr">试题详解</view>
|
||||
<view style="height: 6rpx;width: 120rpx;background-color: rgb(232, 232, 232);"></view>
|
||||
</view>
|
||||
<view class="mt10">
|
||||
<view class="fw600 cor-000 mb10 flex ai-c">
|
||||
<view
|
||||
style="background: linear-gradient(90deg, #11DF20 0%, #00B74F 100%);height: 36rpx;width: 8rpx;"
|
||||
class="mr5"></view>题目解析
|
||||
</view>
|
||||
<view style="text-indent:2em;">{{quesItem.bestAnswer}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -90,6 +119,7 @@
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<q-previewImage ref="previewRef" :urls="imgs" @open="open"></q-previewImage>
|
||||
<view class="wp100 flex jc-sb ai-c p14 bc-fff" v-if="isShowAll" style="position: fixed;bottom: 0;left: 0;">
|
||||
<view style="width: 220rpx;">
|
||||
<view v-if="type==='practice'" style="width: 220rpx;height: 80rpx;"></view>
|
||||
@@ -99,17 +129,17 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-center flex jc-c ai-c" style="flex-direction: column;" @tap="toCollect">
|
||||
<u-icon name="star-fill" v-if="questionList[topicIndex].isCollect" color="rgb(249,236,141)"
|
||||
size="24"></u-icon>
|
||||
<u-icon name="star" v-else size="24"></u-icon>
|
||||
<text class="cor-666">{{questionList[topicIndex].isCollect?'已收藏':'收藏'}}</text>
|
||||
<u-icon name="star-fill" v-if="collectList.includes(questionList[topicIndex].questionId)"
|
||||
color="rgb(249,236,141)" size="20"></u-icon>
|
||||
<u-icon name="star" v-else size="20"></u-icon>
|
||||
<text class="cor-666">{{collectList.includes(questionList[topicIndex].questionId)?'已收藏':'收藏'}}</text>
|
||||
</view>
|
||||
<view class="text-center">
|
||||
<view style="color: #00B74F;">{{rightList.length}}</view>
|
||||
<view style="color: #00B74F;">{{navTitle !== '顺序答题'?rightList.length:storageRightList.length}}</view>
|
||||
<text class="cor-666">答对</text>
|
||||
</view>
|
||||
<view class="text-center">
|
||||
<view style="color: #FF6E02;">{{wrongList.length}}</view>
|
||||
<view style="color: #FF6E02;">{{navTitle !== '顺序答题'?wrongList.length:storageWrongList.length}}</view>
|
||||
<text class="cor-666">答错</text>
|
||||
</view>
|
||||
<view class="text-center" @tap="popupShow=!popupShow">
|
||||
@@ -191,17 +221,17 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-center flex jc-c ai-c" style="flex-direction: column;" @tap="toCollect">
|
||||
<u-icon name="star-fill" v-if="questionList[topicIndex].isCollect" color="rgb(249,236,141)"
|
||||
size="24"></u-icon>
|
||||
<u-icon name="star" v-else size="24"></u-icon>
|
||||
<text class="cor-666">{{questionList[topicIndex].isCollect?'已收藏':'收藏'}}</text>
|
||||
<u-icon name="star-fill" v-if="collectList.includes(questionList[topicIndex].questionId)"
|
||||
color="rgb(249,236,141)" size="20"></u-icon>
|
||||
<u-icon name="star" v-else size="20"></u-icon>
|
||||
<text class="cor-666">{{collectList.includes(questionList[topicIndex].questionId)?'已收藏':'收藏'}}</text>
|
||||
</view>
|
||||
<view class="text-center">
|
||||
<view style="color: #00B74F;">{{rightList.length}}</view>
|
||||
<view style="color: #00B74F;">{{navTitle !== '顺序答题'?rightList.length:storageRightList.length}}</view>
|
||||
<text class="cor-666">答对</text>
|
||||
</view>
|
||||
<view class="text-center">
|
||||
<view style="color: #FF6E02;">{{wrongList.length}}</view>
|
||||
<view style="color: #FF6E02;">{{navTitle !== '顺序答题'?wrongList.length:storageWrongList.length}}</view>
|
||||
<text class="cor-666">答错</text>
|
||||
</view>
|
||||
<view class="text-center" @tap="popupShow=!popupShow">
|
||||
@@ -212,15 +242,17 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex ai-c jc-fs p14" style="flex-wrap: wrap;max-height: 400px;overflow-y: scroll;">
|
||||
<view v-for="(item,index) of questionList" :key="index" style="width:20%;" class="flex ai-c jc-c"
|
||||
@tap="chooseQueston(index)">
|
||||
<view v-for="(item,index) of questionList" :key="item.questionId" style="width:20%;position: relative;"
|
||||
class="flex ai-c jc-c" @tap="chooseQueston(index)">
|
||||
<view class="tCircle mb10" :class="{
|
||||
'active':index == topicIndex,
|
||||
'success':rightList.includes(item.questionId),
|
||||
'error':wrongList.includes(item.questionId)
|
||||
'success':type=='exam'?rightList.includes(item.questionId):storageRightList.includes(item.questionId),
|
||||
'error':type=='exam'?wrongList.includes(item.questionId):storageWrongList.includes(item.questionId)
|
||||
}">
|
||||
{{index+1}}
|
||||
</view>
|
||||
<u-icon name="star-fill" v-if="collectList.includes(item.questionId)"
|
||||
style="position: absolute;right: 5px;top:-3px" color="rgb(249,236,141)" size="24"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -272,6 +304,7 @@
|
||||
import storage from '@/jtools/storage';
|
||||
import useQuestionStore from '@/jtools/store/question' //引入store
|
||||
import {
|
||||
querySysConfig,
|
||||
submitTest
|
||||
} from '@/jtools/api/question';
|
||||
export default {
|
||||
@@ -290,14 +323,15 @@
|
||||
isShowAll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
subject: {
|
||||
type: [String, Number],
|
||||
default: 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgs: [],
|
||||
subject: '1',
|
||||
showSkillInfo: 'hidden',
|
||||
currentType: storage.get('carType') || '1001',
|
||||
onoff: '0',
|
||||
navTitle: '',
|
||||
originArray: '',
|
||||
showBestAnswer: false,
|
||||
@@ -310,6 +344,8 @@
|
||||
tCurrent: 0,
|
||||
index: 0,
|
||||
qIndex: 0,
|
||||
storageRightList: storage.get(`rightList_subject${this.subject}`) || [],
|
||||
storageWrongList: storage.get(`wrongList_subject${this.subject}`) || [],
|
||||
rightList: [],
|
||||
wrongList: [],
|
||||
collectList: storage.get(`collectList_subject${this.subject}`) || [],
|
||||
@@ -322,7 +358,14 @@
|
||||
time: 0,
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
const carType = storage.get('carType') || '1001'
|
||||
querySysConfig(carType, 'NeedSkillInfo').then(resp => {
|
||||
if (resp.code === '0000') {
|
||||
this.showSkillInfo = resp.data.configValue
|
||||
}
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
...mapState(useQuestionStore, ["currentIndex_subject1", "currentIndex_subject4"]), //映射函数,取出tagslist
|
||||
isShowAnswer() {
|
||||
@@ -345,23 +388,33 @@
|
||||
|
||||
},
|
||||
timeCount() {
|
||||
const time = this.subject == '1' ? 60 * 60 * 1000 : 45 * 60 * 1000
|
||||
const time = 45 * 60 * 1000
|
||||
return time
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useQuestionStore, ['getCurrentIndex']),
|
||||
open() {
|
||||
|
||||
},
|
||||
preview(url) {
|
||||
this.imgs = [url] //设置图片数组
|
||||
// #ifdef MP-WEIXIN
|
||||
this.$nextTick(() => {
|
||||
this.imgs = [url]
|
||||
setTimeout(()=>{
|
||||
this.$refs.previewRef.open(url);
|
||||
},500)
|
||||
})
|
||||
// #endif
|
||||
|
||||
},
|
||||
getOriginArr(val) {
|
||||
const arr = JSON.parse(val)
|
||||
let arr1 = []
|
||||
arr.forEach(item => {
|
||||
let isCollect = false
|
||||
if (this.collectList.includes(item.questionId)) {
|
||||
isCollect = true
|
||||
}
|
||||
arr1.push({
|
||||
isChoose: false,
|
||||
isCollect: isCollect,
|
||||
...item
|
||||
})
|
||||
})
|
||||
@@ -381,8 +434,8 @@
|
||||
if (this.tCurrent != 1) {
|
||||
this.originArray = JSON.stringify(this.questionList)
|
||||
}
|
||||
const falseList = storage.get(`wrongList_subject${this.subject}`) || []
|
||||
const trueList = storage.get(`rightList_subject${this.subject}`) || []
|
||||
// const falseList = storage.get(`wrongList_subject${this.subject}`) || []
|
||||
// const trueList = storage.get(`rightList_subject${this.subject}`) || []
|
||||
if (this.tCurrent !== 1) {
|
||||
const arr1 = this.questionList[this.topicIndex].clickAnswer.split('')
|
||||
const arr2 = this.questionList[this.topicIndex].trueAnswer.split('')
|
||||
@@ -392,18 +445,18 @@
|
||||
if (!this.rightList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.rightList.push(this.questionList[this.topicIndex].questionId)
|
||||
}
|
||||
if (!trueList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
trueList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`rightList_subject${this.subject}`, trueList)
|
||||
if (!this.storageRightList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.storageRightList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`rightList_subject${this.subject}`, this.storageRightList)
|
||||
}
|
||||
if (this.wrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const wIndex = this.wrongList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
this.wrongList.splice(wIndex, 1)
|
||||
}
|
||||
if (falseList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const wIndex = falseList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
falseList.splice(wIndex, 1)
|
||||
storage.set(`wrongList_subject${this.subject}`, falseList)
|
||||
if (this.storageWrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const wIndex = this.storageWrongList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
this.storageWrongList.splice(wIndex, 1)
|
||||
storage.set(`wrongList_subject${this.subject}`, this.storageWrongList)
|
||||
}
|
||||
//答对题目 如果不是最后一题,跳下一题
|
||||
if (this.topicIndex < this.questionList.length - 1) {
|
||||
@@ -429,14 +482,14 @@
|
||||
if (!this.wrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.wrongList.push(this.questionList[this.topicIndex].questionId)
|
||||
}
|
||||
if (!falseList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
falseList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`wrongList_subject${this.subject}`, falseList)
|
||||
if (!this.storageWrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.storageWrongList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`wrongList_subject${this.subject}`, this.storageWrongList)
|
||||
}
|
||||
if (trueList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const rIndex = trueList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
trueList.splice(rIndex, 1)
|
||||
storage.set(`rightList_subject${this.subject}`, trueList)
|
||||
if (this.storageRightList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const rIndex = this.storageRightList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
this.storageRightList.splice(rIndex, 1)
|
||||
storage.set(`rightList_subject${this.subject}`, this.storageRightList)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -490,6 +543,7 @@
|
||||
this.$refs.countDown_1.pause();
|
||||
this.$refs.countDown_2.pause();
|
||||
}
|
||||
this.popupShow = false
|
||||
this.$refs.countDown_3.pause();
|
||||
this.$emit('update:isSubmit', true)
|
||||
},
|
||||
@@ -508,10 +562,15 @@
|
||||
toSubmit() {
|
||||
const restTime = this.time.hours * 60 * 60 + this.time.minutes * 60 + this.time.seconds
|
||||
const score = (this.rightList.length / this.questionList.length * 100).toFixed(0)
|
||||
if (this.rightList.length + this.wrongList.length == 0) {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
} else {
|
||||
submitTest({
|
||||
"carTypeId": storage.get('carType') || '1001',
|
||||
"score": score,
|
||||
"testTime": 60 * 60 - restTime,
|
||||
"testTime": 45 * 60 - restTime,
|
||||
subject: this.subject
|
||||
}).then(resp => {
|
||||
const doNotNum = this.questionList.length - this.rightList.length - this.wrongList.length
|
||||
@@ -523,6 +582,7 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
//查看考试结果
|
||||
toResult() {
|
||||
@@ -534,12 +594,9 @@
|
||||
})
|
||||
},
|
||||
toCollect() {
|
||||
if (this.questionList[this.topicIndex].isCollect) {
|
||||
if (this.collectList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const idx = this.collectList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
this.collectList.splice(idx, 1)
|
||||
}
|
||||
this.questionList[this.topicIndex].isCollect = false
|
||||
uni.showToast({
|
||||
title: "取消收藏",
|
||||
icon: 'none'
|
||||
@@ -593,6 +650,7 @@
|
||||
|
||||
// 轮播图切换
|
||||
onChange(e) {
|
||||
// this.onoff='0'
|
||||
// 非触摸事件不做轮播图状态更新
|
||||
if (e.detail.source != "touch") return;
|
||||
|
||||
@@ -644,8 +702,8 @@
|
||||
},
|
||||
//答题
|
||||
answerQues(op, index) {
|
||||
const falseList = storage.get(`wrongList_subject${this.subject}`) || []
|
||||
const trueList = storage.get(`rightList_subject${this.subject}`) || []
|
||||
// const falseList = storage.get(`wrongList_subject${this.subject}`) || []
|
||||
// const trueList = storage.get(`rightList_subject${this.subject}`) || []
|
||||
if (!this.questionList[this.topicIndex].clickAnswer) {
|
||||
this.questionList[this.topicIndex].optionList[index].chooseOption =
|
||||
`${this.questionList[this.topicIndex].optionList[index].chooseOption?this.questionList[this.topicIndex].optionList[index].chooseOption:''}${op}`
|
||||
@@ -678,18 +736,18 @@
|
||||
if (!this.rightList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.rightList.push(this.questionList[this.topicIndex].questionId)
|
||||
}
|
||||
if (!trueList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
trueList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`rightList_subject${this.subject}`, trueList)
|
||||
if (!this.storageRightList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.storageRightList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`rightList_subject${this.subject}`, this.storageRightList)
|
||||
}
|
||||
if (this.wrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const wIndex = this.wrongList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
this.wrongList.splice(wIndex, 1)
|
||||
}
|
||||
if (falseList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const wIndex = falseList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
falseList.splice(wIndex, 1)
|
||||
storage.set(`wrongList_subject${this.subject}`, falseList)
|
||||
if (this.storageWrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const wIndex = this.storageWrongList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
this.storageWrongList.splice(wIndex, 1)
|
||||
storage.set(`wrongList_subject${this.subject}`, this.storageWrongList)
|
||||
}
|
||||
//答对题目 如果不是最后一题,跳下一题
|
||||
if (this.topicIndex < this.questionList.length - 1) {
|
||||
@@ -715,14 +773,14 @@
|
||||
if (!this.wrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.wrongList.push(this.questionList[this.topicIndex].questionId)
|
||||
}
|
||||
if (!falseList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
falseList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`wrongList_subject${this.subject}`, falseList)
|
||||
if (!this.storageWrongList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
this.storageWrongList.push(this.questionList[this.topicIndex].questionId)
|
||||
storage.set(`wrongList_subject${this.subject}`, this.storageWrongList)
|
||||
}
|
||||
if (trueList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const rIndex = trueList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
trueList.splice(rIndex, 1)
|
||||
storage.set(`rightList_subject${this.subject}`, trueList)
|
||||
if (this.storageRightList.includes(this.questionList[this.topicIndex].questionId)) {
|
||||
const rIndex = this.storageRightList.indexOf(this.questionList[this.topicIndex].questionId)
|
||||
this.storageRightList.splice(rIndex, 1)
|
||||
storage.set(`rightList_subject${this.subject}`, this.storageRightList)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -733,17 +791,30 @@
|
||||
// this.renderSwiper(0)
|
||||
this.$emit('changeTab', index)
|
||||
},
|
||||
getQuestionList(val, title) {
|
||||
getQuestionList(val, title, subject) {
|
||||
if (title) {
|
||||
this.navTitle = title
|
||||
}
|
||||
if (subject) {
|
||||
this.subject = subject
|
||||
console.log(this.subject);
|
||||
this.storageRightList = storage.get(`rightList_subject${subject}`) || []
|
||||
this.storageWrongList = storage.get(`wrongList_subject${subject}`) || []
|
||||
this.collectList = storage.get(`collectList_subject${subject}`) || []
|
||||
}
|
||||
if (val && val.length) {
|
||||
this.questionList = JSON.parse(val)
|
||||
} else {
|
||||
this.questionList = JSON.parse(this.originArray)
|
||||
}
|
||||
console.log(this.questionList);
|
||||
if (this.navTitle === '顺序答题') {
|
||||
if (subject) {
|
||||
this.pickerTopic(this[`currentIndex_subject${subject}`])
|
||||
} else {
|
||||
this.pickerTopic(this[`currentIndex_subject${this.subject}`])
|
||||
}
|
||||
|
||||
} else {
|
||||
this.pickerTopic(this.topicIndex)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<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>
|
||||
<text style="color: #FF6E02;font-size: 14px;">共{{chapterNum}}章</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -67,6 +67,7 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
chapterNum:0,
|
||||
errorIcon,
|
||||
newRulesIcon,
|
||||
neverWriteIcon,
|
||||
@@ -111,6 +112,7 @@
|
||||
}
|
||||
this.getExamPoint()
|
||||
this.getQuestionNum()
|
||||
this.getChapterList()
|
||||
},
|
||||
computed: {
|
||||
...mapState(useQuestionStore, ["loading_subject4", "loading_subject1", "version"]), //映射函数,取出tagslist
|
||||
@@ -120,6 +122,15 @@
|
||||
},
|
||||
methods: {
|
||||
...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
|
||||
}
|
||||
})
|
||||
},
|
||||
getQuestionNum() {
|
||||
querySpecialNum({
|
||||
carTypeId: storage.get('carType') || '1001',
|
||||
@@ -218,11 +229,18 @@
|
||||
...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: '当前题库非最新版,请更新~',
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<!-- <u-navbar title="模拟考试" @rightClick="rightClick" :autoBack="true">
|
||||
</u-navbar> -->
|
||||
<j-navbar :isDefineBack="true" @toBack="toBack">{{title}}</j-navbar>
|
||||
<Question ref="question" :tabsList="tabsList" v-model:isSubmit="isSubmit" :type="type" :isShowAll="isShowAll"
|
||||
:subject="subject" @changeTab="changeTab" />
|
||||
<Question ref="question" :tabsList="tabsList" v-model:isSubmit="isSubmit" :type="type" :isShowAll="isShowAll" @changeTab="changeTab" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -57,23 +56,22 @@
|
||||
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)
|
||||
arr = this[`orderQuestion_subject${this.subject}`].filter(qItem=>idList.includes(qItem.questionId))
|
||||
}
|
||||
arr.forEach(item => {
|
||||
let isCollect = false
|
||||
if (this.collectList.includes(item.questionId)) {
|
||||
isCollect = true
|
||||
}
|
||||
this.questionArr.push({
|
||||
isChoose: false,
|
||||
isCollect: isCollect,
|
||||
...item
|
||||
})
|
||||
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.$refs.question.getQuestionList(JSON.stringify(this.questionArr), this.title,this.subject)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -85,48 +83,19 @@
|
||||
toBack() {
|
||||
this.$refs.question.submitPaper()
|
||||
},
|
||||
changeTab(val) {
|
||||
async changeTab(val) {
|
||||
if (val == 1) {
|
||||
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') {
|
||||
if (this.token) {
|
||||
await this.searchUserVip()
|
||||
const result = this.vipOnList.some(item => item.subjects.includes(this.subject))
|
||||
if (result) {
|
||||
const listJson = JSON.stringify(resp.data)
|
||||
uni.navigateTo({
|
||||
url: "/pages/questionBank/practiceExams?title=考前密卷" + "&subject=" + this.subject + "&questionIdList=" + listJson
|
||||
url: "/pages/index/secretPapers?subject=" + this.subject
|
||||
})
|
||||
} else {
|
||||
if (resp.data && resp.data.length > 3) {
|
||||
const arr = resp.data.slice(0, 3)
|
||||
} else {
|
||||
const arr = resp.data
|
||||
}
|
||||
const listJson = JSON.stringify(arr)
|
||||
uni.navigateTo({
|
||||
url: "/pages/questionBank/practiceExams?title=" + title + "&subject=" + this.subject + "&questionIdList=" + listJson+"&needVip="+result
|
||||
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()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<GradesChart :titleName="rightPencentDesc" :actualValue="Number(rightPencent)" />
|
||||
<view class="top_box flex jc-c" style="flex-direction: column;">
|
||||
<view class="wp100 text-center" style="margin-top: -80px;">
|
||||
<text v-if="Number(rightPencent)>=90">太棒了!正确率很高了!</text>
|
||||
<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">
|
||||
|
||||
@@ -60,53 +60,24 @@
|
||||
if (op.needVip) {
|
||||
this.isShowAll = !Boolean(op.needVip == 'true')
|
||||
}
|
||||
if (this.navTitle === '顺序答题') {
|
||||
if (this.subject == '1') {
|
||||
arr = [...this.orderQuestion_subject1]
|
||||
} else if (this.subject == '4') {
|
||||
arr = [...this.orderQuestion_subject4]
|
||||
}
|
||||
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)
|
||||
arr = this[`orderQuestion_subject${this.subject}`].filter(qItem=>idList.includes(qItem.questionId))
|
||||
}else{
|
||||
if(op.isVip){
|
||||
param.isVip=op.isVip
|
||||
}
|
||||
const resp=await queryQuestionId({
|
||||
subject:this.subject,
|
||||
carTypeId:storage.get('carType') || '1001',
|
||||
versionId:this.version,
|
||||
...params
|
||||
if(idList&&idList.length>0){
|
||||
idList.forEach(item=>{
|
||||
this.questionArr.push(questionObj[item])
|
||||
})
|
||||
let list=[]
|
||||
if(resp.code==='0000'){
|
||||
await this.searchUserVip()
|
||||
const res = this.vipOnList.some(item => item.subjects.includes(this.subject))
|
||||
if (!res) {
|
||||
list=resp.data.slice(0,3)
|
||||
}else{
|
||||
list=resp.data
|
||||
}
|
||||
}
|
||||
if(op.needVip){
|
||||
this.isShowAll = op.needVip
|
||||
}
|
||||
arr=this[`orderQuestion_subject${this.subject}`].filter(qItem=>list.includes(qItem.questionId))
|
||||
}
|
||||
arr.forEach(item => {
|
||||
let isCollect = false
|
||||
if (this.collectList.includes(item.questionId)) {
|
||||
isCollect = true
|
||||
}
|
||||
this.questionArr.push({
|
||||
isChoose: false,
|
||||
isCollect: isCollect,
|
||||
...item
|
||||
})
|
||||
})
|
||||
this.loading = false
|
||||
this.$refs.question.getQuestionList(JSON.stringify(this.questionArr),this.navTitle)
|
||||
this.$refs.question.getQuestionList(JSON.stringify(this.questionArr), this.navTitle , this.subject)
|
||||
this.$refs.question.getOriginArr(JSON.stringify(this.questionArr))
|
||||
}
|
||||
},
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
label: "庐江考场",
|
||||
value: 6
|
||||
}],
|
||||
driveType:'',
|
||||
videoType: '',
|
||||
popupShow: false,
|
||||
videoList: [{
|
||||
@@ -128,6 +129,10 @@
|
||||
}
|
||||
},
|
||||
onLoad(op) {
|
||||
if(op.driveType){
|
||||
this.driveType=op.driveType
|
||||
this.param.driveType=op.driveType
|
||||
}
|
||||
if (op.type) {
|
||||
this.videoType = op.type
|
||||
}
|
||||
@@ -139,6 +144,7 @@
|
||||
}
|
||||
if (op.type) {
|
||||
this.param.type = op.type
|
||||
this.getVideoList()
|
||||
}
|
||||
if (op.type == '1') {
|
||||
if (this.param.subject == '2') {
|
||||
@@ -149,10 +155,7 @@
|
||||
} else {
|
||||
this.title = '基础操作讲解'
|
||||
}
|
||||
if (op.videoList) {
|
||||
this.videoList = JSON.parse(op.videoList)
|
||||
this.currentIndex = this.videoList.findIndex(item => item.projectId == this.projectId)
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
getScrollLeft() {
|
||||
@@ -161,6 +164,46 @@
|
||||
}
|
||||
},
|
||||
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}`
|
||||
},
|
||||
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
|
||||
},
|
||||
|
||||
@@ -68,7 +68,9 @@
|
||||
<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>
|
||||
@@ -139,8 +141,9 @@
|
||||
},
|
||||
toCategoryQuestion(item){
|
||||
const jsonString = JSON.stringify(item.errorQuestionIdList)
|
||||
console.log(item);
|
||||
uni.navigateTo({
|
||||
url: "/pages/questionBank/questionBank?navTitle=" + item.categoryName + "&questionIdList=" + jsonString
|
||||
url: "/pages/questionBank/questionBank?navTitle=" + item.categoryName + "&questionIdList=" + jsonString+"&subject="+this.subject
|
||||
})
|
||||
},
|
||||
toPractice() {
|
||||
@@ -264,4 +267,18 @@
|
||||
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>
|
||||
BIN
src/static/image/index/tip.png
Normal file
BIN
src/static/image/index/tip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
src/static/image/index/vip_ksxj.png
Normal file
BIN
src/static/image/index/vip_ksxj.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
src/static/image/index/vip_trueRoom.png
Normal file
BIN
src/static/image/index/vip_trueRoom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
src/static/image/mine/callme.png
Normal file
BIN
src/static/image/mine/callme.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
BIN
src/static/image/mine/giftitem.png
Normal file
BIN
src/static/image/mine/giftitem.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
BIN
src/static/image/mine/writeoff.png
Normal file
BIN
src/static/image/mine/writeoff.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
11
src/uni_modules/g-preview-img/changelog.md
Normal file
11
src/uni_modules/g-preview-img/changelog.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## 1.0.4(2022-12-07)
|
||||
修改:判断在APP端不监听document的滚动
|
||||
## 1.0.3(2022-12-05)
|
||||
新增:支持视频预览,视频图片混用
|
||||
新增:支持预览单张,handlePreviewImg方法直接传入图片或视频地址即可单张预览
|
||||
## 1.0.2(2022-12-05)
|
||||
|
||||
## 1.0.1(2022-12-05)
|
||||
文档错误修改
|
||||
## 1.0.0(2022-11-29)
|
||||
初始化插件
|
||||
@@ -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>
|
||||
84
src/uni_modules/g-preview-img/package.json
Normal file
84
src/uni_modules/g-preview-img/package.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"id": "g-preview-img",
|
||||
"displayName": "g-preview-img一款兼容vue2,vue3的图片预览插件,视频预览,支持单张多张,左右滑动,放大缩小",
|
||||
"version": "1.0.4",
|
||||
"description": "g-preview-img一款兼容vue2,vue3的图片预览插件,视频预览,支持单张多张,左右滑动,放大缩小",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
src/uni_modules/g-preview-img/readme.md
Normal file
64
src/uni_modules/g-preview-img/readme.md
Normal file
@@ -0,0 +1,64 @@
|
||||

|
||||
### 一款兼容vue2,vue3的图片预览插件,视频预览,支持图片视频混用,支持单张多张,左右滑动,放大缩小
|
||||
|
||||
### 基础使用方法
|
||||
|
||||
```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会及时修复!!**
|
||||
25
src/uni_modules/lime-qrcode/changelog.md
Normal file
25
src/uni_modules/lime-qrcode/changelog.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## 0.1.2(2023-12-14)
|
||||
- fix: uvue 引入 API 自定义包出错
|
||||
## 0.1.1(2023-12-11)
|
||||
- chore: uvue的二维码API独立,需要单独下载
|
||||
## 0.1.0(2023-12-07)
|
||||
- fix: 修复因utssdk目录导致无法运行
|
||||
## 0.0.9(2023-12-06)
|
||||
- feat: 支持uvue
|
||||
## 0.0.8(2023-12-06)
|
||||
- feat: 支持uvue
|
||||
## 0.0.7(2023-12-06)
|
||||
- feat: 支持uvue
|
||||
## 0.0.6(2023-12-06)
|
||||
- feat: 支持uvue
|
||||
## 0.0.5(2023-07-30)
|
||||
- fix: 修复再次生成前没有清空,导致图形叠加
|
||||
## 0.0.4(2023-07-27)
|
||||
- fix: 修复相同尺寸无法再次生成
|
||||
## 0.0.3(2023-06-09)
|
||||
- feat: 支持通过`@vue/composition-api`在`vue2`上使用
|
||||
- chore: 更新文档
|
||||
## 0.0.2(2023-06-08)
|
||||
- chore: 更新文档
|
||||
## 0.0.1(2023-06-08)
|
||||
- 首次
|
||||
179
src/uni_modules/lime-qrcode/components/l-qrcode/l-qrcode.uvue
Normal file
179
src/uni_modules/lime-qrcode/components/l-qrcode/l-qrcode.uvue
Normal 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>
|
||||
223
src/uni_modules/lime-qrcode/components/l-qrcode/l-qrcode.vue
Normal file
223
src/uni_modules/lime-qrcode/components/l-qrcode/l-qrcode.vue
Normal 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>
|
||||
36
src/uni_modules/lime-qrcode/components/l-qrcode/props.ts
Normal file
36
src/uni_modules/lime-qrcode/components/l-qrcode/props.ts
Normal 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
25
src/uni_modules/lime-qrcode/components/l-qrcode/type.ts
Normal file
25
src/uni_modules/lime-qrcode/components/l-qrcode/type.ts
Normal 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
|
||||
}
|
||||
78
src/uni_modules/lime-qrcode/components/l-qrcode/useCanvas.ts
Normal file
78
src/uni_modules/lime-qrcode/components/l-qrcode/useCanvas.ts
Normal 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
|
||||
}
|
||||
35
src/uni_modules/lime-qrcode/components/l-qrcode/utils.uts
Normal file
35
src/uni_modules/lime-qrcode/components/l-qrcode/utils.uts
Normal 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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
77
src/uni_modules/lime-qrcode/hybrid/html/index.html
Normal file
77
src/uni_modules/lime-qrcode/hybrid/html/index.html
Normal 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>
|
||||
6
src/uni_modules/lime-qrcode/hybrid/html/qrcode.min.js
vendored
Normal file
6
src/uni_modules/lime-qrcode/hybrid/html/qrcode.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
89
src/uni_modules/lime-qrcode/package.json
Normal file
89
src/uni_modules/lime-qrcode/package.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"id": "lime-qrcode",
|
||||
"displayName": "qrcode 二维码生成",
|
||||
"version": "0.1.2",
|
||||
"description": "全端二维码生成插件,draw api绘制。在H5,微信小程序,uvue,nvue上测试过,非uvue为vue3实现vue2需配置@vue/composition-api",
|
||||
"keywords": [
|
||||
"qrcode",
|
||||
"qr",
|
||||
"uvue",
|
||||
"生成图片",
|
||||
"二维码"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": "305716444"
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"lime-shared"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y",
|
||||
"app-android": {
|
||||
"minVersion": "19"
|
||||
}
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
153
src/uni_modules/lime-qrcode/readme.md
Normal file
153
src/uni_modules/lime-qrcode/readme.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# lime-qrcode 二维码
|
||||
- uniapp vue3 生成二维码插件
|
||||
- 仅在H5、微信小程序、APP-NVUE测试过,如果你在其它端遇到问题或其它端也能跑,请告之
|
||||
- uvue 需要导入[lime-qrcodegen](https://ext.dcloud.net.cn/plugin?id=15838)
|
||||
|
||||
## 使用
|
||||
- 导入插件后直接使用
|
||||
- uvue 需要导入**[lime-qrcodegen](https://ext.dcloud.net.cn/plugin?id=15838)**
|
||||
|
||||
#### 基础使用
|
||||
|
||||
```html
|
||||
<l-qrcode value="http://lime.qcoon.cn" />
|
||||
```
|
||||
|
||||
|
||||
#### ICON
|
||||
- 带 Icon 的二维码
|
||||
|
||||
```html
|
||||
<l-qrcode value="https://limeui.qcoon.cn" size="300rpx" icon="/static/logo.png" iconSize="70rpx"></l-qrcode>
|
||||
```
|
||||
|
||||
#### 颜色
|
||||
- 通过设置 `color` 自定义二维码颜色,通过设置 `bgColor` 自定义背景颜色。
|
||||
|
||||
```html
|
||||
<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>
|
||||
```
|
||||
|
||||
#### 纠错比例
|
||||
- 通过设置 `errorLevel` 调整不同的容错等级。
|
||||
|
||||
```html
|
||||
<l-qrcode value="img10.360buyimg.com/img/jfs/t1/182127/16/37474/11761/64659c31F0cd84976/21f25b952f03a49a.jpg" size="300rpx" errorLevel="H"></l-qrcode>
|
||||
```
|
||||
|
||||
#### 生成图片
|
||||
- 1、通过调用插件的`canvasToTempFilePath`方法生成图片。
|
||||
|
||||
```html
|
||||
<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>
|
||||
<button @click="onClick">生成图片</button>
|
||||
```
|
||||
```js
|
||||
// vue3
|
||||
const qrcodeRef = ref(null)
|
||||
const onClick = () => {
|
||||
if(!qrcodeRef.value) return
|
||||
qrcodeRef.value.canvasToTempFilePath({
|
||||
success(res) {
|
||||
image.value = res.tempFilePath
|
||||
console.log('success:::', res)
|
||||
},
|
||||
fail(err) {
|
||||
console.log('err:::', err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// vue2
|
||||
const el = this.$refs['qrcodeRef']
|
||||
el.canvasToTempFilePath({
|
||||
success:(res)=>{
|
||||
this.image = res.tempFilePath
|
||||
},
|
||||
fail(err) {
|
||||
console.log('err:::', err)
|
||||
}
|
||||
})
|
||||
|
||||
// uvue
|
||||
const el:LQrcodeComponentPublicInstance = this.$refs['qrcodeRef'] as LQrcodeComponentPublicInstance
|
||||
el.canvasToTempFilePath({
|
||||
success:(res: TakeSnapshotSuccess)=>{
|
||||
this.image = res.tempFilePath
|
||||
},
|
||||
fail(err: TakeSnapshotFail) {
|
||||
console.log('err:::', err)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
- 2、通过设置`useCanvasToTempFilePath`在`success`事件里接收图片地址
|
||||
|
||||
```html
|
||||
<image v-if="image" :src="image" style="width: 300rpx;" mode="widthFix"></image>
|
||||
<l-qrcode useCanvasToTempFilePath @success="success" value="https://limeui.qcoon.cn"></l-qrcode>
|
||||
```
|
||||
```js
|
||||
const image = ref(null)
|
||||
const success = (img) => {
|
||||
image.value = img
|
||||
}
|
||||
```
|
||||
|
||||
### 关于vue2的使用方式
|
||||
- 插件使用了`composition-api`, 如果你希望在vue2中使用请按官方的教程[vue-composition-api](https://uniapp.dcloud.net.cn/tutorial/vue-composition-api.html)配置
|
||||
- 关键代码是: 在main.js中 在vue2部分加上这一段即可,官方是把它单独成了一个文件.
|
||||
|
||||
```js
|
||||
// main.js vue2
|
||||
import Vue from 'vue'
|
||||
import VueCompositionAPI from '@vue/composition-api'
|
||||
Vue.use(VueCompositionAPI)
|
||||
```
|
||||
另外插件也用到了TS,vue2可能会遇过官方的TS版本过低的问题,找到HX目录下的`compile-typescript`目录
|
||||
```cmd
|
||||
// \HBuilderX\plugins\compile-typescript
|
||||
yarn add typescript -D
|
||||
- or -
|
||||
npm install typescript -D
|
||||
```
|
||||
|
||||
### 查看示例
|
||||
- 导入后直接使用这个标签查看演示效果
|
||||
|
||||
```html
|
||||
// 代码位于 uni_modules/lime-qrcode/compoents/lime-qrcode
|
||||
<lime-qrcode />
|
||||
```
|
||||
|
||||
### 插件标签
|
||||
- 默认 l-qrcode 为 component
|
||||
- 默认 lime-qrcode 为 demo
|
||||
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --------------------------| ------------------------------------------------------------ | ---------------- | ------------ |
|
||||
| value | 扫描后的文本 | <em>string</em> | `-` |
|
||||
| icon | 二维码中图片的地址 | <em>string</em> | `-` |
|
||||
| size | 二维码大小 | <em>number,string</em> | `160` |
|
||||
| iconSize | 二维码中图片的大小 | <em>number,string</em> | `40` |
|
||||
| color | 二维码颜色 | <em>string</em> | `-` |
|
||||
| bgColor | 二维码背景颜色 | <em>string</em> | `-` |
|
||||
| errorLevel | 二维码纠错等级 | `'L' | 'M' | 'Q' | 'H' ` | `M` |
|
||||
| marginSize | 边距码大小,默认为0码点 | <em>number</em> | `0` |
|
||||
|
||||
### 常见问题
|
||||
- icon 是网络地址时,H5和Nvue需要解决跨域问题,小程序需要配置download
|
||||
|
||||
## 打赏
|
||||
|
||||
如果你觉得本插件,解决了你的问题,赠人玫瑰,手留余香。
|
||||

|
||||

|
||||
25
src/uni_modules/lime-shared/addUnit/index.ts
Normal file
25
src/uni_modules/lime-shared/addUnit/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// @ts-nocheck
|
||||
import {isNumeric} from '../isNumeric'
|
||||
import {isDef} from '../isDef'
|
||||
/**
|
||||
* 给一个值添加单位(像素 px)
|
||||
* @param value 要添加单位的值,可以是字符串或数字
|
||||
* @returns 添加了单位的值,如果值为 undefined 则返回 undefined
|
||||
*/
|
||||
export function addUnit(value?: string | number): string | undefined {
|
||||
if (!isDef(value)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
value = String(value); // 将值转换为字符串
|
||||
|
||||
// 如果值是数字,则在后面添加单位 "px",否则保持原始值
|
||||
return isNumeric(value) ? `${value}px` : value;
|
||||
}
|
||||
|
||||
|
||||
// console.log(addUnit(100)); // 输出: "100px"
|
||||
// console.log(addUnit("200")); // 输出: "200px"
|
||||
// console.log(addUnit("300px")); // 输出: "300px"(已经包含单位)
|
||||
// console.log(addUnit()); // 输出: undefined(值为 undefined)
|
||||
// console.log(addUnit(null)); // 输出: undefined(值为 null)
|
||||
63
src/uni_modules/lime-shared/arrayBufferToFile/index.ts
Normal file
63
src/uni_modules/lime-shared/arrayBufferToFile/index.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
// @ts-nocheck
|
||||
import {platform} from '../platform'
|
||||
/**
|
||||
* buffer转路径
|
||||
* @param {Object} buffer
|
||||
*/
|
||||
// @ts-nocheck
|
||||
export function arrayBufferToFile(buffer: ArrayBuffer | Blob, name?: string, format?:string):Promise<(File|string)> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP
|
||||
const fs = uni.getFileSystemManager()
|
||||
//自定义文件名
|
||||
if (!name && !format) {
|
||||
reject(new Error('ERROR_NAME_PARSE'))
|
||||
}
|
||||
const fileName = `${name || new Date().getTime()}.${format.replace(/(.+)?\//,'')}`;
|
||||
let pre = platform()
|
||||
const filePath = `${pre.env.USER_DATA_PATH}/${fileName}`
|
||||
fs.writeFile({
|
||||
filePath,
|
||||
data: buffer,
|
||||
success() {
|
||||
resolve(filePath)
|
||||
},
|
||||
fail(err) {
|
||||
console.error(err)
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
const file = new File([buffer], name, {
|
||||
type: format,
|
||||
});
|
||||
resolve(file)
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
|
||||
const base64 = uni.arrayBufferToBase64(buffer)
|
||||
bitmap.loadBase64Data(base64, () => {
|
||||
if (!name && !format) {
|
||||
reject(new Error('ERROR_NAME_PARSE'))
|
||||
}
|
||||
const fileNmae = `${name || new Date().getTime()}.${format.replace(/(.+)?\//,'')}`;
|
||||
const filePath = `_doc/uniapp_temp/${fileNmae}`
|
||||
bitmap.save(filePath, {},
|
||||
() => {
|
||||
bitmap.clear()
|
||||
resolve(filePath)
|
||||
},
|
||||
(error) => {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
}, (error) => {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
13
src/uni_modules/lime-shared/base64ToArrayBuffer/index.ts
Normal file
13
src/uni_modules/lime-shared/base64ToArrayBuffer/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// @ts-nocheck
|
||||
// 未完成
|
||||
export function base64ToArrayBuffer(base64 : string) {
|
||||
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
|
||||
if (!format) {
|
||||
new Error('ERROR_BASE64SRC_PARSE')
|
||||
}
|
||||
if(uni.base64ToArrayBuffer) {
|
||||
return uni.base64ToArrayBuffer(bodyData)
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
76
src/uni_modules/lime-shared/base64ToPath/index.ts
Normal file
76
src/uni_modules/lime-shared/base64ToPath/index.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
// @ts-nocheck
|
||||
import {platform} from '../platform'
|
||||
/**
|
||||
* base64转路径
|
||||
* @param {Object} base64
|
||||
*/
|
||||
export function base64ToPath(base64: string, filename?: string):Promise<string> {
|
||||
const [, format] = /^data:image\/(\w+);base64,/.exec(base64) || [];
|
||||
console.log('format', format)
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef MP
|
||||
const fs = uni.getFileSystemManager()
|
||||
//自定义文件名
|
||||
if (!filename && !format) {
|
||||
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
||||
}
|
||||
// const time = new Date().getTime();
|
||||
const name = filename || `${new Date().getTime()}.${format}`;
|
||||
let pre = platform()
|
||||
const filePath = `${pre.env.USER_DATA_PATH}/${name}`
|
||||
fs.writeFile({
|
||||
filePath,
|
||||
data: base64.split(',')[1],
|
||||
encoding: 'base64',
|
||||
success() {
|
||||
resolve(filePath)
|
||||
},
|
||||
fail(err) {
|
||||
console.error(err)
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
// mime类型
|
||||
let mimeString = base64.split(',')[0].split(':')[1].split(';')[0];
|
||||
//base64 解码
|
||||
let byteString = atob(base64.split(',')[1]);
|
||||
//创建缓冲数组
|
||||
let arrayBuffer = new ArrayBuffer(byteString.length);
|
||||
//创建视图
|
||||
let intArray = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < byteString.length; i++) {
|
||||
intArray[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
resolve(URL.createObjectURL(new Blob([intArray], {
|
||||
type: mimeString
|
||||
})))
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
|
||||
bitmap.loadBase64Data(base64, () => {
|
||||
if (!filename && !format) {
|
||||
reject(new Error('ERROR_BASE64SRC_PARSE'))
|
||||
}
|
||||
// const time = new Date().getTime();
|
||||
const name = filename || `${new Date().getTime()}.${format}`;
|
||||
const filePath = `_doc/uniapp_temp/${name}`
|
||||
bitmap.save(filePath, {},
|
||||
() => {
|
||||
bitmap.clear()
|
||||
resolve(filePath)
|
||||
},
|
||||
(error) => {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
}, (error) => {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
21
src/uni_modules/lime-shared/camelCase/index.ts
Normal file
21
src/uni_modules/lime-shared/camelCase/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 将字符串转换为 camelCase 或 PascalCase 风格的命名约定
|
||||
* @param str 要转换的字符串
|
||||
* @param isPascalCase 指示是否转换为 PascalCase 的布尔值,默认为 false
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
export function camelCase(str: string, isPascalCase: boolean = false): string {
|
||||
// 将字符串分割成单词数组
|
||||
let words: string[] = str.split(/[\s_-]+/);
|
||||
|
||||
// 将数组中的每个单词首字母大写(除了第一个单词)
|
||||
let camelCased: string[] = words.map((word, index) => {
|
||||
if (index === 0 && !isPascalCase) {
|
||||
return word.toLowerCase(); // 第一个单词全小写
|
||||
}
|
||||
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
||||
});
|
||||
|
||||
// 将数组中的单词拼接成一个字符串
|
||||
return camelCased.join('');
|
||||
};
|
||||
58
src/uni_modules/lime-shared/canIUseCanvas2d/index.ts
Normal file
58
src/uni_modules/lime-shared/canIUseCanvas2d/index.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// @ts-nocheck
|
||||
// #ifdef MP-ALIPAY
|
||||
interface My {
|
||||
SDKVersion: string
|
||||
}
|
||||
declare var my: My
|
||||
// #endif
|
||||
|
||||
function compareVersion(v1:string, v2:string) {
|
||||
let a1 = v1.split('.');
|
||||
let a2 = v2.split('.');
|
||||
const len = Math.max(a1.length, a2.length);
|
||||
|
||||
while (a1.length < len) {
|
||||
a1.push('0');
|
||||
}
|
||||
while (a2.length < len) {
|
||||
a2.push('0');
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(a1[i], 10);
|
||||
const num2 = parseInt(a2[i], 10);
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1;
|
||||
}
|
||||
if (num1 < num2) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function gte(version: string) {
|
||||
let {SDKVersion} = uni.getSystemInfoSync();
|
||||
// #ifdef MP-ALIPAY
|
||||
SDKVersion = my.SDKVersion
|
||||
// #endif
|
||||
return compareVersion(SDKVersion, version) >= 0;
|
||||
}
|
||||
|
||||
/** 环境是否支持canvas 2d */
|
||||
export function canIUseCanvas2d() {
|
||||
// #ifdef MP-WEIXIN
|
||||
return gte('2.9.0');
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
return gte('2.7.0');
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO
|
||||
return gte('1.78.0');
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO
|
||||
return false
|
||||
// #endif
|
||||
}
|
||||
30
src/uni_modules/lime-shared/changelog.md
Normal file
30
src/uni_modules/lime-shared/changelog.md
Normal file
@@ -0,0 +1,30 @@
|
||||
## 0.1.4(2023-09-05)
|
||||
- feat: 增加 Hooks `useIntersectionObserver`
|
||||
- feat: 增加 `floatAdd`
|
||||
- feat: 因为本人插件兼容 vue2 需要使用 `composition-api`,故增加vue文件代码插件的条件编译
|
||||
## 0.1.3(2023-08-13)
|
||||
- feat: 增加 `camelCase`
|
||||
## 0.1.2(2023-07-17)
|
||||
- feat: 增加 `getClassStr`
|
||||
## 0.1.1(2023-07-06)
|
||||
- feat: 增加 `isNumeric`, 区别于 `isNumber`
|
||||
## 0.1.0(2023-06-30)
|
||||
- fix: `clamp`忘记导出了
|
||||
## 0.0.9(2023-06-27)
|
||||
- feat: 增加`arrayBufferToFile`
|
||||
## 0.0.8(2023-06-19)
|
||||
- feat: 增加`createAnimation`、`clamp`
|
||||
## 0.0.7(2023-06-08)
|
||||
- chore: 更新注释
|
||||
## 0.0.6(2023-06-08)
|
||||
- chore: 增加`createImage`为`lime-watermark`和`lime-qrcode`提供依赖
|
||||
## 0.0.5(2023-06-03)
|
||||
- chore: 更新注释
|
||||
## 0.0.4(2023-05-22)
|
||||
- feat: 增加`range`,`exif`,`selectComponent`
|
||||
## 0.0.3(2023-05-08)
|
||||
- feat: 增加`fillZero`,`debounce`,`throttle`,`random`
|
||||
## 0.0.2(2023-05-05)
|
||||
- chore: 更新文档
|
||||
## 0.0.1(2023-05-05)
|
||||
- 无
|
||||
16
src/uni_modules/lime-shared/clamp/index.ts
Normal file
16
src/uni_modules/lime-shared/clamp/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 将一个值限制在指定的范围内
|
||||
* @param min 最小值
|
||||
* @param max 最大值
|
||||
* @param val 要限制的值
|
||||
* @returns 限制后的值
|
||||
*/
|
||||
export function clamp(min: number, max: number, val: number): number {
|
||||
return Math.max(min, Math.min(max, val));
|
||||
}
|
||||
|
||||
|
||||
// console.log(clamp(0, 10, 5)); // 输出: 5(在范围内,不做更改)
|
||||
// console.log(clamp(0, 10, -5)); // 输出: 0(小于最小值,被限制为最小值)
|
||||
// console.log(clamp(0, 10, 15)); // 输出: 10(大于最大值,被限制为最大值)
|
||||
103
src/uni_modules/lime-shared/cloneDeep/index.ts
Normal file
103
src/uni_modules/lime-shared/cloneDeep/index.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 深度克隆一个对象或数组
|
||||
* @param obj 要克隆的对象或数组
|
||||
* @returns 克隆后的对象或数组
|
||||
*/
|
||||
export function cloneDeep<T>(obj: any): T {
|
||||
// 如果传入的对象为空,返回空
|
||||
if (obj === null) {
|
||||
return null as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是 Set 类型,则将其转换为数组,并通过新的 Set 构造函数创建一个新的 Set 对象
|
||||
if (obj instanceof Set) {
|
||||
return new Set([...obj]) as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是 Map 类型,则将其转换为数组,并通过新的 Map 构造函数创建一个新的 Map 对象
|
||||
if (obj instanceof Map) {
|
||||
return new Map([...obj]) as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是 WeakMap 类型,则直接用传入的 WeakMap 对象进行赋值
|
||||
if (obj instanceof WeakMap) {
|
||||
let weakMap = new WeakMap();
|
||||
weakMap = obj;
|
||||
return weakMap as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是 WeakSet 类型,则直接用传入的 WeakSet 对象进行赋值
|
||||
if (obj instanceof WeakSet) {
|
||||
let weakSet = new WeakSet();
|
||||
weakSet = obj;
|
||||
return weakSet as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是 RegExp 类型,则通过新的 RegExp 构造函数创建一个新的 RegExp 对象
|
||||
if (obj instanceof RegExp) {
|
||||
return new RegExp(obj) as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是 undefined 类型,则返回 undefined
|
||||
if (typeof obj === 'undefined') {
|
||||
return undefined as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是数组,则递归调用 cloneDeep 函数对数组中的每个元素进行克隆
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(cloneDeep) as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是 Date 类型,则通过新的 Date 构造函数创建一个新的 Date 对象
|
||||
if (obj instanceof Date) {
|
||||
return new Date(obj.getTime()) as unknown as T;
|
||||
}
|
||||
|
||||
// 如果传入的对象是普通对象,则使用递归调用 cloneDeep 函数对对象的每个属性进行克隆
|
||||
if (typeof obj === 'object') {
|
||||
const newObj: any = {};
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
newObj[key] = cloneDeep(value);
|
||||
}
|
||||
const symbolKeys = Object.getOwnPropertySymbols(obj);
|
||||
for (const key of symbolKeys) {
|
||||
newObj[key] = cloneDeep(obj[key]);
|
||||
}
|
||||
return newObj;
|
||||
}
|
||||
|
||||
// 如果传入的对象是基本数据类型(如字符串、数字等),则直接返回
|
||||
return obj;
|
||||
}
|
||||
|
||||
// 示例使用
|
||||
|
||||
// // 克隆一个对象
|
||||
// const obj = { name: 'John', age: 30 };
|
||||
// const clonedObj = cloneDeep(obj);
|
||||
|
||||
// console.log(clonedObj); // 输出: { name: 'John', age: 30 }
|
||||
// console.log(clonedObj === obj); // 输出: false (副本与原对象是独立的)
|
||||
|
||||
// // 克隆一个数组
|
||||
// const arr = [1, 2, 3];
|
||||
// const clonedArr = cloneDeep(arr);
|
||||
|
||||
// console.log(clonedArr); // 输出: [1, 2, 3]
|
||||
// console.log(clonedArr === arr); // 输出: false (副本与原数组是独立的)
|
||||
|
||||
// // 克隆一个包含嵌套对象的对象
|
||||
// const person = {
|
||||
// name: 'Alice',
|
||||
// age: 25,
|
||||
// address: {
|
||||
// city: 'New York',
|
||||
// country: 'USA',
|
||||
// },
|
||||
// };
|
||||
// const clonedPerson = cloneDeep(person);
|
||||
|
||||
// console.log(clonedPerson); // 输出: { name: 'Alice', age: 25, address: { city: 'New York', country: 'USA' } }
|
||||
// console.log(clonedPerson === person); // 输出: false (副本与原对象是独立的)
|
||||
// console.log(clonedPerson.address === person.address); // 输出: false (嵌套对象的副本也是独立的)
|
||||
22
src/uni_modules/lime-shared/closest/index.ts
Normal file
22
src/uni_modules/lime-shared/closest/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
// @ts-nocheck
|
||||
|
||||
/**
|
||||
* 在给定数组中找到最接近目标数字的元素。
|
||||
* @param arr 要搜索的数字数组。
|
||||
* @param target 目标数字。
|
||||
* @returns 最接近目标数字的数组元素。
|
||||
*/
|
||||
export function closest(arr: number[], target: number) {
|
||||
return arr.reduce((pre, cur) =>
|
||||
Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur
|
||||
);
|
||||
}
|
||||
|
||||
// 示例
|
||||
// // 定义一个数字数组
|
||||
// const numbers = [1, 3, 5, 7, 9];
|
||||
|
||||
// // 在数组中找到最接近目标数字 6 的元素
|
||||
// const closestNumber = closest(numbers, 6);
|
||||
|
||||
// console.log(closestNumber); // 输出结果: 5
|
||||
149
src/uni_modules/lime-shared/createAnimation/index.ts
Normal file
149
src/uni_modules/lime-shared/createAnimation/index.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
// @ts-nocheck
|
||||
// nvue 需要在节点上设置ref或在export里传入
|
||||
// const animation = createAnimation({
|
||||
// ref: this.$refs['xxx'],
|
||||
// duration: 0,
|
||||
// timingFunction: 'linear'
|
||||
// })
|
||||
// animation.opacity(1).translate(x, y).step({duration})
|
||||
// animation.export(ref)
|
||||
|
||||
// 抹平nvue 与 uni.createAnimation的使用差距
|
||||
// 但是nvue动画太慢~~~无语
|
||||
|
||||
|
||||
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
const nvueAnimation = uni.requireNativePlugin('animation')
|
||||
|
||||
type AnimationTypes = 'matrix' | 'matrix3d' | 'rotate' | 'rotate3d' | 'rotateX' | 'rotateY' | 'rotateZ' | 'scale' | 'scale3d' | 'scaleX' | 'scaleY' | 'scaleZ' | 'skew' | 'skewX' | 'skewY' | 'translate' | 'translate3d' | 'translateX' | 'translateY' | 'translateZ'
|
||||
| 'opacity' | 'backgroundColor' | 'width' | 'height' | 'left' | 'right' | 'top' | 'bottom'
|
||||
|
||||
interface Styles {
|
||||
[key : string] : any
|
||||
}
|
||||
|
||||
interface StepConfig {
|
||||
duration?: number
|
||||
timingFunction?: string
|
||||
delay?: number
|
||||
needLayout?: boolean
|
||||
transformOrigin?: string
|
||||
}
|
||||
interface StepAnimate {
|
||||
styles?: Styles
|
||||
config?: StepConfig
|
||||
}
|
||||
interface StepAnimates {
|
||||
[key: number]: StepAnimate
|
||||
}
|
||||
interface CreateAnimationOptions extends UniApp.CreateAnimationOptions {
|
||||
ref?: string
|
||||
}
|
||||
|
||||
type Callback = (time: number) => void
|
||||
const animateTypes1 : AnimationTypes[] = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
|
||||
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
|
||||
'translateZ'
|
||||
]
|
||||
const animateTypes2 : AnimationTypes[] = ['opacity', 'backgroundColor']
|
||||
const animateTypes3 : AnimationTypes[] = ['width', 'height', 'left', 'right', 'top', 'bottom']
|
||||
|
||||
class LimeAnimation {
|
||||
ref : any
|
||||
context : any
|
||||
options : UniApp.CreateAnimationOptions
|
||||
// stack : any[] = []
|
||||
next : number = 0
|
||||
currentStepAnimates : StepAnimates = {}
|
||||
duration : number = 0
|
||||
constructor(options : CreateAnimationOptions) {
|
||||
const {ref} = options
|
||||
this.ref = ref
|
||||
this.options = options
|
||||
}
|
||||
addAnimate(type : AnimationTypes, args: (string | number)[]) {
|
||||
let aniObj = this.currentStepAnimates[this.next]
|
||||
let stepAnimate:StepAnimate = {}
|
||||
if (!aniObj) {
|
||||
stepAnimate = {styles: {}, config: {}}
|
||||
} else {
|
||||
stepAnimate = aniObj
|
||||
}
|
||||
|
||||
if (animateTypes1.includes(type)) {
|
||||
if (!stepAnimate.styles.transform) {
|
||||
stepAnimate.styles.transform = ''
|
||||
}
|
||||
let unit = ''
|
||||
if (type === 'rotate') {
|
||||
unit = 'deg'
|
||||
}
|
||||
stepAnimate.styles.transform += `${type}(${args.map((v: number) => v + unit).join(',')}) `
|
||||
} else {
|
||||
stepAnimate.styles[type] = `${args.join(',')}`
|
||||
}
|
||||
this.currentStepAnimates[this.next] = stepAnimate
|
||||
}
|
||||
animateRun(styles: Styles = {}, config:StepConfig = {}, ref: any) {
|
||||
const el = ref || this.ref
|
||||
if (!el) return
|
||||
return new Promise((resolve) => {
|
||||
const time = +new Date()
|
||||
nvueAnimation.transition(el, {
|
||||
styles,
|
||||
...config
|
||||
}, () => {
|
||||
resolve(+new Date() - time)
|
||||
})
|
||||
})
|
||||
}
|
||||
nextAnimate(animates: StepAnimates, step: number = 0, ref: any, cb: Callback) {
|
||||
let obj = animates[step]
|
||||
if (obj) {
|
||||
let { styles, config } = obj
|
||||
// this.duration += config.duration
|
||||
this.animateRun(styles, config, ref).then((time: number) => {
|
||||
step += 1
|
||||
this.duration += time
|
||||
this.nextAnimate(animates, step, ref, cb)
|
||||
})
|
||||
} else {
|
||||
this.currentStepAnimates = {}
|
||||
cb && cb(this.duration)
|
||||
}
|
||||
}
|
||||
step(config:StepConfig = {}) {
|
||||
this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
|
||||
this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
|
||||
this.next++
|
||||
return this
|
||||
}
|
||||
export(ref: any, cb?: Callback) {
|
||||
ref = ref || this.ref
|
||||
if(!ref) return
|
||||
this.duration = 0
|
||||
this.next = 0
|
||||
this.nextAnimate(this.currentStepAnimates, 0, ref, cb)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
|
||||
LimeAnimation.prototype[type] = function(...args: (string | number)[]) {
|
||||
this.addAnimate(type, args)
|
||||
return this
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
export function createAnimation(options : CreateAnimationOptions) {
|
||||
// #ifndef APP-NVUE
|
||||
// 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误
|
||||
return uni.createAnimation({ ...options })
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
return new LimeAnimation(options)
|
||||
// #endif
|
||||
}
|
||||
61
src/uni_modules/lime-shared/createImage/index.ts
Normal file
61
src/uni_modules/lime-shared/createImage/index.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
// @ts-nocheck
|
||||
import {isBrowser} from '../isBrowser'
|
||||
class Image {
|
||||
currentSrc: string | null = null
|
||||
naturalHeight: number = 0
|
||||
naturalWidth: number = 0
|
||||
width: number = 0
|
||||
height: number = 0
|
||||
tagName: string = 'IMG'
|
||||
path: string = ''
|
||||
crossOrigin: string = ''
|
||||
referrerPolicy: string = ''
|
||||
onload: () => void = () => {}
|
||||
onerror: () => void = () => {}
|
||||
complete: boolean = false
|
||||
constructor() {}
|
||||
set src(src: string) {
|
||||
console.log('src', src)
|
||||
if(!src) {
|
||||
return this.onerror()
|
||||
}
|
||||
src = src.replace(/^@\//,'/')
|
||||
this.currentSrc = src
|
||||
uni.getImageInfo({
|
||||
src,
|
||||
success: (res) => {
|
||||
const localReg = /^\.|^\/(?=[^\/])/;
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO
|
||||
res.path = localReg.test(src) ? `/${res.path}` : res.path;
|
||||
// #endif
|
||||
this.complete = true
|
||||
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
|
||||
}
|
||||
}
|
||||
interface UniImage extends WechatMiniprogram.Image {
|
||||
complete?: boolean
|
||||
naturalHeight?: number
|
||||
naturalWidth?: number
|
||||
}
|
||||
/** 创建用于 canvas 的 img */
|
||||
export function createImage(canvas?: any): HTMLImageElement | UniImage {
|
||||
if(canvas && canvas.createImage) {
|
||||
return (canvas as WechatMiniprogram.Canvas).createImage()
|
||||
} else if(this.tagName == 'canvas' && !('toBlob' in this) || canvas && !('toBlob' in canvas)){
|
||||
return new Image()
|
||||
} else if(isBrowser) {
|
||||
return new window.Image()
|
||||
}
|
||||
return new Image()
|
||||
}
|
||||
38
src/uni_modules/lime-shared/debounce/index.ts
Normal file
38
src/uni_modules/lime-shared/debounce/index.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
// @ts-nocheck
|
||||
type Timeout = ReturnType<typeof setTimeout> | null;
|
||||
/**
|
||||
* 防抖函数,通过延迟一定时间来限制函数的执行频率。
|
||||
* @param fn 要防抖的函数。
|
||||
* @param wait 触发防抖的等待时间,单位为毫秒。
|
||||
* @returns 防抖函数。
|
||||
*/
|
||||
export function debounce(fn: (...args: any[]) => void, wait = 300) {
|
||||
let timer: Timeout = null; // 用于存储 setTimeout 的标识符的变量
|
||||
|
||||
return function (this: any, ...args: any[]) {
|
||||
if (timer) clearTimeout(timer); // 如果上一个 setTimeout 存在,则清除它
|
||||
|
||||
// 设置一个新的 setTimeout,在指定的等待时间后调用防抖函数
|
||||
timer = setTimeout(() => {
|
||||
fn.apply(this, args); // 使用提供的参数调用原始函数
|
||||
}, wait);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 示例
|
||||
// 定义一个函数
|
||||
// function saveData(data: string) {
|
||||
// // 模拟保存数据的操作
|
||||
// console.log(`Saving data: ${data}`);
|
||||
// }
|
||||
|
||||
// // 创建一个防抖函数,延迟 500 毫秒后调用 saveData 函数
|
||||
// const debouncedSaveData = debounce(saveData, 500);
|
||||
|
||||
// // 连续调用防抖函数
|
||||
// debouncedSaveData('Data 1'); // 不会立即调用 saveData 函数
|
||||
// debouncedSaveData('Data 2'); // 不会立即调用 saveData 函数
|
||||
|
||||
// 在 500 毫秒后,只会调用一次 saveData 函数,输出结果为 "Saving data: Data 2"
|
||||
1056
src/uni_modules/lime-shared/exif/index.ts
Normal file
1056
src/uni_modules/lime-shared/exif/index.ts
Normal file
File diff suppressed because it is too large
Load Diff
11
src/uni_modules/lime-shared/fillZero/index.ts
Normal file
11
src/uni_modules/lime-shared/fillZero/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 在数字前填充零,返回字符串形式的结果
|
||||
* @param number 要填充零的数字
|
||||
* @param length 填充零后的字符串长度,默认为2
|
||||
* @returns 填充零后的字符串
|
||||
*/
|
||||
export function fillZero(number: number, length: number = 2): string {
|
||||
// 将数字转换为字符串,然后使用 padStart 方法填充零到指定长度
|
||||
return `${number}`.padStart(length, '0');
|
||||
}
|
||||
36
src/uni_modules/lime-shared/floatAdd/index.ts
Normal file
36
src/uni_modules/lime-shared/floatAdd/index.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import {isNumber} from '../isNumber'
|
||||
/**
|
||||
* 返回两个浮点数相加的结果
|
||||
* @param num1 第一个浮点数
|
||||
* @param num2 第二个浮点数
|
||||
* @returns 两个浮点数的相加结果
|
||||
*/
|
||||
export function floatAdd(num1: number, num2: number): number {
|
||||
// 检查 num1 和 num2 是否为数字类型
|
||||
if (!(isNumber(num1) || isNumber(num2))) {
|
||||
console.warn('Please pass in the number type');
|
||||
return NaN;
|
||||
}
|
||||
|
||||
let r1: number, r2: number, m: number;
|
||||
|
||||
try {
|
||||
// 获取 num1 小数点后的位数
|
||||
r1 = num1.toString().split('.')[1].length;
|
||||
} catch (error) {
|
||||
r1 = 0;
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取 num2 小数点后的位数
|
||||
r2 = num2.toString().split('.')[1].length;
|
||||
} catch (error) {
|
||||
r2 = 0;
|
||||
}
|
||||
|
||||
// 计算需要扩大的倍数
|
||||
m = Math.pow(10, Math.max(r1, r2));
|
||||
|
||||
// 返回相加结果
|
||||
return (num1 * m + num2 * m) / m;
|
||||
}
|
||||
27
src/uni_modules/lime-shared/getClassStr/index.ts
Normal file
27
src/uni_modules/lime-shared/getClassStr/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 获取对象的类名字符串
|
||||
* @param obj - 需要处理的对象
|
||||
* @returns 由对象属性作为类名组成的字符串
|
||||
*/
|
||||
export function getClassStr<T>(obj: T): string {
|
||||
let classNames: string[] = [];
|
||||
|
||||
// 遍历对象的属性
|
||||
for (let key in obj) {
|
||||
// 检查属性确实属于对象自身且其值为true
|
||||
if ((obj as any).hasOwnProperty(key) && obj[key]) {
|
||||
// 将属性名添加到类名数组中
|
||||
classNames.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
// 将类名数组用空格连接成字符串并返回
|
||||
return classNames.join(' ');
|
||||
}
|
||||
|
||||
|
||||
// 示例
|
||||
// const obj = { foo: true, bar: false, baz: true };
|
||||
// const classNameStr = getClassStr(obj);
|
||||
// console.log(classNameStr); // 输出: "foo baz"
|
||||
6
src/uni_modules/lime-shared/getCurrentPage/index.ts
Normal file
6
src/uni_modules/lime-shared/getCurrentPage/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// @ts-nocheck
|
||||
/** 获取当前页 */
|
||||
export const getCurrentPage = () => {
|
||||
const pages = getCurrentPages();
|
||||
return pages[pages.length - 1] //as T & WechatMiniprogram.Page.TrivialInstance;
|
||||
};
|
||||
14
src/uni_modules/lime-shared/getLocalFilePath/index.ts
Normal file
14
src/uni_modules/lime-shared/getLocalFilePath/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// @ts-nocheck
|
||||
export const getLocalFilePath = (path: string) => {
|
||||
if(typeof plus == 'undefined') return path
|
||||
if(/^(_www|_doc|_documents|_downloads|file:\/\/|\/storage\/emulated\/0\/)/.test(path)) return path
|
||||
if (/^\//.test(path)) {
|
||||
const localFilePath = plus.io.convertAbsoluteFileSystem(path)
|
||||
if (localFilePath !== path) {
|
||||
return localFilePath
|
||||
} else {
|
||||
path = path.slice(1)
|
||||
}
|
||||
}
|
||||
return '_www/' + path
|
||||
}
|
||||
86
src/uni_modules/lime-shared/getRect/index.ts
Normal file
86
src/uni_modules/lime-shared/getRect/index.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
// @ts-nocheck
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
// 当编译环境是 APP-NVUE 时,引入 uni.requireNativePlugin('dom'),具体插件用途未知
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
// #endif
|
||||
|
||||
interface RectOptions {
|
||||
/**
|
||||
* 上下文
|
||||
*/
|
||||
context ?: any // ComponentInternalInstance 类型,用于指定上下文
|
||||
|
||||
/**
|
||||
* 是否需要获取所有节点,nvue 环境下不支持
|
||||
*/
|
||||
needAll ?: boolean,
|
||||
|
||||
/**
|
||||
* 节点引用对象,类型为 UniNamespace.NodesRef
|
||||
*/
|
||||
nodes ?: UniNamespace.NodesRef
|
||||
|
||||
/**
|
||||
* 节点引用对象的键,类型为 UniNamespace.NodesRef 中的某个键
|
||||
*/
|
||||
type ?: keyof UniNamespace.NodesRef
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点信息
|
||||
* @param selector 选择器字符串
|
||||
* @param options RectOptions 对象,用于配置选项
|
||||
* @returns 包含节点信息的 Promise 对象
|
||||
*/
|
||||
export function getRect(selector : string, options : RectOptions = {}) {
|
||||
// #ifndef APP-NVUE
|
||||
const typeDefault = 'boundingClientRect'
|
||||
let { context, needAll, type = typeDefault } = options
|
||||
// #endif
|
||||
|
||||
// #ifdef MP || VUE2
|
||||
if (context.proxy) context = context.proxy
|
||||
// #endif
|
||||
|
||||
return new Promise<UniNamespace.NodeInfo>((resolve, reject) => {
|
||||
// #ifndef APP-NVUE
|
||||
const dom = uni.createSelectorQuery().in(context)[needAll ? 'selectAll' : 'select'](selector);
|
||||
const result = (rect: UniNamespace.NodeInfo) => {
|
||||
if (rect) {
|
||||
resolve(rect)
|
||||
} else {
|
||||
reject('no rect')
|
||||
}
|
||||
}
|
||||
if (type == typeDefault) {
|
||||
dom[type](result).exec()
|
||||
} else {
|
||||
dom[type]({
|
||||
node: true,
|
||||
size: true,
|
||||
rect: true
|
||||
}, result).exec()
|
||||
}
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
let { context } = options
|
||||
if (/#|\./.test(selector) && context.refs) {
|
||||
selector = selector.replace(/#|\./, '')
|
||||
if (context.refs[selector]) {
|
||||
selector = context.refs[selector]
|
||||
if(Array.isArray(selector)) {
|
||||
selector = selector[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
dom.getComponentRect(selector, (res) => {
|
||||
if (res.size) {
|
||||
resolve(res.size)
|
||||
} else {
|
||||
reject('no rect')
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
});
|
||||
};
|
||||
30
src/uni_modules/lime-shared/getStyleStr/index.ts
Normal file
30
src/uni_modules/lime-shared/getStyleStr/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// @ts-nocheck
|
||||
interface CSSProperties {
|
||||
[key: string]: string | number
|
||||
}
|
||||
/**
|
||||
* 将字符串转换为带有连字符分隔的小写形式
|
||||
* @param key - 要转换的字符串
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
export function toLowercaseSeparator(key: string) {
|
||||
return key.replace(/([A-Z])/g, '-$1').toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取样式对象对应的样式字符串
|
||||
* @param style - CSS样式对象
|
||||
* @returns 由非空有效样式属性键值对组成的字符串
|
||||
*/
|
||||
export function getStyleStr(style: CSSProperties): string {
|
||||
return Object.keys(style)
|
||||
.filter(key => style[key] !== undefined && style[key] !== null && style[key] !== '')
|
||||
.map((key: string) => `${toLowercaseSeparator(key)}: ${style[key]};`)
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
// 示例
|
||||
// const style = { color: 'red', fontSize: '16px', backgroundColor: '', border: null };
|
||||
// const styleStr = getStyleStr(style);
|
||||
// console.log(styleStr);
|
||||
// 输出: "color: red; font-size: 16px;"
|
||||
30
src/uni_modules/lime-shared/hasOwn/index.ts
Normal file
30
src/uni_modules/lime-shared/hasOwn/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// @ts-nocheck
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty
|
||||
/**
|
||||
* 检查对象或数组是否具有指定的属性或键
|
||||
* @param obj 要检查的对象或数组
|
||||
* @param key 指定的属性或键
|
||||
* @returns 如果对象或数组具有指定的属性或键,则返回true;否则返回false
|
||||
*/
|
||||
export function hasOwn(obj: Object | Array<any>, key: string): boolean {
|
||||
return hasOwnProperty.call(obj, key);
|
||||
}
|
||||
|
||||
// 示例
|
||||
// const obj = { name: 'John', age: 30 };
|
||||
|
||||
// if (hasOwn(obj, 'name')) {
|
||||
// console.log("对象具有 'name' 属性");
|
||||
// } else {
|
||||
// console.log("对象不具有 'name' 属性");
|
||||
// }
|
||||
// // 输出: 对象具有 'name' 属性
|
||||
|
||||
// const arr = [1, 2, 3];
|
||||
|
||||
// if (hasOwn(arr, 'length')) {
|
||||
// console.log("数组具有 'length' 属性");
|
||||
// } else {
|
||||
// console.log("数组不具有 'length' 属性");
|
||||
// }
|
||||
// 输出: 数组具有 'length' 属性
|
||||
43
src/uni_modules/lime-shared/index.ts
Normal file
43
src/uni_modules/lime-shared/index.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
// @ts-nocheck
|
||||
// validator
|
||||
export * from './isString'
|
||||
export * from './isNumber'
|
||||
export * from './isNumeric'
|
||||
export * from './isDef'
|
||||
export * from './isFunction'
|
||||
export * from './isObject'
|
||||
export * from './isPromise'
|
||||
export * from './isBase64'
|
||||
|
||||
export * from './hasOwn'
|
||||
|
||||
// 单位转换
|
||||
export * from './addUnit'
|
||||
export * from './unitConvert'
|
||||
export * from './toNumber'
|
||||
|
||||
export * from './random'
|
||||
export * from './range'
|
||||
export * from './fillZero'
|
||||
|
||||
// image
|
||||
export * from './base64ToPath'
|
||||
export * from './pathToBase64'
|
||||
export * from './exif'
|
||||
|
||||
// canvas
|
||||
export * from './canIUseCanvas2d'
|
||||
|
||||
// page
|
||||
export * from './getCurrentPage'
|
||||
|
||||
// dom
|
||||
export * from './getRect'
|
||||
export * from './selectComponent'
|
||||
export * from './createAnimation'
|
||||
|
||||
// delay
|
||||
export * from './sleep'
|
||||
export * from './debounce'
|
||||
export * from './throttle'
|
||||
|
||||
9
src/uni_modules/lime-shared/isBase64/index.ts
Normal file
9
src/uni_modules/lime-shared/isBase64/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 判断给定的路径是否为Base64编码的图像路径
|
||||
* @param path 图像路径
|
||||
* @returns 如果路径是Base64编码,则返回true;否则返回false
|
||||
*/
|
||||
export const isBase64 = (path: string): boolean => {
|
||||
return /^data:image\/(\w+);base64/.test(path);
|
||||
};
|
||||
2
src/uni_modules/lime-shared/isBrowser/index.ts
Normal file
2
src/uni_modules/lime-shared/isBrowser/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// @ts-nocheck
|
||||
export const isBrowser = typeof window !== 'undefined';
|
||||
9
src/uni_modules/lime-shared/isDef/index.ts
Normal file
9
src/uni_modules/lime-shared/isDef/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 检查一个值是否已定义(不为 undefined)且不为 null
|
||||
* @param value 要检查的值
|
||||
* @returns 如果值已定义且不为 null,则返回 true;否则返回 false
|
||||
*/
|
||||
export function isDef(value: unknown): boolean {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
8
src/uni_modules/lime-shared/isFunction/index.ts
Normal file
8
src/uni_modules/lime-shared/isFunction/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 检查一个值是否为函数类型
|
||||
* @param val 要检查的值
|
||||
* @returns 如果值的类型是函数类型,则返回 true;否则返回 false
|
||||
*/
|
||||
export const isFunction = (val: unknown): val is Function =>
|
||||
typeof val === 'function';
|
||||
9
src/uni_modules/lime-shared/isNumber/index.ts
Normal file
9
src/uni_modules/lime-shared/isNumber/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 检查一个值是否为数字类型
|
||||
* @param value 要检查的值,可以是 number 类型或 string 类型的数字
|
||||
* @returns 如果值是数字类型且不是 NaN,则返回 true;否则返回 false
|
||||
*/
|
||||
export function isNumber(value: number | string): boolean {
|
||||
return typeof value === 'number' && !isNaN(value);
|
||||
}
|
||||
9
src/uni_modules/lime-shared/isNumeric/index.ts
Normal file
9
src/uni_modules/lime-shared/isNumeric/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 检查一个值是否为数字类型或表示数字的字符串
|
||||
* @param value 要检查的值,可以是 string 类型或 number 类型
|
||||
* @returns 如果值是数字类型或表示数字的字符串,则返回 true;否则返回 false
|
||||
*/
|
||||
export function isNumeric(value: string | number): boolean {
|
||||
return /^(-)?\d+(\.\d+)?$/.test(value);
|
||||
}
|
||||
8
src/uni_modules/lime-shared/isObject/index.ts
Normal file
8
src/uni_modules/lime-shared/isObject/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 检查一个值是否为对象类型
|
||||
* @param val 要检查的值
|
||||
* @returns 如果值的类型是对象类型,则返回 true;否则返回 false
|
||||
*/
|
||||
export const isObject = (val : unknown) : val is Record<any, any> =>
|
||||
val !== null && typeof val === 'object';
|
||||
13
src/uni_modules/lime-shared/isPromise/index.ts
Normal file
13
src/uni_modules/lime-shared/isPromise/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// @ts-nocheck
|
||||
import {isFunction} from '../isFunction'
|
||||
import {isObject} from '../isObject'
|
||||
/**
|
||||
* 检查一个值是否为 Promise 类型
|
||||
* @param val 要检查的值
|
||||
* @returns 如果值的类型是 Promise 类型,则返回 true;否则返回 false
|
||||
*/
|
||||
export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
|
||||
// 使用 isObject 函数判断值是否为对象类型
|
||||
// 使用 isFunction 函数判断值是否具有 then 方法和 catch 方法
|
||||
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
|
||||
};
|
||||
7
src/uni_modules/lime-shared/isString/index.ts
Normal file
7
src/uni_modules/lime-shared/isString/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* 检查一个值是否为字符串类型
|
||||
* @param str 要检查的值
|
||||
* @returns 如果值的类型是字符串类型,则返回 true;否则返回 false
|
||||
*/
|
||||
export const isString = (str: unknown): str is string => typeof str === 'string';
|
||||
17
src/uni_modules/lime-shared/kebabCase/index.ts
Normal file
17
src/uni_modules/lime-shared/kebabCase/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// export function toLowercaseSeparator(key: string) {
|
||||
// return key.replace(/([A-Z])/g, '-$1').toLowerCase();
|
||||
// }
|
||||
|
||||
/**
|
||||
* 将字符串转换为指定连接符的命名约定
|
||||
* @param str 要转换的字符串
|
||||
* @param separator 指定的连接符,默认为 "-"
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
export function kebabCase(str: string, separator: string = "-"): string {
|
||||
return str
|
||||
.replace(/[A-Z]/g, match => `${separator}${match.toLowerCase()}`) // 将大写字母替换为连接符加小写字母
|
||||
.replace(/[\s_-]+/g, separator) // 将空格、下划线和短横线替换为指定连接符
|
||||
.replace(new RegExp(`^${separator}|${separator}$`, "g"), "") // 删除开头和结尾的连接符
|
||||
.toLowerCase(); // 将结果转换为全小写
|
||||
}
|
||||
83
src/uni_modules/lime-shared/package.json
Normal file
83
src/uni_modules/lime-shared/package.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"id": "lime-shared",
|
||||
"displayName": "lime-shared",
|
||||
"version": "0.1.4",
|
||||
"description": "本人插件的几个公共函数,获取当前页,图片的base64转临时路径,图片的exif信息等",
|
||||
"keywords": [
|
||||
"lime-shared",
|
||||
"exif",
|
||||
"selectComponent"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "sdk-js",
|
||||
"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": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "y",
|
||||
"快手": "y",
|
||||
"飞书": "y",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
121
src/uni_modules/lime-shared/pathToBase64/index.ts
Normal file
121
src/uni_modules/lime-shared/pathToBase64/index.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
// @ts-nocheck
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
import { getLocalFilePath } from '../getLocalFilePath'
|
||||
// #endif
|
||||
function isImage(extension : string) {
|
||||
const imageExtensions = ["jpg", "jpeg", "png", "gif", "bmp", "svg"];
|
||||
return imageExtensions.includes(extension.toLowerCase());
|
||||
}
|
||||
// #ifdef H5
|
||||
function getSVGFromURL(url: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
xhr.responseType = 'text';
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200) {
|
||||
const svg = xhr.responseText;
|
||||
resolve(svg);
|
||||
} else {
|
||||
reject(new Error(xhr.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function () {
|
||||
reject(new Error('Network error'));
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
/**
|
||||
* 路径转base64
|
||||
* @param {Object} string
|
||||
*/
|
||||
export function pathToBase64(path : string) : Promise<string> {
|
||||
if (/^data:/.test(path)) return path
|
||||
let extension = path.substring(path.lastIndexOf('.') + 1);
|
||||
const isImageFile = isImage(extension)
|
||||
let prefix = ''
|
||||
if (isImageFile) {
|
||||
prefix = 'image/';
|
||||
if(extension == 'svg') {
|
||||
extension += '+xml'
|
||||
}
|
||||
} else if (extension === 'pdf') {
|
||||
prefix = 'application/pdf';
|
||||
} else if (extension === 'txt') {
|
||||
prefix = 'text/plain';
|
||||
} else {
|
||||
// 添加更多文件类型的判断
|
||||
// 如果不是图片、PDF、文本等类型,可以设定默认的前缀或采取其他处理
|
||||
prefix = 'application/octet-stream';
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef H5
|
||||
if (isImageFile) {
|
||||
if(extension == 'svg') {
|
||||
getSVGFromURL(path).then(svg => {
|
||||
const base64 = btoa(svg);
|
||||
resolve(`data:image/svg+xml;base64,${base64}`);
|
||||
})
|
||||
} else {
|
||||
let image = new Image();
|
||||
image.setAttribute("crossOrigin", 'Anonymous');
|
||||
image.onload = function () {
|
||||
let canvas = document.createElement('canvas');
|
||||
canvas.width = this.naturalWidth;
|
||||
canvas.height = this.naturalHeight;
|
||||
canvas.getContext('2d').drawImage(image, 0, 0);
|
||||
let result = canvas.toDataURL(`${prefix}${extension}`)
|
||||
resolve(result);
|
||||
canvas.height = canvas.width = 0
|
||||
}
|
||||
image.src = path + '?v=' + Math.random()
|
||||
image.onerror = (error) => {
|
||||
reject(error);
|
||||
};
|
||||
}
|
||||
|
||||
} else {
|
||||
reject('not image');
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
if (uni.canIUse('getFileSystemManager')) {
|
||||
uni.getFileSystemManager().readFile({
|
||||
filePath: path,
|
||||
encoding: 'base64',
|
||||
success: (res) => {
|
||||
resolve(`data:${prefix}${extension};base64,${res.data}`)
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error({ error, path })
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), (entry) => {
|
||||
entry.file((file : any) => {
|
||||
const fileReader = new plus.io.FileReader()
|
||||
fileReader.onload = (data) => {
|
||||
resolve(data.target.result)
|
||||
}
|
||||
fileReader.onerror = (error) => {
|
||||
console.error({ error, path })
|
||||
reject(error)
|
||||
}
|
||||
fileReader.readAsDataURL(file)
|
||||
}, reject)
|
||||
}, reject)
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
2320
src/uni_modules/lime-shared/piexif/index.ts
Normal file
2320
src/uni_modules/lime-shared/piexif/index.ts
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user