作者 徐浩

20240621记录代买

正在显示 59 个修改的文件 包含 2115 行增加627 行删除
<script>
import Vue from 'vue'
import { update } from "@/common/uitls.js"
import {
mapState,
mapMutations
} from 'vuex'
var that
export default {
onLaunch: function() {
that=this
console.log('App Launch')
... ... @@ -26,7 +28,17 @@
// })
// }
// }
// 拦截页面跳转并检查更新
// #ifdef APP-PLUS
uni.addInterceptor('navigateTo', {
success() {
const currentPage = (getCurrentPages()).map(item => item.route);
if(!currentPage.includes('pages/update/update')){
update()
}
}
})
// #endif
uni.getSystemInfo({
success: function(e) {
that.$store.commit('setplatform',e.platform)
... ...
export const ENV = 'dev'
export const REFERER = (() => {
if(ENV === 'dev') {
return 'https://edudev.baoshanjiaoyu.com/'
}
})()
\ No newline at end of file
... ...
import service from "@/common/service.js"
/**
* @description: 版本判断以及更新逻辑
* @param {Object} obj
* @author: xuhao
*/
export async function update() {
await inspectApk()
await inspectWgt()
}
// 检查是否有apk包更新
function inspectApk() {
return new Promise((req, err) => {
let version = plus.runtime.version
// let version = '1.0.0'
console.log('version', version)
service.P_post('/version/index', {
client: uni.getSystemInfoSync().platform,
version: version
}).then(res => {
if(res.msg.version) {
uni.navigateTo({
url: '/pages/update/update'
})
err()
} else {
req()
}
})
})
}
// 检查是否有wgt包更新
function inspectWgt() {
return new Promise((req, err) => {
plus.runtime.getProperty(plus.runtime.appid, (widgetInfo) => {
let version = widgetInfo.version
console.log('version', version)
service.P_post('/version/index', {
client: uni.getSystemInfoSync().platform,
version: version
}).then(res => {
if(res.msg.version) {
wgtUpdate(res.msg.url)
err()
} else {
req()
}
})
})
})
}
/**
* 热更新逻辑
*/
function wgtUpdate(url) {
// 检查是否正在更新
if(uni.getStorageSync('updatingInProgress')){
return
}
uni.setStorageSync('updatingInProgress', true)
let urlSystem = uni.getStorageSync('url')
const downloadTask = uni.downloadFile({
url: urlSystem + '/app/renew/download?filename=' + url,
success: (downloadResult) => {
if (downloadResult.statusCode === 200) {
plus.runtime.install(downloadResult.tempFilePath, {
force: true
}, function() {
console.log('install success...');
plus.runtime.restart();
}, function(e) {
console.error('install fail...', e);
},);
}
},
complete: () => {
uni.removeStorageSync('updatingInProgress')
}
});
var showLoading = plus.nativeUI.showWaiting("正在更新", {
back: "none"
});
downloadTask.onProgressUpdate((res) => {
showLoading.setTitle("正在更新" + res.progress + "% ");
if (res.progress == 100) {
plus.nativeUI.closeWaiting();
}
})
}
\ No newline at end of file
... ...
<template>
<view class="Countdown">
<view v-if="remainingTime === 0" @click="startCountdown">获取验证码</view>
<view v-else>{{ remainingTime }}s 后重新获取</view>
</view>
</template>
<script>
export default {
name: 'Countdown',
data() {
return {
remainingTime: 0,
timer: null
}
},
methods: {
startCountdown() {
this.$emit('start')
},
start() {
this.remainingTime = 60;
this.timer = setInterval(() => {
this.remainingTime--;
if (this.remainingTime === 0) {
clearInterval(this.timer);
}
}, 1000);
}
},
beforeDestroy() {
clearInterval(this.timer);
}
}
</script>
<style lang="scss" scoped>
.Countdown{
font-size: 26rpx;
}
</style>
\ No newline at end of file
... ...
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<view class="CustomReturn-container" :style="{height: titleHeight, paddingTop: paddingTop, backgroundColor: bgColor}">
<view class="CustomReturn">
<view v-if="isShowBreak" class="CustomReturn-r">
... ... @@ -17,7 +16,6 @@
<slot></slot>
</view>
</view>
<!-- #endif -->
</view>
... ... @@ -112,10 +110,11 @@
this.paddingTop = uni.getSystemInfoSync().statusBarHeight + 'px'
// #ifdef MP-WEIXIN
let res = wx.getMenuButtonBoundingClientRect();
// #endif
this.paddingTop = res.top + 'px'
this.titleHeight = res.height + 10 + 'px';
this.entityHeight = res.top + res.height
// #endif
},
toBreak(){
... ...
... ... @@ -39,15 +39,16 @@
},
methods:{
setOtherHeight(height) {
// #ifdef APP-PLUS
let paddingTop = uni.getSystemInfoSync().statusBarHeight
let titleHeight = 88 + 'rpx';
// #endif
// #ifdef MP-WEIXIN
let res = wx.getMenuButtonBoundingClientRect();
let paddingTop = res.top;
let titleHeight = res.height + 10 + 'px';
// #endif
let paddingTop = res.top
let titleHeight = res.height + 10;
this.PaddingTop = `calc(${paddingTop + titleHeight}px + ${height + this.otherUnit})`
// this.PaddingTop = `calc(${uni.getSystemInfoSync().statusBarHeight}px + ${height}rpx + 88rpx + 5px)`
this.PaddingTop = `calc(${paddingTop}px + ${titleHeight} + ${height + this.otherUnit})`
}
}
}
... ...
<template>
<u-popup :show="show" :round="10" mode="bottom">
<view class="UserAgreement">
<view class="UserAgreement-top">
<view class="UserAgreement-top-content">隐私政策</view>
</view>
<scroll-view :scroll-y="true" style="height: 60vh;">
<view class="UserAgreement-body" v-html="content"></view>
</scroll-view>
<view class="UserAgreement-bottom-container">
<view class="UserAgreement-bottom" @click="cancel">
知道了
</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
name:"UserAgreement",
data() {
return {
show: false,
title: '',
content: ''
};
},
mounted() {
},
methods: {
getData() {
this.$service.P_get('config/policy').then(res => {
console.log('=======>', res)
this.content = res.data.content
})
},
open() {
this.getData()
this.show = true
},
cancel(){
this.show = false
this.$emit('cancel')
},
close() {
this.show = false
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.UserAgreement{
padding: 0 40rpx;
background-color: #fff;
border-radius: 20rpx;
text-align: left;
.UserAgreement-top{
text-align: center;
padding: 49rpx 0;
display: flex;
justify-content: center;
.UserAgreement-top-content{
position: relative;
font-size: 32rpx;
color: #323232;
}
}
.UserAgreement-body{
color: #646464;
font-size: 28rpx;
overflow: auto;
padding-bottom: 20rpx;
}
.UserAgreement-bottom-container{
display: flex;
justify-content: space-between;
.UserAgreement-bottom{
line-height: 90rpx;
font-size: 34rpx;
color: #FFFFFF;
background-color: #2d81ff;
border-radius: 500rpx;
text-align: center;
margin-top: 40rpx;
margin-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
width: 100%;
}
.UserAgreement-bottom-2{
color: rgba(100, 100, 100, 1);
line-height: 90rpx;
font-size: 34rpx;
background-color: rgba(239, 239, 239, 1);
border-radius: 500rpx;
text-align: center;
margin-top: 40rpx;
margin-bottom: 30rpx;
width: 300rpx;
}
}
}
</style>
\ No newline at end of file
... ...
<template>
<view>
<view class="Protocol" @click="select">
<u-checkbox-group v-model="checked">
<u-checkbox shape="circle" label=" " :name="1"></u-checkbox>
</u-checkbox-group>
<view>
我已阅读并同意<text style="color: #2d81ff;" @tap.stop ="openYonghu">《用户协议》</text>和<text style="color: #2d81ff;" @tap.stop="openYinSi">《隐私政策》</text>
</view>
</view>
<UserAgreementPop ref="userAgreementPopRef" />
<PrivacyPolicyPop ref="privacyPolicyPopRef" />
</view>
</template>
<script>
import UserAgreementPop from "@/components/UserAgreementPop/index.vue"
import PrivacyPolicyPop from "@/components/PrivacyPolicyPop/index.vue"
export default {
name: 'Protocol',
components: {
UserAgreementPop,
PrivacyPolicyPop
},
computed: {
checked: {
get() {
if(!this.value) {
return []
} else {
return [1]
}
},
set(val) {
console.log(val)
if(val.length) {
this.$emit('input', true)
} else {
this.$emit('input', false)
}
}
}
},
model: {
event: 'input',
prop: 'value'
},
props: {
value: {
type: Boolean,
default: false
}
},
data() {
return {
}
},
methods: {
openYinSi() {
this.$refs.privacyPolicyPopRef.open()
},
openYonghu() {
this.$refs.userAgreementPopRef.open()
},
select() {
if(this.checked.length) {
this.checked = []
} else {
this.checked = [1]
}
}
}
}
</script>
<style lang="scss" scoped>
.Protocol{
display: flex;
align-items: center;
font-size: 26rpx;
}
</style>
\ No newline at end of file
... ...
<template>
<u-popup :show="show" :round="10" mode="bottom">
<view class="UserAgreement">
<view class="UserAgreement-top">
<view class="UserAgreement-top-content">用户协议</view>
</view>
<scroll-view :scroll-y="true" style="height: 60vh;">
<view class="UserAgreement-body" v-html="content"></view>
</scroll-view>
<view class="UserAgreement-bottom-container">
<view class="UserAgreement-bottom" @click="cancel">
知道了
</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
name:"UserAgreement",
data() {
return {
show: false,
title: '',
content: ''
};
},
mounted() {
},
methods: {
getData() {
this.$service.P_get('config/agreement').then(res => {
console.log('=======>', res)
this.content = res.data.content
})
},
open() {
this.getData()
this.show = true
},
cancel(){
this.show = false
this.$emit('cancel')
},
close() {
this.show = false
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.UserAgreement{
padding: 0 40rpx;
background-color: #fff;
border-radius: 20rpx;
text-align: left;
.UserAgreement-top{
text-align: center;
padding: 49rpx 0;
display: flex;
justify-content: center;
.UserAgreement-top-content{
position: relative;
font-size: 32rpx;
color: #323232;
}
}
.UserAgreement-body{
color: #646464;
font-size: 28rpx;
overflow: auto;
padding-bottom: 20rpx;
}
.UserAgreement-bottom-container{
display: flex;
justify-content: space-between;
.UserAgreement-bottom{
line-height: 90rpx;
font-size: 34rpx;
color: #FFFFFF;
background-color: #2d81ff;
border-radius: 500rpx;
text-align: center;
margin-top: 40rpx;
margin-bottom: calc(env(safe-area-inset-bottom) + 30rpx);
width: 100%;
}
.UserAgreement-bottom-2{
color: rgba(100, 100, 100, 1);
line-height: 90rpx;
font-size: 34rpx;
background-color: rgba(239, 239, 239, 1);
border-radius: 500rpx;
text-align: center;
margin-top: 40rpx;
margin-bottom: 30rpx;
width: 300rpx;
}
}
}
</style>
\ No newline at end of file
... ...
... ... @@ -11,6 +11,7 @@
<script>
export default {
name: 'VoicePlayback',
data() {
return {
audioContext: null,
... ... @@ -40,7 +41,7 @@
this.duration = duration
},
init({ url, duration }) {
this.audioContext = wx.createInnerAudioContext();
this.audioContext = uni.createInnerAudioContext();
this.audioContext.src = url
this.audioContext.onPlay(() => {
this.isPlay = true
... ... @@ -50,6 +51,7 @@
});
this.audioContext.onEnded(() => {
this.audioContext.stop()
this.init({ url, duration })
})
this.audioContext.onStop(() => {
this.isPlay = false
... ...
<template>
<view class="qxcplayer-box" :style="'height:' + height + 'rpx'">
<video id="qxc_player" class="qxc-video" :src="playUrl"
autoplay="" @play="videoPlay()" @pause="videoPause()" @timeupdate="videoTimeUpdate"
@error="videoError"
referrer-policy="origin"
@controlstoggle="controlstoggle"
@fullscreenchange="fullScreenChange"
:custom-cache="false"
>
<video id="qxc_player" class="qxc-video" :src="playUrl" autoplay="" @play="videoPlay()" @pause="videoPause()"
@timeupdate="videoTimeUpdate" @error="videoError" :header="{'Referer':REFERER}" referrer-policy="origin"
@controlstoggle="controlstoggle" @fullscreenchange="fullScreenChange" :custom-cache="false">
<view :class="fullScreen? 'controller-top controller-top-nobg': 'controller-top'" v-if="topShow">
<text class="speed-txt" @click="speedTap">X {{speedVal}}</text>
</view>
<cover-image v-if="!isPlay && topShow" @click="centerPlayClick" src="../../static/qxc_play.png" :class="fullScreen ? 'centerbtn-fullscreen' : 'centerbtn'"></cover-image>
<cover-image v-if="isPlay && topShow" @click="centerPauseClick" src="../../static/qxc_pause.png" :class="fullScreen ? 'centerbtn-fullscreen' : 'centerbtn'"></cover-image>
<cover-image v-if="!isPlay && topShow" @click="centerPlayClick" src="../../static/qxc_play.png"
:class="fullScreen ? 'centerbtn-fullscreen' : 'centerbtn'"></cover-image>
<cover-image v-if="isPlay && topShow" @click="centerPauseClick" src="../../static/qxc_pause.png"
:class="fullScreen ? 'centerbtn-fullscreen' : 'centerbtn'"></cover-image>
<SpeedView @speedChange="speedChange" ref="speedBox" class="speed-box"></SpeedView>
</video>
</view>
... ... @@ -21,11 +18,16 @@
<script>
import QXCMiniPlayerSDK from './lib/qxcplaysdk.es'
import SpeedView from './speed/speedview.vue'
let qxcplayerSDK = null
import {
REFERER
} from "@/common/config.js"
let qxcplayerSDK = null
let videoCtx = null
export default {
name:"qxcplayer",
components: {SpeedView},
name: "qxcplayer",
components: {
SpeedView
},
props: {
height: {
type: Number,
... ... @@ -34,6 +36,7 @@
},
data() {
return {
REFERER,
count: 0,
isPlay: false,
showControls: true,
... ... @@ -50,7 +53,8 @@
videoCtx = uni.createVideoContext('qxc_player', this)
},
methods: {
setTime: function(time) {/*设置视频初始化播放位置 参数 第一个 时间*/
setTime: function(time) {
/*设置视频初始化播放位置 参数 第一个 时间*/
let that = this;
if (time && time > 0) {
videoCtx.seek(time);
... ... @@ -60,91 +64,89 @@
console.log('V1.0.0')
qxcplayerSDK = new QXCMiniPlayerSDK({
data: {
token: params.token,
// 用户名,可不填
name: params.name,
// 环境 test 测试环境 product 正式环境 默认是正式环境
env: params.env,
logLeve: 0,
isWx: true
token: params.token,
// 用户名,可不填
name: params.name,
// 环境 test 测试环境 product 正式环境 默认是正式环境
env: params.env,
logLeve: 0,
isWx: true
},
playerCallback: {
onConnectResult: (type, reason) => {
},
onDuplicateLoginKickOut: () => {
// 异地登录
this.playUrl = ''
uni.showToast({
title: '异地登录' + this.count,
icon:'error',
duration: 2000
});
},
onPlayUrl: (url, time) => {
// uni.showToast({
// title: 'onPlayUrl' + url,
// icon: 'none'
// })
this.playUrl = url
videoCtx.seek(time)
},
onLineList: (linelist) => {
},
onPlayerInfo: (title, total) => {
},
onMediaError: (code, msg) => {
uni.showToast({
title: msg + "#" + code,
icon:'error',
duration: 2000
});
}
}
onConnectResult: (type, reason) => {},
onDuplicateLoginKickOut: () => {
// 异地登录
this.playUrl = ''
uni.showToast({
title: '异地登录' + this.count,
icon: 'error',
duration: 2000
});
},
onPlayUrl: (url, time) => {
// console.log(url)
// uni.showToast({
// title: 'onPlayUrl' + url,
// icon: 'none'
// })
this.playUrl = url
videoCtx.seek(time)
},
onLineList: (linelist) => {},
onPlayerInfo: (title, total) => {},
onMediaError: (code, msg) => {
uni.showToast({
title: msg + "#" + code,
icon: 'error',
duration: 2000
});
}
}
})
qxcplayerSDK.connect()
this.count = this.count + 1
console.log('mgs: initData', this.count)
},
videoPlay: function () {
videoPlay: function() {
this.isPlay = true
},
videoPause: function () {
videoPause: function() {
this.isPlay = false
},
videoTimeUpdate: function (e) {
videoTimeUpdate: function(e) {
qxcplayerSDK.setCurTime(Math.floor(e.detail.currentTime))
this.VVideo.curTime = e.detail.currentTime
},
videoError: function (e) {
console.log(e)
videoError: function(e) {
console.log('=========>', e)
uni.showToast({
title: '播放失败' + this.count,
icon:'error',
icon: 'error',
duration: 2000
});
this.isPlay = false
},
speedTap: function (e) {
speedTap: function(e) {
this.$refs.speedBox.setShow()
},
speedChange: function (val) {
speedChange: function(val) {
videoCtx.playbackRate(Number(val))
this.speedVal = val
},
controlstoggle: function (e) {
let show = e.detail.show
this.topShow = show
controlstoggle: function(e) {
let show = e.detail.show
this.topShow = show
},
fullScreenChange: function(e) {
this.fullScreen = e.detail.fullScreen
},
fullScreenChange: function (e) {
this.fullScreen = e.detail.fullScreen
centerPlayClick: function() {
if (videoCtx) videoCtx.play()
},
centerPlayClick: function () {
if (videoCtx) videoCtx.play()
},
centerPauseClick: function () {
if (videoCtx) videoCtx.pause()
},
destory: function () {
centerPauseClick: function() {
if (videoCtx) videoCtx.pause()
},
destory: function() {
this.playUrl = ''
qxcplayerSDK.release()
}
... ... @@ -153,56 +155,58 @@
</script>
<style scoped>
.qxcplayer-box{
position: relative;
width: 100%;
.qxcplayer-box {
position: relative;
width: 100%;
}
.qxc-video{
width: 100%;
height: 100%;
.qxc-video {
width: 100%;
height: 100%;
}
.controller-top{
width: 100%;
height: 30rpx;
position: fixed;
top: 0rpx;
display: flex;
flex-direction: row-reverse;
background: rgba(0, 0, 0, 0.3);
padding-top: 20rpx;
.controller-top {
width: 100%;
height: 30rpx;
position: fixed;
top: 0rpx;
display: flex;
flex-direction: row-reverse;
background: rgba(0, 0, 0, 0.3);
padding-top: 20rpx;
}
.controller-top-nobg{
background: rgba(0, 0, 0, 0.0);
.controller-top-nobg {
background: rgba(0, 0, 0, 0.0);
}
.speed-txt{
color: white;
font-size: 10pt;
pointer-events: all;
margin-right: 40rpx;
padding: 2rpx;
.speed-txt {
color: white;
font-size: 10pt;
pointer-events: all;
margin-right: 40rpx;
padding: 2rpx;
}
.centerbtn{
position: absolute;
width: 30rpx;
height: 30rpx;
top: calc(200rpx - 37rpx);
left: calc(50% - 30rpx);
background-color: rgba(0, 0, 0, 0.2);
border-radius: 50%;
padding: 20rpx;
.centerbtn {
position: absolute;
width: 30rpx;
height: 30rpx;
top: calc(200rpx - 37rpx);
left: calc(50% - 30rpx);
background-color: rgba(0, 0, 0, 0.2);
border-radius: 50%;
padding: 20rpx;
}
.centerbtn-fullscreen{
position: absolute;
width: 30rpx;
height: 30rpx;
top: calc(50% - 37rpx);
left: calc(50% - 30rpx);
background-color: rgba(0, 0, 0, 0.2);
border-radius: 50%;
padding: 20rpx;
.centerbtn-fullscreen {
position: absolute;
width: 30rpx;
height: 30rpx;
top: calc(50% - 37rpx);
left: calc(50% - 30rpx);
background-color: rgba(0, 0, 0, 0.2);
border-radius: 50%;
padding: 20rpx;
}
</style>
\ No newline at end of file
... ...
... ... @@ -70,15 +70,23 @@
currentTime:0,
playState:"pause",//"loading"/"playing"/"pause"
isSliderChanging:false,
backgroundAudioManager: wx.getBackgroundAudioManager()
backgroundAudioManager: uni.getBackgroundAudioManager()
};
},
mounted: function(){
if(this.autoplay) {
// this.play()
}
},
destroyed() {
console.log('destroyed')
this.stop()
},
methods:{
stop() {
this.backgroundAudioManager.stop()
},
previousSong() {
this.$emit('previousSong')
},
... ... @@ -90,8 +98,19 @@
this.$refs.NotificationD.show = false
},
setSrc(src) {
this.src = src
this.play()
this.src = 'https://edudev.baoshanjiaoyu.com/code.mp3'
this.backgroundAudioManager.title = this.title;//
this.backgroundAudioManager.epname = this.epname;//
this.backgroundAudioManager.singer = this.singer;//
this.backgroundAudioManager.src = this.src
this.backgroundAudioManager.onPlay(this.playerOnPlay)
// this.setProgress(10)
this.backgroundAudioManager.onEnded(this.playerOnEnded)
this.backgroundAudioManager.onError(this.playerOnError)
// #ifdef APP-PLUS
this.backgroundAudioManager.play()
// #endif
// this.play()
},
openNotificationD() {
this.$refs.NotificationD.show = true
... ... @@ -113,6 +132,8 @@
playerOnEnded:function(e)
{
this.playState="pause";
console.log('playerOnEnded')
// this.backgroundAudioManager.stop()
this.$emit("ended");
},
playerOnTimeupdate:function(e)
... ... @@ -128,6 +149,7 @@
},
playerOnError:function(e)
{
console.log(e)
uni.showToast({
title:"播放出错"+e
});
... ... @@ -150,14 +172,16 @@
return `${m}:${s}`;
},
play:function(){
console.log('=======》')
// #ifdef MP-WEIXIN
this.backgroundAudioManager.title = this.title;//
this.backgroundAudioManager.epname = this.epname;//
this.backgroundAudioManager.singer = this.singer;//
this.backgroundAudioManager.src = this.src
this.backgroundAudioManager.onPlay(this.playerOnPlay)
// this.setProgress(10)
this.backgroundAudioManager.onEnded(this.playerOnEnded)
this.backgroundAudioManager.onError(this.playerOnError)
// #endif
// #ifdef APP-PLUS
this.backgroundAudioManager.play()
// #endif
},
pause:function(){
this.backgroundAudioManager.pause();
... ... @@ -184,4 +208,7 @@
<style lang="scss">
@import './index.scss';
.imt-audio-2{
margin-top: 100rpx;
}
</style>
... ...
{
"name" : "teaching",
"appid" : "__UNI__C551C4D",
"name" : "中志云校园",
"appid" : "__UNI__8740A53",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"versionCode" : 20240619,
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
... ... @@ -17,7 +17,10 @@
"delay" : 0
},
/* 模块配置 */
"modules" : {},
"modules" : {
"OAuth" : {},
"VideoPlayer" : {}
},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
... ... @@ -41,9 +44,49 @@
]
},
/* ios打包配置 */
"ios" : {},
"ios" : {
"dSYMs" : false
},
/* SDK配置 */
"sdkConfigs" : {}
"sdkConfigs" : {
"payment" : {},
"oauth" : {
"univerify" : {}
},
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* 快应用特有相关 */
... ... @@ -51,11 +94,12 @@
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "wx5bbc433d447d1a86",
"permissions": {
"scope.record": {
"desc": "用于录制音频"
}
},
"requiredBackgroundModes" : [ "audio", "location" ],
"permissions" : {
"scope.record" : {
"desc" : "用于录制音频"
}
},
"setting" : {
"urlCheck" : false,
"es6" : true
... ...
... ... @@ -6,7 +6,7 @@
<view class="oneSettingV2-c-1-l">头像</view>
<view class="oneSettingV2-c-1-r">
<avatar selWidth="100rpx" selHeight="100rpx" @upload="myUpload"
:avatarSrc="userdata.img?$service.getimg(userdata.img):'/static/images/tx.png'"
:avatarSrc="userdata.img_url ? $service.getimg(userdata.img_url):'/static/images/tx.png'"
avatarStyle="width: 100rpx;height: 100rpx;border-radius: 50%;" inner=true></avatar>
</view>
</view>
... ...
... ... @@ -45,7 +45,7 @@
<view class="myQuestion-2-i-3-c-1">
<view class="myQuestion-2-i-3-c-1-l">
<view class="myQuestion-2-i-3-c-1-l-i">
<image :src="info.lecturer.img_url || '/static/images/tx.png'" mode="widthFix"></image>
<image :src="info.lecturer ? info.lecturer.img_url : '/static/images/tx.png'" mode="widthFix"></image>
</view>
<text class="myQuestion-2-i-3-c-1-l-t">{{info.lecturer.title}}老师回复</text>
</view>
... ... @@ -317,6 +317,10 @@
height: 48rpx;
width: 48rpx;
border-radius: 200rpx;
image{
height: 100%;
width: 100%;
}
}
.myQuestion-2-i-3-c-1-l-t{
font-size: 26rpx;
... ...
... ... @@ -27,6 +27,7 @@
import MarkReadPop from "../MarkReadPop/index.vue"
import InfoPop from "../InfoPop/index.vue"
import { READINGSTATUS } from "../../emit.js"
import { GENDER } from "@/emit/index.js"
export default {
name: 'ListItem',
props: {
... ... @@ -43,6 +44,7 @@
},
data() {
return {
GENDER,
READINGSTATUS
}
},
... ... @@ -75,7 +77,6 @@
.ListItem-t-l {
display: flex;
align-items: center;
.ListItem-t-l-1 {
font-size: 30rpx;
color: #3D4054;
... ...
... ... @@ -84,7 +84,25 @@
"navigationStyle": "custom"
}
}
},
{
"path" : "pages/update/update",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom",
"app-plus": {
"animationType": "fade-in", // 设置fade-in淡入动画,为最合理的动画类型
"background": "transparent", // 背景透明
"backgroundColor": "transparent", // 背景透明
"webviewBGTransparent":true,
"mask":"none",
"popGesture": "none" // 关闭IOS屏幕左边滑动关闭当前页面的功能
}
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
... ...
... ... @@ -249,6 +249,9 @@
}
&:last-child{
padding-right: 0;
&:before{
border-left: none;
}
}
}
}
... ...
... ... @@ -56,6 +56,10 @@
.UserMenu-i-1{
height: 74rpx;
width: 74rpx;
image{
height: 100%;
width: 100%;
}
}
.UserMenu-i-2{
font-size: 24rpx;
... ...
... ... @@ -78,135 +78,6 @@
</view>
</view>
</view>
<view v-if="userDatas" class="header-wrap">
<view class="study-report area">
<image class="study-report-icon" src="@/static/images/xh_icon3.png"></image>
<text>学习报告:{{userDatas.name||''}}</text>
</view>
<view class="study-report-wrap area">
<view class="credit-wrap flex">
<view class="credit-item flex" @tap="$sjuNav.navigateTo(`/pagesB/oneMyCredit/oneMyCredit`,{credit})">
<view class="credit-num">
{{userDatas.credit||''}}
</view>
<view>
我的学分
</view>
</view>
<view class="credit-item flex">
<view class="percentage-num">
{{userDatas.pm_num||''}}
</view>
<view>
<!-- {{userDatas.pm_title||''}} <text>(排名)</text> -->
模拟全校排名
</view>
</view>
</view>
<view class="matter-wrap flex">
<view class="matter-item flex">
<view class="second-num">
{{userDatas.leave_num||'0'}}
</view>
<view class="">
<!-- <text class="leave"></text> -->
请假
</view>
</view>
<view class="matter-item flex">
<view class="second-num">
{{userDatas.late_num||'0'}}
</view>
<view class="">
<!-- <text class="leave2"></text> -->
迟到
</view>
</view>
<view class="matter-item flex">
<view class="second-num">
{{userDatas.truancy_num||'0'}}
</view>
<view class="">
<!-- <text class="leave3"></text> -->
旷课
</view>
</view>
<view class="matter-item flex">
<view class="second-num">
{{userDatas.nophone_num||'0'}}
</view>
<view class="">
<!-- <text class="leave4"></text> -->
未交手机
</view>
</view>
</view>
</view>
</view>
<!-- 说明内容 -->
<view class="explain">
模块正确率达到上岸基准线,对应模块徽章将被点亮。全部
徽章点亮即可凭荣誉勋章截图到学生服务中心领取奖品1份!
</view>
<!-- 勋章墙 -->
<view class="medalWall">
<view class="medalWall-Item" v-for="item in medalList" :key="item.id">
<view class="medalWall-Item-icon">
<image src="@/static/images/xh_icon1.png" v-if="item.is_light"></image>
<image src="@/static/images/xh_icon2.png" v-else></image>
</view>
<view class="medalWall-Item-text">{{ item.name }}</view>
</view>
</view>
<!--
菜单2.0
author: xuhao
date: 2023.02.20
-->
<view class="menu area">
<view class="menu-item" @tap="go_txz">
<view class="menu-item-icon">
<image src="@/static/images/xh_icon4.png"></image>
</view>
<view class="menu-item-text">走读通行证</view>
</view>
<view class="menu-item" @click="$service.jump" data-url="/pagesB/oneRanking/oneRanking">
<view class="menu-item-icon">
<image src="@/static/images/xh_icon5.png"></image>
</view>
<view class="menu-item-text">班级考勤排名</view>
</view>
<view class="menu-item" @click="$service.jump" data-url="/pagesB/oneLeave/oneLeave">
<view class="menu-item-icon">
<image src="@/static/images/xh_icon6.png"></image>
</view>
<view class="menu-item-text">请假申请</view>
</view>
<view class="menu-item" @click="$service.jump" data-url="/pagesB/notHand/notHand">
<view class="menu-item-icon">
<image src="@/static/images/xh_icon7.png"></image>
</view>
<view class="menu-item-text">不交手机申请</view>
</view>
<view class="menu-item" @click="$service.jump" data-url="/pagesStu/sq_list/sq_list">
<view class="menu-item-icon">
<image src="@/static/images/xh_icon8.png"></image>
</view>
<view class="menu-item-text">申请审批结果</view>
</view>
<view class="menu-item" @click="$service.jump" data-url="/pages_v2/stu_jspf_index/stu_jspf_index">
<view class="menu-item-icon">
<image src="@/static/images/xh_icon9.png"></image>
</view>
<view class="menu-item-text">评价反馈</view>
</view>
<view class="menu-item" @click="$service.jump" data-url="/page_admin/praise_andLike/praise_andLike">
<view class="menu-item-icon">
<image src="@/static/images/admin/icon5.png"></image>
</view>
<view class="menu-item-text">点赞表扬</view>
</view>
</view>
<PopupA ref="popupARef"/>
<HonorWall ref="honorWallRef" :dataList="medalList" />
</view>
... ... @@ -493,6 +364,7 @@
position: relative;
.contentV2-1-bg{
height: 375rpx;
width: 100%;
box-sizing: border-box;
}
.contentV2-1-c{
... ...
... ... @@ -10,6 +10,7 @@
<script>
import Vue from 'vue'
import { update } from "@/common/uitls.js"
import {
mapState,
mapMutations
... ... @@ -41,6 +42,9 @@
// url:'/new_tec/homePage/homePage'
// })
// return
// #ifdef APP-PLUS
update()
// #endif
if(identity==2){
uni.reLaunch({
url:'/pages/tch_index/tch_index'
... ... @@ -49,6 +53,10 @@
uni.switchTab({
url:'/pages/index/index'
})
} else if(identity==4){
uni.reLaunch({
url:'/new_tec/homePage/homePage'
})
} else {
uni.reLaunch({
url:'/pages/admin_index/admin_index'
... ...
<template>
<view class="oneSubmitted">
<CustomReturn bgColor="none" title="登录"/>
<CustomReturn bgColor="none" title="登录" />
<view class="oneSubmitted-v2">
<image class="oneSubmitted-v2-bg" src="@/static/imagesV2/icon29.png" mode="widthFix"></image>
<PaddingTopB>
... ... @@ -9,6 +9,7 @@
<image class="oneSubmitted-v2-1-i" src="@/static/imagesV2/icon68.png" mode="widthFix"></image>
</view>
<view class="oneSubmitted-v2-2">
<view class="oneSubmitted-v2-2-1" @click="openMajor">
<view class="oneSubmitted-v2-2-1-l">
<text style="color: #979797;" v-if="!school.id">请选择学校</text>
... ... @@ -16,23 +17,65 @@
</view>
<u-icon name="arrow-down-fill" size="10"></u-icon>
</view>
<view class="oneSubmitted-v2-2-2" v-if="!school.id" @click="prompt">
登录
<!-- #ifdef APP-PLUS -->
<view class="oneSubmitted-v2-2-1">
<input v-model="phoneNumber" class="oneSubmitted-v2-2-1-i" type="text"
placeholder="请输入账号/手机号" />
</view>
<view class="oneSubmitted-v2-2-1" style="margin-bottom: 20rpx;"
v-if="loginType === LOGINMETHOD.CODE">
<input class="oneSubmitted-v2-2-1-i" type="text" v-model="code" placeholder="请输入验证码" />
<view class="oneSubmitted-v2-2-1-r">
<Countdown ref="countdownRef" @start="sendCode" />
</view>
</view>
<view class="oneSubmitted-v2-2-1" style="margin-bottom: 20rpx;" v-else>
<input class="oneSubmitted-v2-2-1-i" type="text" v-if="isPlaintext" v-model="password" placeholder="请输入密码" />
<input class="oneSubmitted-v2-2-1-i" type="password" v-else v-model="password" placeholder="请输入密码" />
<view @click="changePlaintext">
<u-icon name="eye-off" v-if="isPlaintext" color="#BDBDBD" size="20"></u-icon>
<u-icon name="eye-fill" v-else color="#BDBDBD" size="20"></u-icon>
</view>
</view>
<button class="oneSubmitted-v2-2-2" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber" v-else>
登录
</button>
<view class="oneSubmitted-v2-2-3">
本小程序为中志教育内部系统,不对外开放
<view class="oneSubmitted-v2-2-c" @click="">
<text v-if="loginType === LOGINMETHOD.CODE"
@click="changeLoginType(LOGINMETHOD.PASSWORDLOGIN)">密码登录</text>
<text v-else @click="changeLoginType(LOGINMETHOD.CODE)">验证码登录</text>
</view>
<view class="oneSubmitted-v2-2-xy">
<Protocol v-model="isReadProtocol" />
</view>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<view class="oneSubmitted-v2-2-2" @click="appLogin">
登录
</view>
<view class="oneSubmitted-v2-2-4">
<view class="oneSubmitted-v2-2-4-i" @click="oneClickLogin">
<image src="@/static/imagesV2/icon71.png" mode="widthFix"></image>
</view>
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view class="oneSubmitted-v2-2-2" v-if="!school.id" @click="prompt">
登录
</view>
<button class="oneSubmitted-v2-2-2" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber"
v-else>
登录
</button>
<view class="oneSubmitted-v2-2-3">
本小程序为中志教育内部系统,不对外开放
</view>
<!-- #endif -->
</view>
</PaddingTopB>
</view>
<!-- 登录-->
<!-- <view class="header-wrap"></view> -->
</PaddingTopB>
</view>
<!-- 登录-->
<!-- <view class="header-wrap"></view> -->
<!-- <view class="content-wrap1 area flex">
<!-- <view class="content-wrap1 area flex">
<view class="content-item flex">
<image class="img" src="/static/images/logo.png" mode=""></image>
<view class="botm-btn-2" @click="openMajor">
... ... @@ -52,38 +95,225 @@
</view>
</view>
</view> -->
<u-picker :show="show" :columns="columns" @cancel="show = false" keyName="name" @confirm="confirm"></u-picker>
<u-picker :show="show" :columns="columns" @cancel="show = false" keyName="name" @confirm="confirm"></u-picker>
</view>
</template>
<script>
import CustomReturn from "@/components/CustomReturn/index.vue"
import PaddingTopB from "@/components/PaddingTopB/index.vue"
import Countdown from "@/components/Countdown/index.vue"
import Protocol from "@/components/Protocol/index.vue"
import Vue from 'vue'
import {
mapState,
mapMutations
} from 'vuex'
var that
/**
* 大咖课类型
*/
const LOGINMETHOD = {
/**
* 密码登录
* @value 1
*/
'PASSWORDLOGIN': 1,
/**
* 验证码登录
* @value 1
*/
'CODE': 2
}
var that
export default {
components: {
CustomReturn,
PaddingTopB
PaddingTopB,
Countdown,
Protocol
},
data() {
return {
LOGINMETHOD,
loginType: LOGINMETHOD.PASSWORDLOGIN,
show: false,
columns: [],
school: {}
school: {},
// 手机号/账号
phoneNumber: '',
// 验证码
code: '',
// 密码
password: '',
// 协议状态
isReadProtocol: false,
// 是否是明文密码
isPlaintext: false
}
},
onLoad(option) {
that=this
that = this
console.log(option);
console.log(process.env.NODE_ENV)
this.getColumns()
},
methods: {
changePlaintext() {
this.isPlaintext = !this.isPlaintext
},
changeLoginType(type) {
this.loginType = type
},
sendCode() {
if(!this.phoneNumber) {
uni.showToast({
title: '请输入手机号',
icon: 'none'
})
return
}
let form = {
phone: this.phoneNumber
}
console.log(form)
that.$service.P_post('login/send_sms', form).then(res => {
if (res.code == 1) {
this.$refs.countdownRef.start()
} else {
if (res.msg) {
uni.showToast({
icon: 'none',
title: res.msg
})
} else {
uni.showToast({
icon: 'none',
title: '获取数据失败'
})
}
}
})
},
oneClickLogin() {
if (!this.school.id) {
uni.showToast({
icon: 'none',
title: '请选择学校'
})
return
}
this.loginPhone()
},
// 手机号一键登录
loginPhone(callBack = null) {
let that = this
uni.showLoading({
title: '加载中'
})
uni.preLogin({
provider: 'univerify',
success(res) {
//预登录成功
uni.hideLoading()
if (callBack) {
callBack()
}
uni.login({
provider: 'univerify',
univerifyStyle: { // 自定义登录框样式
"fullScreen": true,
"authButton": {
"normalColor": '#2d81ff',
"highlightColor": "#2d81ff",
"disabledColor": "#2d81ff",
"title": '本机号码一键登录/注册'
},
"otherLoginButton": {
"title": "其他登录方式"
},
"privacyTerms": {
"defaultCheckBoxState": false,
"checkBoxSize": 14,
"termsColor": "#2d81ff",
"textColor": "#202020",
// "uncheckedImage": "static/login/icon4.png",
// "checkedImage": "static/login/icon5.png",
"isCenterHint": true,
"privacyItems": [{
"url": "https://edudev.baoshanjiaoyu.com/agreement/yonghuxieyi.html", // 点击跳转的协议详情页面
"title": "校园通用户协议" // 协议名称
},
{
"url": "https://edudev.baoshanjiaoyu.com/agreement/yinsixieyi.html", // 点击跳转的协议详情页面
"title": "校园通隐私政策" // 协议名称
}
]
}
},
success(res) { // 登录成功
console.log('===========》', res)
uni.closeAuthView()
let form = {
access_token: res.authResult.access_token,
openid: res.authResult.openid,
school_id: that.school.id
}
that.$service.P_post('login/loginByOperator', form).then(res => {
if (res.code == 1) {
that.jumpLogic(res.data)
} else {
if (res.msg) {
uni.showToast({
icon: 'none',
title: res.msg
})
} else {
uni.showToast({
icon: 'none',
title: '获取数据失败'
})
}
}
})
},
// 当用户点击自定义按钮时,会触发uni.login的fail回调[点击其他登录方式,可以跳转页面]
// 判断返回数据执行任意逻辑
fail(res) { // 登录失败
console.log(res.errCode)
console.log(res.errMsg)
uni.closeAuthView()
uni.hideLoading()
if (res.code == 30003) {
uni.navigateBack({
delta: 1
})
}
if (res.code == "30002") {
console.log('密码登录');
} else if (res.code == "30008") {
console.log('自定义按钮登录方式');
}
}
})
},
fail(res) { // 预登录失败
// 不显示一键登录选项(或置灰)
// 根据错误信息判断失败原因,如有需要可将错误提交给统计服务器
uni.hideLoading()
if (callBack) {
callBack()
}
uni.closeAuthView()
// uni.navigateTo({
// url: '/pages/Login/Login'
// })
console.log('失败', 2222);
console.log(res.errCode)
console.log(res.errMsg)
}
});
},
prompt() {
uni.showToast({
icon: 'none',
... ... @@ -95,158 +325,217 @@
this.show = false
},
getColumns() {
var jkurl='/login/school'
var jkurl = '/login/school'
console.log('columns')
that.$service.P_get(jkurl).then(res => {
console.log(res)
console.log('columns', res)
this.columns = [res.data]
}).catch(e => {
console.log('catch', e)
})
},
openMajor() {
this.show = true
},
onGetPhoneNumber(e){
var that =this
if(e.detail.errMsg=="getPhoneNumber:fail user deny"){ //用户决绝授权
}else{ //允许授权
console.log(e)
//e.detail.encryptedData //加密的用户信息
//e.detail.iv //加密算法的初始向量 时要用到
// uni.setStorageSync('res_code', res_login.code);
var datas={
code: e.detail.code
}
var jkurl='login/getPhone'
that.$service.P_post(jkurl, datas).then(res => {
that.btnkg = 0
console.log(res)
if (res.code == 1) {
that.htmlReset = 0
var datas = res.data
console.log(typeof datas)
// if (typeof datas == 'string') {
// datas = JSON.parse(datas)
// }
var datas=JSON.stringify(datas)
console.log(res)
// uni.showModal({
// title:e.detail.code,
// content:datas
// })
// return
that.getdata(datas)
} else {
if (res.msg) {
uni.showToast({
icon: 'none',
title: res.msg
})
} else {
uni.showToast({
icon: 'none',
title: '获取数据失败'
})
}
}
}).catch(e => {
that.htmlReset = 1
that.btnkg = 0
// that.$refs.htmlLoading.htmlReset_fuc(1)
console.log(e)
onGetPhoneNumber(e) {
var that = this
if (e.detail.errMsg == "getPhoneNumber:fail user deny") { //用户决绝授权
} else { //允许授权
console.log(e)
//e.detail.encryptedData //加密的用户信息
//e.detail.iv //加密算法的初始向量 时要用到
// uni.setStorageSync('res_code', res_login.code);
var datas = {
code: e.detail.code
}
var jkurl = 'login/getPhone'
that.$service.P_post(jkurl, datas).then(res => {
that.btnkg = 0
console.log(res)
if (res.code == 1) {
that.htmlReset = 0
var datas = res.data
console.log(typeof datas)
// if (typeof datas == 'string') {
// datas = JSON.parse(datas)
// }
var datas = JSON.stringify(datas)
console.log(res)
// uni.showModal({
// title:e.detail.code,
// content:datas
// })
// return
that.getdata(datas)
} else {
if (res.msg) {
uni.showToast({
icon: 'none',
title: '获取数据失败,请检查您的网络连接'
title: res.msg
})
})
}
} else {
uni.showToast({
icon: 'none',
title: '获取数据失败'
})
}
}
}).catch(e => {
that.htmlReset = 1
that.btnkg = 0
// that.$refs.htmlLoading.htmlReset_fuc(1)
console.log(e)
uni.showToast({
icon: 'none',
title: '获取数据失败,请检查您的网络连接'
})
})
}
},
login_fuc(){
login_fuc() {
// /pages/index/index
// console.log(that.$service.VER)
// return
if(that.$service.VER==0){
uni.setStorageSync('identity',0)
if (that.$service.VER == 0) {
uni.setStorageSync('identity', 0)
uni.switchTab({
url:'/pages/index/index'
url: '/pages/index/index'
})
return
}else{
} else {
that.getdata('18300000000')
}
},
login_fuc1(){
login_fuc1() {
that.getdata('15536043014')
return
uni.setStorageSync('identity',1)
uni.setStorageSync('identity', 1)
uni.reLaunch({
url:'/pages/tch_index/tch_index'
url: '/pages/tch_index/tch_index'
})
},
getdata(tel){
appLogin() {
// #ifdef APP-PLUS
if(!this.isReadProtocol) {
uni.showToast({
icon: 'none',
title: '请阅读并同意《用户协议》和《隐私政策》'
})
return
}
if (!this.school.id) {
uni.showToast({
icon: 'none',
title: '请选择学校'
})
return
}
if(!this.phoneNumber) {
uni.showToast({
icon: 'none',
title: '请填写手机号'
})
return
}
if(this.loginType === LOGINMETHOD.PASSWORDLOGIN) {
if(!this.password) {
uni.showToast({
icon: 'none',
title: '请输入密码'
})
return
}
let form = {
school_id: this.school.id,
phone: this.phoneNumber,
pass: this.password
}
that.$service.P_post('login/loginByPassword', form).then(res => {
if (res.code == 1) {
that.jumpLogic(res.data)
} else {
if (res.msg) {
uni.showToast({
icon: 'none',
title: res.msg
})
} else {
uni.showToast({
icon: 'none',
title: '获取数据失败'
})
}
}
})
} else if(this.loginType === LOGINMETHOD.CODE) {
if(!this.code) {
uni.showToast({
icon: 'none',
title: '请输入验证码'
})
return
}
let form = {
school_id: this.school.id,
phone: this.phoneNumber,
code: this.code
}
that.$service.P_post('login/loginByCode', form).then(res => {
if (res.code == 1) {
that.jumpLogic(res.data)
} else {
if (res.msg) {
uni.showToast({
icon: 'none',
title: res.msg
})
} else {
uni.showToast({
icon: 'none',
title: '获取数据失败'
})
}
}
})
}
// #endif
},
getdata(tel) {
// #ifdef MP-WEIXIN
wx.login({
success: function(res_login) {
console.log(res_login)
uni.setStorageSync('res_code', res_login.code);
var datas={
var datas = {
code: res_login.code,
type:1,
phone:tel,
type: 1,
phone: tel,
school_id: that.school.id
}
var jkurl='/login'
var jkurl = '/login'
that.$service.P_post(jkurl, datas).then(res => {
that.btnkg = 0
console.log(res)
if (res.code == 1) {
that.htmlReset = 0
var datas = res.data
console.log(typeof datas)
console.log('datas', datas)
if (typeof datas == 'string') {
datas = JSON.parse(datas)
}
console.log(res)
var identity=datas.identity
var token=datas.token
uni.setStorageSync('identity',identity)
uni.setStorageSync('token',token)
that.$store.commit('login', datas)
uni.showToast({
icon: 'none',
title: '登陆成功'
})
setTimeout(function(){
// uni.reLaunch({
// url:'/new_tec/homePage/homePage'
// })
// return
if(identity==2){
uni.reLaunch({
url:'/pages/tch_index/tch_index'
})
}else if(identity==1){
uni.switchTab({
url:'/pages/index/index'
})
} else if(identity==4){
uni.reLaunch({
url:'/new_tec/homePage/homePage'
})
} else {
uni.reLaunch({
url:'/pages/admin_index/admin_index'
})
}
},1000)
that.jumpLogic(datas)
} else {
if (res.msg) {
uni.showToast({
icon: 'none',
... ... @@ -271,8 +560,44 @@
})
}
})
// #endif
},
jumpLogic(datas) {
console.log(datas)
var identity = datas.identity
var token = datas.token
uni.setStorageSync('identity', identity)
uni.setStorageSync('token', token)
that.$store.commit('login', datas)
uni.showToast({
icon: 'none',
title: '登陆成功'
})
setTimeout(function() {
// uni.reLaunch({
// url:'/new_tec/homePage/homePage'
// })
// return
if (identity == 2) {
uni.reLaunch({
url: '/pages/tch_index/tch_index'
})
} else if (identity == 1) {
uni.switchTab({
url: '/pages/index/index'
})
} else if (identity == 4) {
uni.reLaunch({
url: '/new_tec/homePage/homePage'
})
} else {
uni.reLaunch({
url: '/pages/admin_index/admin_index'
})
}
}, 1000)
}
}
}
</script>
... ... @@ -281,24 +606,30 @@
.oneSubmitted {
position: relative;
}
.oneSubmitted-v2{
.oneSubmitted-v2 {
position: relative;
background-color: #ebf5ff;
.oneSubmitted-v2-bg{
.oneSubmitted-v2-bg {
position: absolute;
width: 100%;
}
.oneSubmitted-v2-1{
.oneSubmitted-v2-1 {
text-align: center;
margin-top: 150rpx;
.oneSubmitted-v2-1-i{
.oneSubmitted-v2-1-i {
height: 240rpx;
width: 240rpx;
}
}
.oneSubmitted-v2-2{
.oneSubmitted-v2-2 {
padding: 0 75rpx;
.oneSubmitted-v2-2-1{
.oneSubmitted-v2-2-1 {
display: flex;
background-color: #FFFFFF;
height: 102rpx;
... ... @@ -306,11 +637,40 @@
border-radius: 300rpx;
padding: 0 40rpx;
box-sizing: border-box;
.oneSubmitted-v2-2-1-l{
margin-bottom: 49rpx;
&:last-child {
margin-bottom: 0;
}
.oneSubmitted-v2-2-1-l {
flex-grow: 1;
}
.oneSubmitted-v2-2-1-i {
flex-grow: 1;
font-size: 32rpx;
}
.oneSubmitted-v2-2-1-r {
width: 200rpx;
display: flex;
justify-content: flex-end;
flex-shrink: 0;
}
}
.oneSubmitted-v2-2-c {
margin-bottom: 30rpx;
text-align: right;
padding-right: 20rpx;
color: #646464;
font-size: 28rpx;
}
.oneSubmitted-v2-2-2{
.oneSubmitted-v2-2-xy {}
.oneSubmitted-v2-2-2 {
height: 90rpx;
border-radius: 200rpx;
font-size: 34rpx;
... ... @@ -320,15 +680,29 @@
margin-top: 60rpx;
background-color: #2D81FF;
}
.oneSubmitted-v2-2-3{
.oneSubmitted-v2-2-3 {
font-size: 24rpx;
margin-top: 26rpx;
text-align: center;
color: #323232;
}
.oneSubmitted-v2-2-4{
display: flex;
justify-content: center;
margin-top: 40rpx;
.oneSubmitted-v2-2-4-i{
width: 88rpx;
height: 88rpx;
image{
height: 100%;
width: 100%;
}
}
}
}
}
.content-wrap1 {
min-height: 608rpx;
background: #FFFFFF;
... ... @@ -367,12 +741,14 @@
font-weight: 400;
color: #FFFFFF;
margin: 28rpx 0 28rpx 0;
}
.botm-btn1{
.botm-btn1 {
margin-top: 40rpx;
}
.botm-btn-2{
.botm-btn-2 {
margin-top: 40rpx;
background-color: #F4F4F4;
width: 100%;
... ... @@ -383,6 +759,7 @@
border-radius: 200rpx;
font-size: 25rpx;
}
.samll-text {
height: 28rpx;
font-size: 28rpx;
... ... @@ -390,7 +767,8 @@
font-weight: 400;
color: #545D6E;
}
.login_top{
.login_top {
width: 100%;
}
</style>
</style>
\ No newline at end of file
... ...
... ... @@ -91,161 +91,6 @@
</view>
</PaddingTopB>
</view>
<!-- 我的 -->
<!-- 头部卡片 -->
<view v-if="mymsg" class="header-wrap">
<view class="header-all area flex">
<view class="header-left flex" @tap="$sjuNav.navigateTo(`/pagesB/oneSetting/oneSetting`)">
<view class="header-img">
<!-- <image :src="userImg" mode="aspectFill"></image> -->
<myLazyLoad class="image" :src="$service.getimg(mymsg.img)" mode="aspectFill" :borderRadius="112"></myLazyLoad>
</view>
<view class="header-user">
<view class="header-userName flex">
<view class="user_name oh1">
{{mymsg.name||''}}
</view> <text class="oh1">{{mymsg.className||''}}</text>
</view>
<view class="header-userNum oh1">
{{mymsg.study_code||''}}
</view>
</view>
</view>
<view class="pass-check" @tap="go_txz">
通行证
</view>
</view>
</view>
<view>
<!-- 我的住宿办理 -->
<view class="handle-wrap area">
<image class="handle-img" src="/static/images/wdzsbl.png" mode="aspectFit" />
<view class="handle-item flex">
<view class="handle-item-left flex">
<text class="icon icon-xiangxingtujianzhu handle-icon"></text>
<view class="my-handle">
我的住宿办理
</view>
</view>
<!-- <view class="go-see" @click="$service.jump" data-url="/pagesStu/stu_live/stu_live"> -->
<view class="go-see" @click="gozs" data-url="/pagesStu/stu_live/stu_live">
去查看
</view>
</view>
</view>
<!-- 我的床位 手机箱 -->
<view class="content-wrap-bed-phone area flex">
<view class="content-item">
<image class="content-img" src="/static/images/wdcw.png" mode="aspectFit"></image>
<view class="content-text flex">
<view class="content-bed">
我的床位
</view>
<view class="content-bed-num">
{{mymsg.bed_title||''}}
</view>
</view>
</view>
<view class="content-item">
<image class="content-img" src="/static/images/sjx.png" mode="aspectFit"></image>
<view class="content-text flex">
<view class="content-bed">
手机箱
</view>
<view class="content-bed-num">
{{mymsg.phone_box||''}}
</view>
</view>
</view>
</view>
<!-- 列表 -->
<view class="seat-num-wrap area">
<!-- <view class="seat-num-item flex">
<view class="seat-num-left flex">
<text class="icon icon-banji seat-icon"></text>
<view class="seat-text">
小班座位
</view>
</view>
<view class="seat-num">
{{mymsg.small_seat||''}}
</view>
</view> -->
<view class="seat-num-item flex">
<view class="seat-num-left flex">
<text class="icon icon-xuexi seat-icon2"></text>
<view class="seat-text">
听课座位
</view>
</view>
<view class="seat-num">
{{mymsg.big_seat||''}}
</view>
</view>
<view class="seat-num-item flex">
<view class="seat-num-left flex flex_0">
<text class="icon icon-banji seat-icon"></text>
<view class="seat-text">
我的班级
</view>
</view>
<view class="seat-num">
{{mymsg.className||''}}
</view>
</view>
<view class="seat-num-item flex">
<view class="seat-num-left flex">
<text class="icon icon-banzhuren seat-icon"></text>
<view class="seat-text">
班主任电话
</view>
</view>
<view class="seat-num">
{{mymsg.teacher_phone||''}}
</view>
</view>
<view class="seat-num-item flex">
<view class="seat-num-left flex">
<text class="icon icon-kechengqiri seat-icon"></text>
<view class="seat-text">
课程有效期
</view>
</view>
<view class="seat-num">
{{mymsg.end_time||''}}
</view>
</view>
<!-- <view class="seat-num-item flex" @click="$service.jump" data-url="/pagesStu/sq_list/sq_list">
<view class="seat-num-left flex">
<text class="icon icon-xiangxingtujianzhu seat-icon"></text>
<view class="seat-text">
请假申请记录
</view>
</view>
<view class="seat-num">
<text class="icon icon-arrow-right-copy seat-icon"></text>
</view>
</view>
<view class="seat-num-item flex" @click="$service.jump" data-url="/pagesStu/sq_list_tel/sq_list_tel">
<view class="seat-num-left flex">
<text class="icon icon-xiangxingtujianzhu seat-icon"></text>
<view class="seat-text">
不交手机申请记录
</view>
</view>
<view class="seat-num">
<text class="icon icon-arrow-right-copy seat-icon"></text>
</view>
</view> -->
</view>
</view>
</view>
</template>
... ...
... ... @@ -248,6 +248,10 @@
right: 0;
width: 100rpx;
height: 40rpx;
image{
height: 100%;
width: 100%;
}
}
}
.entrance-container {
... ... @@ -298,6 +302,10 @@
width: 78rpx;
height: 40rpx;
margin-top: 20rpx;
image{
height: 100%;
width: 100%;
}
}
}
}
... ...
... ... @@ -13,8 +13,8 @@
<PaddingTopB>
<view class="main" v-if="userDatas">
<view class="user-wrap" @click="$service.jump" data-url="/pagesA/tch_msg/tch_msg">
<view class="user-info">
<view class="user-wrap">
<view class="user-info" @click="$service.jump" data-url="/pagesA/tch_msg/tch_msg">
<view class="avatar">
<view class="img">
<image :src="$service.getimg(userDatas.img)" mode="aspectFill"></image>
... ... @@ -323,11 +323,19 @@
.set-up {
width: 40rpx;
height: 40rpx;
image{
height: 100%;
width: 100%;
}
}
.bg-img {
height: 360rpx;
position: absolute;
width: 100%;
image{
height: 100%;
width: 100%;
}
}
.main {
width: 100%;
... ... @@ -355,6 +363,10 @@
box-sizing: border-box;
border-radius: 50%;
overflow: hidden;
image{
height: 100%;
width: 100%;
}
}
.identity {
background: linear-gradient(0deg, #2D81FF 0%, #458FFE 100%);
... ... @@ -366,6 +378,8 @@
padding: 6rpx 20rpx;
margin-top: -20rpx;
text-align: center;
position: relative;
z-index: 2;
}
}
.info {
... ... @@ -382,6 +396,10 @@
width: 30rpx;
height: 30rpx;
margin: 0 15rpx 0 10rpx;
image{
height: 100%;
width: 100%;
}
}
.tab {
background: rgba(49, 132, 255, 0.08);
... ... @@ -431,6 +449,14 @@
}
.class-division {
margin-right: 100rpx;
.cell-item-icon{
height: 70rpx;
width: 70rpx;
image{
height: 100%;
width: 100%;
}
}
}
}
}
... ... @@ -467,6 +493,10 @@
.icon {
width: 70rpx;
height: 70rpx;
image{
height: 100%;
width: 100%;
}
}
}
.bg {
... ...
<template>
<u-popup :show="show" bgColor="transparent" mode="center" :safeAreaInsetBottom="false" borderRadius="20">
<view class="new-update">
<view class="new-update-1">
<image class="new-update-1-i" src="@/static/imagesV2/icon70.png" mode="widthFix"></image>
<view class="new-update-1-c">
<view class="new-update-1-c-1">
发现新版本
</view>
</view>
</view>
<view class="new-update-2">
<view class="new-update-2-1">新版本更新内容</view>
<scroll-view :scroll-y="true" style="height: 300rpx;">
<view style="font-size: 28rpx !important;">
<view v-html="content"></view>
</view>
</scroll-view>
<view class="immediate" @click="update" v-if="!is_load">立即升级</view>
<view class="progress" v-else>
<u-line-progress :percentage="progressOf" activeColor="#1b60b2"></u-line-progress>
<view class="progress-t">安装包下载中,请稍后({{ size.schedule }}M/{{ size.total }}M)</view>
</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
data() {
return {
show: true,
content: '更新内容',
is_load: false,
progressOf: 0,
urlObj: {
ios: '',
apk: ''
},
size: {
total: 0,
schedule: 0
}
}
},
onBackPress(e) {
// 这里可以自定义返回逻辑
return true // return true 表示禁止默认返回
},
onLoad() {
this.getData()
},
methods: {
getData() {
let version = plus.runtime.version
this.$service.P_post('/version/index', {
client: uni.getSystemInfoSync().platform,
version: version
}).then(res => {
this.content = res.msg.content
if(plus.os.name.toLowerCase() == 'ios') {
this.urlObj.ios = res.msg.url
} else {
this.urlObj.apk = res.msg.url
}
})
},
update() {
let that = this
if (plus.os.name.toLowerCase() == 'ios') {
plus.runtime.openURL(this.urlObj.ios)
} else {
this.is_load = true
var dtask = this.getCreateDownload()
try {
dtask.start();
var prg = 0;
dtask.addEventListener('statechanged', (task, status) => {
switch (task.state) {
case 3:
that.progressOf = parseInt(
(parseFloat(task.downloadedSize) /
parseFloat(task.totalSize)) *
100
);
that.size.total = (task.totalSize / (1024 * 1024)).toFixed(2)
that.size.schedule = (task.downloadedSize / (1024 * 1024)).toFixed(2)
break;
case 4:
that.is_load = false
//下载完成
break;
}
})
} catch (err) {
console.log('err', err)
// plus.nativeUI.closeWaiting();
that.is_load = false
uni.showToast({
title: '更新失败-03',
mask: false,
duration: 1500
});
}
}
},
// 获取下载实例
getCreateDownload() {
return plus.downloader.createDownload(this.urlObj.apk, {},
function(d, status) {
// 下载完成
if (status == 200) {
plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename), {}, e => e,
function(error) {
uni.showToast({
title: '安装失败-01',
mask: false,
duration: 1500
});
})
} else {
uni.showToast({
title: '更新失败-02',
mask: false,
duration: 1500
});
}
});
}
}
}
</script>
<style lang="scss" scoped>
.new-update{
width: 611rpx;
.new-update-1{
position: relative;
height: 260rpx;
.new-update-1-i{
width: 100%;
position: absolute;
}
.new-update-1-c{
padding-top: 50rpx;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
box-sizing: border-box;
padding-left: 54rpx;
.new-update-1-c-1{
font-size: 36rpx;
font-weight: 800;
color: #FFFFFF;
margin-bottom: 10rpx;
}
.new-update-1-c-2{
font-size: 26rpx;
color: #fff;
}
}
}
.new-update-2{
background: #fff;
border-radius:0 0 40rpx 40rpx;
padding: 50rpx;
padding-top: 20rpx;
box-sizing: border-box;
.new-update-2-1{
margin-bottom: 20rpx;
color: #1b60b2;
font-weight: bold;
}
.immediate{
line-height: 90rpx;
background: linear-gradient(0deg, #098ad5 0%, #1b60b2 100%);
color: #fff;
margin: 60rpx 0 0 0;
border-radius: 500rpx;
text-align: center;
}
.progress{
height: 80rpx;
margin: 60rpx 0 0 0;
.progress-t{
font-size: 26rpx;
color: #323232;
margin-top: 15rpx;
text-align: center;
}
}
}
}
</style>
\ No newline at end of file
... ...
... ... @@ -401,6 +401,10 @@
width: 30rpx;
height: 30rpx;
margin-right: 10rpx;
image{
height: 100%;
width: 100%;
}
}
}
}
... ...
... ... @@ -251,6 +251,8 @@
margin-right: 30rpx;
.avatar-img {
border-radius: 50%;
height: 100%;
width: 100%;
}
.gender {
position: absolute;
... ... @@ -258,6 +260,10 @@
height: 24rpx;
right: 0rpx;
bottom: 12rpx;
image{
height: 100%;
width: 100%;
}
}
}
.info {
... ...
... ... @@ -16,7 +16,7 @@
{{item.name}}
</view>
<image class="gender" v-if="item.sex!=1" src="/static/imagesV2/stu_selection/icon_female.png" mode="aspectFit"></image>
<image class="gender" v-else src="/static/imagesV2/stu_selection/icon_male.png" mode="aspectFit"></image>
<image class="gender" v-else src="/static/imagesV2/stu_selection/icon_male.png" mode="widthFix"></image>
</view>
<view class="operate">
<view class="btn" @click="$service.jump" :data-url="'/pagesA/stu_bz_index/stu_bz_index?id='+item.id">
... ... @@ -224,8 +224,8 @@
align-items: center;
}
.gender {
width: 29rpx !important;
height: 24rpx !important;
width: 29rpx;
height: 29rpx;
margin-left: 20rpx;
}
... ... @@ -245,6 +245,10 @@
margin-right: 10rpx;
width: 30rpx;
height: 30rpx;
image{
height: 100%;
width: 100%;
}
}
}
}
... ...
... ... @@ -206,6 +206,9 @@
height: 504rpx;
position: absolute;
width: 100%;
image{
width: 100%;
}
}
.main {
width: 100%;
... ...
... ... @@ -4,7 +4,7 @@
</CustomReturn>
<view class="bg-img">
<image src="/static/imagesV2/icon18.png" mode="aspectFill"></image>
<image src="/static/imagesV2/icon18.png" mode="widthFix"></image>
</view>
<PaddingTopB>
... ... @@ -220,12 +220,16 @@
position: absolute;
width: 100%;
top: 0;
image{
width: 100%;
height: 100%;
}
}
.main {
width: 100%;
padding: 25rpx 25rpx 135rpx;
box-sizing: border-box;
margin-top: 250rpx;
margin-top: 160rpx;
}
.card {
... ... @@ -241,6 +245,10 @@
.icon {
width: 40rpx;
height: 40rpx;
image{
height: 100%;
width: 100%;
}
}
.title {
font-size: 32rpx;
... ...
... ... @@ -15,16 +15,17 @@
</view>
</view>
<!-- #ifdef APP-PLUS -->
<view class="oneSettingV2-c-1">
<view class="oneSettingV2-c-1" @click="clearCache">
<view class="oneSettingV2-c-1-l">清理缓存</view>
<view class="oneSettingV2-c-1-r">
<text>{{ cache }}</text>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view class="oneSettingV2-c-1">
<view class="oneSettingV2-c-1" @click="checkVersion">
<view class="oneSettingV2-c-1-l">检查版本</view>
<view class="oneSettingV2-c-1-r">
<text>v{{ version }}</text>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
... ... @@ -44,15 +45,49 @@
export default {
data() {
return {
cache: '',
version: ''
}
},
onLoad(option) {
// #ifdef APP-PLUS
this.getCache()
this.getVersion()
// #endif
},
computed: {},
methods: {
checkVersion() {
uni.navigateTo({
url: '/pages/update/update'
})
},
getVersion() {
plus.runtime.getProperty(plus.runtime.appid, (widgetInfo) => {
console.log('=========>', widgetInfo.version)
this.version = widgetInfo.version
})
},
clearCache(){
let that = this
uni.showModal({
title:'提示',
content:'确定清除缓存吗?',
success(res) {
// 用户确定要删除
if(res.confirm){
//使用plus.cache.clear 清除应用中的缓存数据 这里清除后还要二十几KB没有清除,达不到全部清除
plus.cache.clear(() => {
that.getCache()
uni.showToast({
title:'清除成功',
icon:'none'
})
});
}
}
})
},
toRichText(type) {
uni.navigateTo({
url: '/pagesB/richText/richText?type=' + type
... ... @@ -111,6 +146,7 @@
.oneSettingV2-c-1-r{
font-size: 28rpx;
color: #646464;
display: flex;
}
}
}
... ...
... ... @@ -172,6 +172,10 @@
height: 504rpx;
position: absolute;
width: 100%;
image{
height: 100%;
width: 100%;
}
}
.main {
width: 100%;
... ...
... ... @@ -220,6 +220,10 @@
height: 30rpx;
margin-right: 10rpx;
margin-top: 5rpx;
image{
height: 100%;
width: 100%;
}
}
textarea {
width: 100%;
... ...
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<view class="CustomReturn-container" :style="{height: titleHeight, paddingTop: paddingTop, backgroundColor: bgColor}">
<view class="CustomReturn">
<view v-if="isShowBreak" class="CustomReturn-r">
... ... @@ -15,13 +14,14 @@
<u-icon name="close-circle-fill" size="20" color="#E6E6E6"></u-icon>
</view>
</view>
<!-- #ifdef MP-WEIXIN -->
<view style="width: 200rpx;"></view>
<!-- #endif -->
</view>
<view class="other">
<slot></slot>
</view>
</view>
<!-- #endif -->
</view>
... ... @@ -120,10 +120,10 @@
this.paddingTop = uni.getSystemInfoSync().statusBarHeight + 'px'
// #ifdef MP-WEIXIN
let res = wx.getMenuButtonBoundingClientRect();
// #endif
this.paddingTop = res.top + 'px'
this.titleHeight = res.height + 10 + 'px';
this.entityHeight = res.top + res.height
// #endif
},
toBreak(){
... ... @@ -169,6 +169,7 @@
.CustomReturn-title{
font-size: 36rpx;
flex-grow: 1;
.CustomReturn-title-c{
background-color: #F6F6F6;
border: 1px solid #E6E6E6;
... ...
... ... @@ -323,6 +323,10 @@
height: 48rpx;
width: 48rpx;
border-radius: 200rpx;
image{
height: 100%;
width: 100%;
}
}
.myQuestion-2-i-3-c-1-l-t{
font-size: 26rpx;
... ...
<template>
<view class="audioPlayback">
<view class="audioPlayback-bg">
<image class="audioPlayback-bg-img" src="@/static/images/txz.jpg"></image>
<image class="audioPlayback-bg-img" :src="info.cover"></image>
</view>
<TopNavigation />
<PaddingTopB>
... ... @@ -9,18 +9,18 @@
<view class="audioPlayback-content-1">
<view class="ItemQ">
<view class="ItemQ-1">
<image src="@/static/images/txz.jpg"></image>
<image :src="info.cover"></image>
</view>
<view class="ItemQ-2">音频</view>
<view class="ItemQ-2">{{ info.name }}</view>
</view>
</view>
<view class="audioPlayback-content-2">
<yz-audio
@ended="ended"
:autoplay="true"
singer="歌手"
epname="专辑名称"
title="歌曲标题"
:singer="info.created_user"
:epname="info.name"
:title="info.name"
ref="player1"></yz-audio>
</view>
</view>
... ... @@ -38,10 +38,32 @@
},
data() {
return {
id: null,
info: {}
};
},
onLoad({ id }) {
this.id = id
this.getData()
},
onUnload() {
console.log('onUnload')
},
methods: {
getData() {
this.$service.P_get('/course/info', { id: this.id }).then(res => {
console.log(res.data.data)
this.info = res.data.data
this.$nextTick(() => {
// const bgAudioManager = uni.getBackgroundAudioManager();
// bgAudioManager.title = '致爱丽丝';
// bgAudioManager.singer = '暂无';
// bgAudioManager.coverImgUrl = 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/music-a.png';
// bgAudioManager.src = 'https://edudev.baoshanjiaoyu.com/code.mp3';
this.$refs.player1.setSrc(this.info.url)
})
})
},
ended() {
}
... ...
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<view class="CustomReturn-container" :style="{height: titleHeight, paddingTop: paddingTop, backgroundColor: bgColor}">
<view class="CustomReturn">
<view v-if="isShowBreak" class="CustomReturn-r">
... ... @@ -15,7 +14,6 @@
<slot></slot>
</view>
</view>
<!-- #endif -->
</view>
... ... @@ -110,10 +108,10 @@
this.paddingTop = uni.getSystemInfoSync().statusBarHeight + 'px'
// #ifdef MP-WEIXIN
let res = wx.getMenuButtonBoundingClientRect();
// #endif
this.paddingTop = res.top + 'px'
this.titleHeight = res.height + 10 + 'px';
this.entityHeight = res.top + res.height
// #endif
},
toBreak(){
... ... @@ -149,7 +147,7 @@
display: flex;
align-items: center;
flex-grow: 1;
padding: 0 24rpx;
padding: 24rpx 24rpx;
justify-content: space-between;
position: relative;
z-index: 1002;
... ...
... ... @@ -6,7 +6,7 @@
<view @tap="tabsClick(BIGSHOTS.AUDIOLESSONS)" :class="{'bigShots-1-1-i': true, 'bigShots-1-1-is': type === BIGSHOTS.AUDIOLESSONS}">音频课程</view>
</view>
<view class="bigShots-1-2">
<picker @change="bindpickerChange" :value="index" :range="subjectList" range-key="title">
<picker @change="bindpickerChange" :range="subjectList" range-key="title">
<view class="bigShots-1-2-i">
<text class="bigShots-1-2-i-t">{{ selectType.name || '请选择分类' }} </text>
<u-icon size="10" name="arrow-down-fill" color="#646464"></u-icon>
... ... @@ -92,6 +92,11 @@
'LIKECOUNT': 'up_count'
}
export default {
watch: {
type(newVal) {
this.onRetry()
}
},
data() {
return {
SORTINGTYPE,
... ... @@ -168,7 +173,8 @@
page: this.page,
order_field: this.currentSorting,
order_sort: this.currentSorting ? this.sortLog[this.currentSorting] : '',
cate_id: this.selectType.id || ''
cate_id: this.selectType.id || '',
type: this.type
}).then(res => {
uni.hideLoading();
if (res.code == 1) {
... ... @@ -198,12 +204,15 @@
this.type = type
},
toBigShotsDetails(item) {
uni.navigateTo({
url: '/pagesStu/bigShotsDetails/bigShotsDetails?id=' + item.id
})
// uni.navigateTo({
// url: '/pagesStu/audioFrequency/audioFrequency'
// })
if(item.type === BIGSHOTS.VIDEOLESSONS) {
uni.navigateTo({
url: '/pagesStu/bigShotsDetails/bigShotsDetails?id=' + item.id
})
} else {
uni.navigateTo({
url: '/pagesStu/audioFrequency/audioFrequency?id=' + item.id
})
}
}
}
}
... ...
... ... @@ -2,45 +2,54 @@
<view class="bigShotsDetails">
<view class="bigShotsDetails-1">
<qxcplayer class="qxcplayer-style" ref="qxcplayerRef"></qxcplayer>
<view class="bigShotsDetails-1-c">视频专辑:行测</view>
<view class="bigShotsDetails-1-c">视频专辑:{{ info.name }}</view>
</view>
<view class="bigShotsDetails-2">
<view class="bigShotsDetails-2-1">
共<text style="color: #2D81FF;">20</text>条评价
共<text style="color: #2D81FF;">{{ info.comment_count }}</text>条评价
</view>
<view class="bigShotsDetails-2-2">
<view class="bigShotsDetails-2-2-i" v-for="(item, index) in 10" :key="index">
<image class="bigShotsDetails-2-2-i-l" src="@/static/images/tx.png" mode="widthFix"></image>
<view class="bigShotsDetails-2-2-i" v-for="(item, index) in commitList" :key="item.id">
<image class="bigShotsDetails-2-2-i-l" v-if="item.answer" :src="item.answer" mode="widthFix"></image>
<image class="bigShotsDetails-2-2-i-l" v-else src="@/static/images/tx.png" mode="widthFix"></image>
<view class="bigShotsDetails-2-2-i-r">
<view class="bigShotsDetails-2-2-i-r-1">
<view class="bigShotsDetails-2-2-i-r-1-l">栾珍</view>
<view class="bigShotsDetails-2-2-i-r-1-r">2023-12-10</view>
<view class="bigShotsDetails-2-2-i-r-1-l">{{ item.user_name }}</view>
<view class="bigShotsDetails-2-2-i-r-1-r">{{ item.created_at }}</view>
</view>
<view class="bigShotsDetails-2-2-i-r-2">
老师讲的很仔细,可能第一册比较简单吧,没有很多 的语法知识,不过我也学到很多,这就是积累的过程, 谢谢老师
{{ item.comment }}
</view>
</view>
</view>
<u-empty
v-if="notData"
mode="data"
text="暂无数据"
icon="/static/imagesV2/icon24.png"
>
</u-empty>
</view>
</view>
<view class="bigShotsDetails-3-c">
<view class="bigShotsDetails-3">
<view class="bigShotsDetails-3-l">
<view class="bigShotsDetails-3-l-1">
<input class="bigShotsDetails-3-l-1-in" type="text" placeholder="请输入"/>
<input class="bigShotsDetails-3-l-1-in" v-model="commentText" type="text" placeholder="请输入"/>
</view>
<view class="bigShotsDetails-3-l-2">
<view class="bigShotsDetails-3-l-2" @click="release">
发布
</view>
</view>
<view class="bigShotsDetails-3-r">
<view class="bigShotsDetails-3-r-i">
<image class="bigShotsDetails-3-r-i-i" src="@/static/imagesV2/icon47.png" mode="widthFix"></image>
<text>0</text>
<text>{{ info.comment_count }}</text>
</view>
<view class="bigShotsDetails-3-r-i">
<image class="bigShotsDetails-3-r-i-i" src="@/static/imagesV2/icon48.png" mode="widthFix"></image>
<text>0</text>
<view class="bigShotsDetails-3-r-i" @click="like">
<image class="bigShotsDetails-3-r-i-i" v-if="info.is_up" src="@/static/imagesV2/icon69.png" mode="widthFix"></image>
<image class="bigShotsDetails-3-r-i-i" v-else src="@/static/imagesV2/icon48.png" mode="widthFix"></image>
<text>{{ info.up_count }}</text>
</view>
</view>
</view>
... ... @@ -55,23 +64,116 @@
components: {
qxcplayer
},
destroyed() {
onUnload() {
// 销毁
this.$refs.qxcplayerRef.destory()
},
computed: {
notData() {
return this.status === 'nomore' && !this.commitList.length
}
},
data() {
return {
id: null,
page: 1,
info: {},
commitList: [],
// 加载前值为loadmore,加载中为loading,没有数据为nomore
status: 'loadmore',
commentText: ''
};
},
onLoad({ id }) {
this.id = id
this.getData()
this.onRetry()
},
onReachBottom() {
debugger
},
mounted() {
this.$refs.qxcplayerRef.initData({
token: 'fb08f60a1b9b32e4ba80|0|1705377109|3743-4262|6021|e7wDu4613bceC0R25|200|',
env: 'product',
name: 'qxcname',
})
},
methods: {
like() {
this.$service.P_post('/course/up', {
id: this.id
}).then(res => {
if(this.info.is_up){
this.$set(this.info, 'up_count', this.info.up_count - 1)
} else {
this.$set(this.info, 'up_count', this.info.up_count + 1)
}
this.$set(this.info, 'is_up', !this.info.is_up)
})
},
release() {
this.$service.P_post('/course/comment_add', {
id: this.id,
comment: this.commentText
}).then(res => {
uni.showToast({
icon: 'none',
title: '评论成功,审核后可查看'
})
})
},
onRetry(){
this.page=1
this.commitList = []
this.status = 'loadmore'
this.getComment()
},
getComment() {
if(this.status === 'loading' || this.status === 'nomore') return;
this.status = 'loading';
uni.showLoading({
title: '加载中',
mask: true
})
this.$service.P_get('/course/comment', {
page: this.page,
id: this.id,
}).then((res) => {
if (res.code == 1) {
this.page++;
this.commitList = [
...this.commitList,
...res.data.data
]
this.status = res.data.data.length < res.data.per_page ? 'nomore' : 'loadmore'
} else {
this.status = 'loadmore';
if (res.msg) {
uni.showToast({
icon: 'none',
title: res.msg
})
} else {
uni.showToast({
icon: 'none',
title: '获取数据失败'
})
}
}
console.log(res)
})
},
getData() {
this.$service.P_get('/course/info', { id: this.id }).then(res => {
console.log(res.data.data)
this.info = res.data.data
this.$nextTick(() => {
this.$refs.qxcplayerRef.initData({
token: this.info.qxy_token,
env: 'test',
name: 'qxcname',
})
})
})
}
}
}
</script>
... ...
... ... @@ -339,6 +339,10 @@
height: 504rpx;
position: absolute;
width: 100%;
image{
width: 100%;
height: 100%;
}
}
.vio_list{
... ... @@ -412,6 +416,10 @@
top: 0;
width: 130rpx;
height: 40rpx;
image{
height: 100%;
width: 100%;
}
}
.rule_msg{
.xz_room{
... ... @@ -527,6 +535,10 @@
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
image{
height: 100%;
width: 100%;
}
}
.d1{
font-size: 32rpx;
... ...
... ... @@ -4,7 +4,7 @@
</CustomReturn>
<view class="bg-img">
<image src="/static/imagesV2/icon18.png" mode="aspectFill"></image>
<image src="/static/imagesV2/icon18.png" mode="widthFix"></image>
</view>
<PaddingTopB>
... ... @@ -220,6 +220,10 @@
position: absolute;
width: 100%;
top: 0;
image{
height: 100%;
width: 100%;
}
}
.main {
width: 100%;
... ... @@ -241,6 +245,10 @@
.icon {
width: 40rpx;
height: 40rpx;
image{
height: 100%;
width: 100%;
}
}
.title {
font-size: 32rpx;
... ...
... ... @@ -259,6 +259,10 @@
.head-bg {
width: 100%;
height: 100%;
image{
height: 100%;
width: 100%;
}
}
&-box {
position: absolute;
... ...
'use strict';
// const crypto = require('crypto')
exports.main = async (event, context) => {
//event为客户端上传的参数
const res = await uniCloud.getPhoneNumber({
appid: '__UNI__8740A53', // 替换成自己开通一键登录的应用的DCloud appid,使用callFunction方式调用时可以不传(会自动取当前客户端的appid),如果使用云函数URL化的方式访问必须传此参数
provider: 'univerify',
access_token: event.queryStringParameters.access_token,
openid: event.queryStringParameters.openid
})
// 执行用户信息入库等操作,正常情况下不要把完整手机号返回给前端
// 如果数据库在uniCloud上,可以直接入库
// 如果数据库不在uniCloud上,可以通过 uniCloud.httpclient API,将手机号通过http方式传递给其他服务器的接口,详见:https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=httpclient
//返回数据给客户端
return {
code: 0,
message: '获取手机号成功',
data: res
}
}
\ No newline at end of file
... ...
{
"name": "getPhoneNumber",
"dependencies": {},
"extensions": {
"uni-cloud-jql": {},
"uni-cloud-verify": {}
}
}
\ No newline at end of file
... ...
// 本文件用于,使用JQL语法操作项目关联的uniCloud空间的数据库,方便开发调试和远程数据库管理
// 编写clientDB的js API(也支持常规js语法,比如var),可以对云数据库进行增删改查操作。不支持uniCloud-db组件写法
// 可以全部运行,也可以选中部分代码运行。点击工具栏上的运行按钮或者按下【F5】键运行代码
// 如果文档中存在多条JQL语句,只有最后一条语句生效
// 如果混写了普通js,最后一条语句需是数据库操作语句
// 此处代码运行不受DB Schema的权限控制,移植代码到实际业务中注意在schema中配好permission
// 不支持clientDB的action
// 数据库查询有最大返回条数限制,详见:https://uniapp.dcloud.net.cn/uniCloud/cf-database.html#limit
// 详细JQL语法,请参考:https://uniapp.dcloud.net.cn/uniCloud/jql.html
// 下面示例查询uni-id-users表的所有数据
db.collection('uni-id-users').get();
... ...
## 0.0.3(2022-11-11)
- 修复 config 方法获取根节点为数组格式配置时错误的转化为了对象的Bug
## 0.0.2(2021-04-16)
- 修改插件package信息
## 0.0.1(2021-03-15)
- 初始化项目
... ...
{
"id": "uni-config-center",
"displayName": "uni-config-center",
"version": "0.0.3",
"description": "uniCloud 配置中心",
"keywords": [
"配置",
"配置中心"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "unicloud-template-function"
},
"directories": {
"example": "../../../scripts/dist"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "u"
}
}
}
}
}
... ...
# 为什么使用uni-config-center
实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ ├─index.js
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b // plugin-b对应的目录
├─index.js
└─config.json // plugin-b对应的配置文件
```
假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。
uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ └─index.js
├─plugin-b // plugin-b对应的目录
│ └─index.js
└─uni-config-center
├─index.js // config-center入口文件
├─plugin-a
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b
└─config.json // plugin-b对应的配置文件
```
使用uni-config-center后的优势
- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便
- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持)
# 用法
在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
```js
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
pluginId: 'uni-id', // 插件id
defaultConfig: { // 默认配置
tokenExpiresIn: 7200,
tokenExpiresThreshold: 600,
},
customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并
// defaudltConfig 默认配置
// userConfig 用户配置
return Object.assign(defaultConfig, userConfig)
}
})
// 以如下配置为例
// {
// "tokenExpiresIn": 7200,
// "passwordErrorLimit": 6,
// "bindTokenToDevice": false,
// "passwordErrorRetryTime": 3600,
// "app-plus": {
// "tokenExpiresIn": 2592000
// },
// "service": {
// "sms": {
// "codeExpiresIn": 300
// }
// }
// }
// 获取配置
uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象
uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200
uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300
uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600
// 获取文件绝对路径
uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径
// 引用文件(require)
uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。
// 判断是否包含某文件
uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在
```
\ No newline at end of file
... ...
"use strict";var t=require("fs"),r=require("path");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t),o=e(r),i="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var u=function(t){var r={exports:{}};return t(r,r.exports),r.exports}((function(t,r){var e="__lodash_hash_undefined__",n=9007199254740991,o="[object Arguments]",u="[object Function]",c="[object Object]",a=/^\[object .+?Constructor\]$/,f=/^(?:0|[1-9]\d*)$/,s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s[o]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s[u]=s["[object Map]"]=s["[object Number]"]=s[c]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1;var l="object"==typeof i&&i&&i.Object===Object&&i,h="object"==typeof self&&self&&self.Object===Object&&self,p=l||h||Function("return this")(),_=r&&!r.nodeType&&r,v=_&&t&&!t.nodeType&&t,d=v&&v.exports===_,y=d&&l.process,g=function(){try{var t=v&&v.require&&v.require("util").types;return t||y&&y.binding&&y.binding("util")}catch(t){}}(),b=g&&g.isTypedArray;function j(t,r,e){switch(e.length){case 0:return t.call(r);case 1:return t.call(r,e[0]);case 2:return t.call(r,e[0],e[1]);case 3:return t.call(r,e[0],e[1],e[2])}return t.apply(r,e)}var w,O,m,A=Array.prototype,z=Function.prototype,M=Object.prototype,x=p["__core-js_shared__"],C=z.toString,F=M.hasOwnProperty,U=(w=/[^.]+$/.exec(x&&x.keys&&x.keys.IE_PROTO||""))?"Symbol(src)_1."+w:"",S=M.toString,I=C.call(Object),P=RegExp("^"+C.call(F).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),T=d?p.Buffer:void 0,q=p.Symbol,E=p.Uint8Array,$=T?T.allocUnsafe:void 0,D=(O=Object.getPrototypeOf,m=Object,function(t){return O(m(t))}),k=Object.create,B=M.propertyIsEnumerable,N=A.splice,L=q?q.toStringTag:void 0,R=function(){try{var t=vt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),G=T?T.isBuffer:void 0,V=Math.max,W=Date.now,H=vt(p,"Map"),J=vt(Object,"create"),K=function(){function t(){}return function(r){if(!xt(r))return{};if(k)return k(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Q(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function X(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function Z(t){var r=this.__data__=new X(t);this.size=r.size}function tt(t,r){var e=Ot(t),n=!e&&wt(t),o=!e&&!n&&At(t),i=!e&&!n&&!o&&Ft(t),u=e||n||o||i,c=u?function(t,r){for(var e=-1,n=Array(t);++e<t;)n[e]=r(e);return n}(t.length,String):[],a=c.length;for(var f in t)!r&&!F.call(t,f)||u&&("length"==f||o&&("offset"==f||"parent"==f)||i&&("buffer"==f||"byteLength"==f||"byteOffset"==f)||dt(f,a))||c.push(f);return c}function rt(t,r,e){(void 0!==e&&!jt(t[r],e)||void 0===e&&!(r in t))&&ot(t,r,e)}function et(t,r,e){var n=t[r];F.call(t,r)&&jt(n,e)&&(void 0!==e||r in t)||ot(t,r,e)}function nt(t,r){for(var e=t.length;e--;)if(jt(t[e][0],r))return e;return-1}function ot(t,r,e){"__proto__"==r&&R?R(t,r,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[r]=e}Q.prototype.clear=function(){this.__data__=J?J(null):{},this.size=0},Q.prototype.delete=function(t){var r=this.has(t)&&delete this.__data__[t];return this.size-=r?1:0,r},Q.prototype.get=function(t){var r=this.__data__;if(J){var n=r[t];return n===e?void 0:n}return F.call(r,t)?r[t]:void 0},Q.prototype.has=function(t){var r=this.__data__;return J?void 0!==r[t]:F.call(r,t)},Q.prototype.set=function(t,r){var n=this.__data__;return this.size+=this.has(t)?0:1,n[t]=J&&void 0===r?e:r,this},X.prototype.clear=function(){this.__data__=[],this.size=0},X.prototype.delete=function(t){var r=this.__data__,e=nt(r,t);return!(e<0)&&(e==r.length-1?r.pop():N.call(r,e,1),--this.size,!0)},X.prototype.get=function(t){var r=this.__data__,e=nt(r,t);return e<0?void 0:r[e][1]},X.prototype.has=function(t){return nt(this.__data__,t)>-1},X.prototype.set=function(t,r){var e=this.__data__,n=nt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this},Y.prototype.clear=function(){this.size=0,this.__data__={hash:new Q,map:new(H||X),string:new Q}},Y.prototype.delete=function(t){var r=_t(this,t).delete(t);return this.size-=r?1:0,r},Y.prototype.get=function(t){return _t(this,t).get(t)},Y.prototype.has=function(t){return _t(this,t).has(t)},Y.prototype.set=function(t,r){var e=_t(this,t),n=e.size;return e.set(t,r),this.size+=e.size==n?0:1,this},Z.prototype.clear=function(){this.__data__=new X,this.size=0},Z.prototype.delete=function(t){var r=this.__data__,e=r.delete(t);return this.size=r.size,e},Z.prototype.get=function(t){return this.__data__.get(t)},Z.prototype.has=function(t){return this.__data__.has(t)},Z.prototype.set=function(t,r){var e=this.__data__;if(e instanceof X){var n=e.__data__;if(!H||n.length<199)return n.push([t,r]),this.size=++e.size,this;e=this.__data__=new Y(n)}return e.set(t,r),this.size=e.size,this};var it,ut=function(t,r,e){for(var n=-1,o=Object(t),i=e(t),u=i.length;u--;){var c=i[it?u:++n];if(!1===r(o[c],c,o))break}return t};function ct(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":L&&L in Object(t)?function(t){var r=F.call(t,L),e=t[L];try{t[L]=void 0;var n=!0}catch(t){}var o=S.call(t);n&&(r?t[L]=e:delete t[L]);return o}(t):function(t){return S.call(t)}(t)}function at(t){return Ct(t)&&ct(t)==o}function ft(t){return!(!xt(t)||function(t){return!!U&&U in t}(t))&&(zt(t)?P:a).test(function(t){if(null!=t){try{return C.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function st(t){if(!xt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=yt(t),e=[];for(var n in t)("constructor"!=n||!r&&F.call(t,n))&&e.push(n);return e}function lt(t,r,e,n,o){t!==r&&ut(r,(function(i,u){if(o||(o=new Z),xt(i))!function(t,r,e,n,o,i,u){var a=gt(t,e),f=gt(r,e),s=u.get(f);if(s)return void rt(t,e,s);var l=i?i(a,f,e+"",t,r,u):void 0,h=void 0===l;if(h){var p=Ot(f),_=!p&&At(f),v=!p&&!_&&Ft(f);l=f,p||_||v?Ot(a)?l=a:Ct(j=a)&&mt(j)?l=function(t,r){var e=-1,n=t.length;r||(r=Array(n));for(;++e<n;)r[e]=t[e];return r}(a):_?(h=!1,l=function(t,r){if(r)return t.slice();var e=t.length,n=$?$(e):new t.constructor(e);return t.copy(n),n}(f,!0)):v?(h=!1,d=f,y=!0?(g=d.buffer,b=new g.constructor(g.byteLength),new E(b).set(new E(g)),b):d.buffer,l=new d.constructor(y,d.byteOffset,d.length)):l=[]:function(t){if(!Ct(t)||ct(t)!=c)return!1;var r=D(t);if(null===r)return!0;var e=F.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&C.call(e)==I}(f)||wt(f)?(l=a,wt(a)?l=function(t){return function(t,r,e,n){var o=!e;e||(e={});var i=-1,u=r.length;for(;++i<u;){var c=r[i],a=n?n(e[c],t[c],c,e,t):void 0;void 0===a&&(a=t[c]),o?ot(e,c,a):et(e,c,a)}return e}(t,Ut(t))}(a):xt(a)&&!zt(a)||(l=function(t){return"function"!=typeof t.constructor||yt(t)?{}:K(D(t))}(f))):h=!1}var d,y,g,b;var j;h&&(u.set(f,l),o(l,f,n,i,u),u.delete(f));rt(t,e,l)}(t,r,u,e,lt,n,o);else{var a=n?n(gt(t,u),i,u+"",t,r,o):void 0;void 0===a&&(a=i),rt(t,u,a)}}),Ut)}function ht(t,r){return bt(function(t,r,e){return r=V(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=V(n.length-r,0),u=Array(i);++o<i;)u[o]=n[r+o];o=-1;for(var c=Array(r+1);++o<r;)c[o]=n[o];return c[r]=e(u),j(t,this,c)}}(t,r,Pt),t+"")}var pt=R?function(t,r){return R(t,"toString",{configurable:!0,enumerable:!1,value:(e=r,function(){return e}),writable:!0});var e}:Pt;function _t(t,r){var e,n,o=t.__data__;return("string"==(n=typeof(e=r))||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?o["string"==typeof r?"string":"hash"]:o.map}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return ft(e)?e:void 0}function dt(t,r){var e=typeof t;return!!(r=null==r?n:r)&&("number"==e||"symbol"!=e&&f.test(t))&&t>-1&&t%1==0&&t<r}function yt(t){var r=t&&t.constructor;return t===("function"==typeof r&&r.prototype||M)}function gt(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var bt=function(t){var r=0,e=0;return function(){var n=W(),o=16-(n-e);if(e=n,o>0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(pt);function jt(t,r){return t===r||t!=t&&r!=r}var wt=at(function(){return arguments}())?at:function(t){return Ct(t)&&F.call(t,"callee")&&!B.call(t,"callee")},Ot=Array.isArray;function mt(t){return null!=t&&Mt(t.length)&&!zt(t)}var At=G||function(){return!1};function zt(t){if(!xt(t))return!1;var r=ct(t);return r==u||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}function Mt(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}function xt(t){var r=typeof t;return null!=t&&("object"==r||"function"==r)}function Ct(t){return null!=t&&"object"==typeof t}var Ft=b?function(t){return function(r){return t(r)}}(b):function(t){return Ct(t)&&Mt(t.length)&&!!s[ct(t)]};function Ut(t){return mt(t)?tt(t,!0):st(t)}var St,It=(St=function(t,r,e){lt(t,r,e)},ht((function(t,r){var e=-1,n=r.length,o=n>1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=St.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!xt(e))return!1;var n=typeof r;return!!("number"==n?mt(e)&&dt(r,e.length):"string"==n&&r in e)&&jt(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e<n;){var u=r[e];u&&St(t,u,e,o)}return t})));function Pt(t){return t}t.exports=It}));const c=Object.prototype.hasOwnProperty,a=(t,r)=>c.call(t,r);class f{constructor({pluginId:t,defaultConfig:r={},customMerge:e,root:n}){this.pluginId=t,this.defaultConfig=r,this.pluginConfigPath=o.default.resolve(n||__dirname,t),this.customMerge=e,this._config=void 0}resolve(t){return o.default.resolve(this.pluginConfigPath,t)}hasFile(t){return n.default.existsSync(this.resolve(t))}requireFile(t){try{return require(this.resolve(t))}catch(t){if("MODULE_NOT_FOUND"===t.code)return;throw t}}_getUserConfig(){return this.requireFile("config.json")}config(t,r){if(!this._config){const t=this._getUserConfig();this._config=Array.isArray(t)?t:(this.customMerge||u)(this.defaultConfig,t)}let e=this._config;return t?function(t,r,e){if("number"==typeof r)return t[r];if("symbol"==typeof r)return a(t,r)?t[r]:e;const n="string"!=typeof(o=r)?o:o.split(".").reduce(((t,r)=>(r.split(/\[([^}]+)\]/g).forEach((r=>r&&t.push(r))),t)),[]);var o;let i=t;for(let t=0;t<n.length;t++){const r=n[t];if(!a(i,r))return e;i=i[r]}return i}(e,t,r):e}}const s=new class{constructor(){this._configMap=new Map}plugin({pluginId:t,defaultConfig:r,customMerge:e,root:n=__dirname,cache:o=!0}){if(this._configMap.has(t)&&o)return this._configMap.get(t);const i=new f({pluginId:t,defaultConfig:r,customMerge:e,root:n});return o&&this._configMap.set(t,i),i}};var l=s.plugin.bind(s);module.exports=l;
... ...
{
"name": "uni-config-center",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
"author": "DCloud",
"license": "Apache-2.0"
}
\ No newline at end of file
... ...
## 1.0.16(2023-04-25)
- 新增maxTokenLength配置,用于限制数据库用户记录token数组的最大长度
## 1.0.15(2023-04-06)
- 修复部分语言国际化出错的Bug
## 1.0.14(2023-03-07)
- 修复 admin用户包含其他角色时未包含在token的Bug
## 1.0.13(2022-07-21)
- 修复 创建token时未传角色权限信息生成的token不正确的bug
## 1.0.12(2022-07-15)
- 提升与旧版本uni-id的兼容性(补充读取配置文件时回退平台app-plus、h5),但是仍推荐使用新平台名进行配置(app、web)
## 1.0.11(2022-07-14)
- 修复 部分情况下报`read property 'reduce' of undefined`的错误
## 1.0.10(2022-07-11)
- 将token存储在用户表的token字段内,与旧版本uni-id保持一致
## 1.0.9(2022-07-01)
- checkToken兼容token内未缓存角色权限的情况,此时将查库获取角色权限
## 1.0.8(2022-07-01)
- 修复clientDB默认依赖时部分情况下获取不到uni-id配置的Bug
## 1.0.7(2022-06-30)
- 修复config文件不合法时未抛出具体错误的Bug
## 1.0.6(2022-06-28)
- 移除插件内的数据表schema
## 1.0.5(2022-06-27)
- 修复使用多应用配置时报`Cannot read property 'appId' of undefined`的Bug
## 1.0.4(2022-06-27)
- 修复使用自定义token内容功能报错的Bug [详情](https://ask.dcloud.net.cn/question/147945)
## 1.0.2(2022-06-23)
- 对齐旧版本uni-id默认配置
## 1.0.1(2022-06-22)
- 补充对uni-config-center的依赖
## 1.0.0(2022-06-21)
- 提供uni-id token创建、校验、刷新接口,简化旧版uni-id公共模块
... ...
{
"id": "uni-id-common",
"displayName": "uni-id-common",
"version": "1.0.16",
"description": "包含uni-id token生成、校验、刷新功能的云函数公共模块",
"keywords": [
"uni-id-common",
"uniCloud",
"token",
"权限"
],
"repository": "https://gitcode.net/dcloud/uni-id-common",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "unicloud-template-function"
},
"uni_modules": {
"dependencies": ["uni-config-center"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
... ...
# uni-id-common
文档请参考:[uni-id-common](https://uniapp.dcloud.net.cn/uniCloud/uni-id-common.html)
\ No newline at end of file
... ...
"use strict";var e,t=(e=require("crypto"))&&"object"==typeof e&&"default"in e?e.default:e;const n={TOKEN_EXPIRED:"uni-id-token-expired",CHECK_TOKEN_FAILED:"uni-id-check-token-failed",PARAM_REQUIRED:"uni-id-param-required",ACCOUNT_EXISTS:"uni-id-account-exists",ACCOUNT_NOT_EXISTS:"uni-id-account-not-exists",ACCOUNT_CONFLICT:"uni-id-account-conflict",ACCOUNT_BANNED:"uni-id-account-banned",ACCOUNT_AUDITING:"uni-id-account-auditing",ACCOUNT_AUDIT_FAILED:"uni-id-account-audit-failed",ACCOUNT_CLOSED:"uni-id-account-closed"};function i(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof e.then}function r(e){if(!e)return;const t=e.match(/^(\d+).(\d+).(\d+)/);return t?t.slice(1,4).map(e=>parseInt(e)):void 0}function o(e,t){const n=r(e),i=r(t);return n?i?function(e,t){const n=Math.max(e.length,t.length);for(let i=0;i<n;i++){const n=e[i],r=t[i];if(n>r)return 1;if(n<r)return-1}return 0}(n,i):1:i?-1:0}const s={"uni-id-token-expired":30203,"uni-id-check-token-failed":30202};function c(e){const{errCode:t,errMsgValue:n}=e;e.errMsg=this._t(t,n),t in s&&(e.code=s[t]),delete e.errMsgValue}function a(e){return"object"===(i=e,Object.prototype.toString.call(i).slice(8,-1).toLowerCase())&&e.errCode&&(t=e.errCode,Object.values(n).includes(t))&&!!e.errCode;var t,i}let u={"zh-Hans":{"uni-id-token-expired":"登录状态失效,token已过期","uni-id-check-token-failed":"token校验未通过","uni-id-param-required":"缺少参数: {param}","uni-id-account-exists":"此账号已注册","uni-id-account-not-exists":"此账号未注册","uni-id-account-conflict":"用户账号冲突","uni-id-account-banned":"从账号已封禁","uni-id-account-auditing":"此账号正在审核中","uni-id-account-audit-failed":"此账号审核失败","uni-id-account-closed":"此账号已注销"},en:{"uni-id-token-expired":"The login status is invalid, token has expired","uni-id-check-token-failed":"Check token failed","uni-id-param-required":"Parameter required: {param}","uni-id-account-exists":"Account exists","uni-id-account-not-exists":"Account does not exists","uni-id-account-conflict":"User account conflict","uni-id-account-banned":"Account has been banned","uni-id-account-auditing":"Account audit in progress","uni-id-account-audit-failed":"Account audit failed","uni-id-account-closed":"Account has been closed"}};try{const e=require.resolve("uni-config-center/uni-id/lang/index.js");u=function(e,t){const n=Object.keys(e);n.push(...Object.keys(t));const i={};for(let r=0;r<n.length;r++){const o=n[r];i[o]=Object.assign({},e[o],t[o])}return i}(u,require(e))}catch(e){}var d=u;function l(e){return e.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function h(e){return JSON.parse((t=function(e){var t=4-(e=e.toString()).length%4;if(4!==t)for(var n=0;n<t;++n)e+="=";return e.replace(/-/g,"+").replace(/_/g,"/")}(e),Buffer.from(t,"base64").toString("utf-8")));var t}function f(e){return l((t=JSON.stringify(e),Buffer.from(t,"utf-8").toString("base64")));var t}function p(e,n){return l(t.createHmac("sha256",n).update(e).digest("base64"))}const k=function(e,t){if("string"!=typeof e)throw new Error("Invalid token");const n=e.split(".");if(3!==n.length)throw new Error("Invalid token");const[i,r,o]=n;if(p(i+"."+r,t)!==o)throw new Error("Invalid token");const s=h(i);if("HS256"!==s.alg||"JWT"!==s.typ)throw new Error("Invalid token");const c=h(r);if(1e3*c.exp<Date.now()){const e=new Error("Token expired");throw e.name="TokenExpiredError",e}return c},g=function(e,t,n={}){const{expiresIn:i}=n;if(!i)throw new Error("expiresIn is required");const r=parseInt(Date.now()/1e3),o={...e,iat:r,exp:r+n.expiresIn},s=f({alg:"HS256",typ:"JWT"})+"."+f(o);return s+"."+p(s,t)},I=uniCloud.database(),_=I.command,C=I.collection("uni-id-users"),T=I.collection("uni-id-roles");class m{constructor({uniId:e}={}){this.uid=null,this.userRecord=null,this.userPermission=null,this.oldToken=null,this.oldTokenPayload=null,this.uniId=e,this.config=this.uniId._getConfig(),this.clientInfo=this.uniId._clientInfo,this.checkConfig()}checkConfig(){const{tokenExpiresIn:e,tokenExpiresThreshold:t}=this.config;if(t>=e)throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn");t>e/2&&console.warn(`Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${t}, tokenExpiresIn: ${e}`)}get customToken(){return this.uniId.interceptorMap.get("customToken")}isTokenInDb(e){return o(e,"1.0.10")>=0}async getUserRecord(){if(this.userRecord)return this.userRecord;const e=await C.doc(this.uid).get();if(this.userRecord=e.data[0],!this.userRecord)throw{errCode:n.ACCOUNT_NOT_EXISTS};switch(this.userRecord.status){case void 0:case 0:break;case 1:throw{errCode:n.ACCOUNT_BANNED};case 2:throw{errCode:n.ACCOUNT_AUDITING};case 3:throw{errCode:n.ACCOUNT_AUDIT_FAILED};case 4:throw{errCode:n.ACCOUNT_CLOSED}}if(this.oldTokenPayload){if(this.isTokenInDb(this.oldTokenPayload.uniIdVersion)){if(-1===(this.userRecord.token||[]).indexOf(this.oldToken))throw{errCode:n.CHECK_TOKEN_FAILED}}if(this.userRecord.valid_token_date&&this.userRecord.valid_token_date>1e3*this.oldTokenPayload.iat)throw{errCode:n.TOKEN_EXPIRED}}return this.userRecord}async updateUserRecord(e){await C.doc(this.uid).update(e)}async getUserPermission(){if(this.userPermission)return this.userPermission;const e=(await this.getUserRecord()).role||[];if(0===e.length)return this.userPermission={role:[],permission:[]},this.userPermission;if(e.includes("admin"))return this.userPermission={role:e,permission:[]},this.userPermission;const t=await T.where({role_id:_.in(e)}).get(),n=(i=t.data.reduce((e,t)=>(t.permission&&e.push(...t.permission),e),[]),Array.from(new Set(i)));var i;return this.userPermission={role:e,permission:n},this.userPermission}async _createToken({uid:e,role:t,permission:i}={}){if(!t||!i){const e=await this.getUserPermission();t=e.role,i=e.permission}let r={uid:e,role:t,permission:i};if(this.uniId.interceptorMap.has("customToken")){const n=this.uniId.interceptorMap.get("customToken");if("function"!=typeof n)throw new Error("Invalid custom token file");r=await n({uid:e,role:t,permission:i})}const o=Date.now(),{tokenSecret:s,tokenExpiresIn:c,maxTokenLength:a=10}=this.config,u=g({...r,uniIdVersion:"1.0.16"},s,{expiresIn:c}),d=await this.getUserRecord(),l=(d.token||[]).filter(e=>{try{const t=this._checkToken(e);if(d.valid_token_date&&d.valid_token_date>1e3*t.iat)return!1}catch(e){if(e.errCode===n.TOKEN_EXPIRED)return!1}return!0});return l.push(u),l.length>a&&l.splice(0,l.length-a),await this.updateUserRecord({last_login_ip:this.clientInfo.clientIP,last_login_date:o,token:l}),{token:u,tokenExpired:o+1e3*c}}async createToken({uid:e,role:t,permission:i}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"uid"}};this.uid=e;const{token:r,tokenExpired:o}=await this._createToken({uid:e,role:t,permission:i});return{errCode:0,token:r,tokenExpired:o}}async refreshToken({token:e}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const t=this._checkToken(e);this.uid=t.uid,this.oldTokenPayload=t;const{uid:i}=t,{role:r,permission:o}=await this.getUserPermission(),{token:s,tokenExpired:c}=await this._createToken({uid:i,role:r,permission:o});return{errCode:0,token:s,tokenExpired:c}}_checkToken(e){const{tokenSecret:t}=this.config;let i;try{i=k(e,t)}catch(e){if("TokenExpiredError"===e.name)throw{errCode:n.TOKEN_EXPIRED};throw{errCode:n.CHECK_TOKEN_FAILED}}return i}async checkToken(e,{autoRefresh:t=!0}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const i=this._checkToken(e);this.uid=i.uid,this.oldTokenPayload=i;const{tokenExpiresThreshold:r}=this.config,{uid:o,role:s,permission:c}=i,a={role:s,permission:c};if(!s&&!c){const{role:e,permission:t}=await this.getUserPermission();a.role=e,a.permission=t}if(!r||!t){const e={code:0,errCode:0,...i,...a};return delete e.uniIdVersion,e}const u=Date.now();let d={};1e3*i.exp-u<1e3*r&&(d=await this._createToken({uid:o}));const l={code:0,errCode:0,...i,...a,...d};return delete l.uniIdVersion,l}}var E=Object.freeze({__proto__:null,checkToken:async function(e,{autoRefresh:t=!0}={}){return new m({uniId:this}).checkToken(e,{autoRefresh:t})},createToken:async function({uid:e,role:t,permission:n}={}){return new m({uniId:this}).createToken({uid:e,role:t,permission:n})},refreshToken:async function({token:e}={}){return new m({uniId:this}).refreshToken({token:e})}});const w=require("uni-config-center")({pluginId:"uni-id"});class x{constructor({context:e,clientInfo:t,config:n}={}){this._clientInfo=e?function(e){return{appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,deviceId:e.DEVICEID}}(e):t,this.config=n||this._getOriginConfig(),this.interceptorMap=new Map,w.hasFile("custom-token.js")&&this.setInterceptor("customToken",require(w.resolve("custom-token.js")));this._i18n=uniCloud.initI18n({locale:this._clientInfo.locale,fallbackLocale:"zh-Hans",messages:JSON.parse(JSON.stringify(d))}),d[this._i18n.locale]||this._i18n.setLocale("zh-Hans")}setInterceptor(e,t){this.interceptorMap.set(e,t)}_t(...e){return this._i18n.t(...e)}_parseOriginConfig(e){return Array.isArray(e)?e:e[0]?Object.values(e):e}_getOriginConfig(){if(w.hasFile("config.json")){let e;try{e=w.config()}catch(e){throw new Error("Invalid uni-id config file\n"+e.message)}return this._parseOriginConfig(e)}try{return this._parseOriginConfig(require("uni-id/config.json"))}catch(e){throw new Error("Invalid uni-id config file")}}_getAppConfig(){const e=this._getOriginConfig();return Array.isArray(e)?e.find(e=>e.dcloudAppid===this._clientInfo.appId)||e.find(e=>e.isDefaultConfig):e}_getPlatformConfig(){const e=this._getAppConfig();if(!e)throw new Error(`Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId`);let t;switch("app-plus"===this._clientInfo.platform&&(this._clientInfo.platform="app"),"h5"===this._clientInfo.platform&&(this._clientInfo.platform="web"),this._clientInfo.platform){case"web":t="h5";break;case"app":t="app-plus"}const n=[{tokenExpiresIn:7200,tokenExpiresThreshold:1200,passwordErrorLimit:6,passwordErrorRetryTime:3600},e];t&&e[t]&&n.push(e[t]),n.push(e[this._clientInfo.platform]);const i=Object.assign(...n);return["tokenSecret","tokenExpiresIn"].forEach(e=>{if(!i||!i[e])throw new Error(`Config parameter missing, ${e} is required`)}),i}_getConfig(){return this._getPlatformConfig()}}for(const e in E)x.prototype[e]=E[e];function y(e){const t=new x(e);return new Proxy(t,{get(e,t){if(t in e&&0!==t.indexOf("_")){if("function"==typeof e[t])return(n=e[t],function(){let e;try{e=n.apply(this,arguments)}catch(e){if(a(e))return c.call(this,e),e;throw e}return i(e)?e.then(e=>(a(e)&&c.call(this,e),e),e=>{if(a(e))return c.call(this,e),e;throw e}):(a(e)&&c.call(this,e),e)}).bind(e);if("context"!==t&&"config"!==t)return e[t]}var n}})}x.prototype.createInstance=y;const A={createInstance:y};module.exports=A;
... ...
{
"name": "uni-id-common",
"version": "1.0.16",
"description": "uni-id token生成、校验、刷新",
"main": "index.js",
"homepage": "https://uniapp.dcloud.io/uniCloud/uni-id-common.html",
"repository": {
"type": "git",
"url": "git+https://gitee.com/dcloud/uni-id-common.git"
},
"author": "DCloud",
"license": "Apache-2.0",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}
\ No newline at end of file
... ...