修缮登录逻辑

This commit is contained in:
田岩
2025-06-23 20:57:34 +08:00
parent c6d6e3a99a
commit 4f78ab3f99
46 changed files with 313 additions and 226 deletions
+5
View File
@@ -57,7 +57,12 @@ export function previewFile(id,responseType = 'arraybuffer') {
responseType,
success(result) {
console.log(result)
// #ifdef APP-PLUS
let _header = result.header['Content-Type'].split(';')[0]
// #endif
// #ifndef APP-PLUS
let _header = result.header['content-type'].split(';')[0]
// #endif
// let base64 = new Blob([result.data],{type:result.header['content-type'].split(';')[0]})
let base64 = `data:${_header};base64,` + uni.arrayBufferToBase64(result.data)
resolve(base64)
+4 -2
View File
@@ -1,8 +1,7 @@
import request from '@/api/request'
import common from "@/common/common";
import {setToken, setUserInfo} from "@/common/common";
const setToken = data => uni.setStorageSync('token', data)
const setUserInfo = data => uni.setStorageSync('userInfo', data)
// 账号登录接口
export const useAccountLoginApp = (data) => request({
@@ -63,4 +62,7 @@ export const loginOut = (data) => request({
url: '/traapp/access/loginOut',
method: 'post',
data
}).then(() =>{
setToken(null)
setUserInfo(null)
})
+2 -1
View File
@@ -104,7 +104,8 @@ const formatDate2 = (timestamp, format = 'yyyy-MM-dd HH:mm:ss') => {
// 获取token
export const getToken = () => uni.getStorageSync('token')
export const setToken = data => uni.setStorageSync('token', data)
export const setUserInfo = data => uni.setStorageSync('userInfo', data)
export const getUserInfo = (key = '') => {
const userInfo = uni.getStorageSync('userInfo')
return '' === key ? userInfo : userInfo[key];
+3
View File
@@ -2,3 +2,6 @@
MaxUploadPictureSize = 2048 // 最大图片上传限制
MaxUploadDocumentMaxSize = 102400 // 最大文档上传限制
500
@@ -60,7 +60,6 @@
<script setup>
import ImagePreview from '@/components/image-preview/image-preview.vue'
import VideoPreview from '@/components/image-preview/video-preview.vue'
import { defineProps } from 'vue';
const props = defineProps({
type:{
default: 0,// 1 userAnswer 0: AIAnswer
@@ -36,15 +36,15 @@
qryTraCrsBbsDataByCrsNum
} from '@/api/courseDetail.js';
const message_list = reactive([
const message_list = ref([
])
const props = defineProps({
crsNum:String
})
onMounted(() => {
qryTraCrsBbsDataByCrsNum({crsNum:props.crsNum}).then(() => {
qryTraCrsBbsDataByCrsNum({crsNum:props.crsNum}).then(({body}) => {
message_list.value = body
})
})
</script>
+6 -5
View File
@@ -21,6 +21,7 @@
<view class="body-tab">
<uv-tabs
class="font_pf"
:current="tabAct"
:list="tabList"
@change="tabSwitch"
:scrollable="false"
@@ -47,7 +48,7 @@
<uv-button type="primary">去考试</uv-button>
</template>
<template v-if="tabAct == 2">
<uv-button type="primary" class="send_evaluate">发布评价</uv-button>
<uv-button type="primary" class="send_evaluate" @click="common.navigateTo('/pages/courseDetail/submit?crsNum='+crsNum)">发布评价</uv-button>
</template>
</view>
@@ -60,15 +61,15 @@ import { onLoad } from '@dcloudio/uni-app';
import { getCourseDetailApi } from '@/api/courseDetail.js';
// import {formatDate2} from '@/common/common.js'
import common from '@/common/common';
import introduceVue from './introduce.vue';
import knowledge from './knowledge.vue';
import comment from './comment.vue';
import introduceVue from './components/introduce.vue';
import knowledge from './components/knowledge.vue';
import comment from './components/comment.vue';
// tab栏
const tabList = ref([{ name: '课程介绍' }, { name: '知识点' }, { name: '评价' }]);
const form = ref({});
const crsNum = ref('');
const tabAct = ref(0);
const tabAct = ref(2);
const tabSwitch = (item) => {
tabAct.value = item.index;
};
+210 -158
View File
@@ -22,7 +22,8 @@
<view class="num-box">
<view class="font_pf fz-28 c-666">综合评分</view>
<view class="slider-box">
<uv-slider step="1" activeColor="#0066FF" :blockSize="14" v-model="num" min="0" max="10"></uv-slider>
<uv-slider step="1" activeColor="#0066FF" :blockSize="14" v-model="formData.bbsGrade"
:min="0" :max="10"></uv-slider>
</view>
<view class="flex-jcsb">
<view class="font_pf fz-30 c-000">0</view>
@@ -31,186 +32,237 @@
</view>
</view>
<view class="tab">
<view class="tab-btn" :class="activeTab == 1 ? 'is-active' : ''" @click="changeTab(1)">建议</view>
<view class="tab-btn" :class="activeTab == 2 ? 'is-active' : ''" @click="changeTab(2)">提问</view>
<view class="tab-btn" :class="{'is-active':formData.bbsTag=='SUG'}" @click="formData.bbsTag='SUG'">
建议</view>
<view class="tab-btn" :class="{'is-active':formData.bbsTag=='ASK'}" @click="formData.bbsTag='ASK'">
提问</view>
</view>
<view class="input-textarea">
<uv-textarea v-model="aaa" height="124" :placeholder="activeTab == 1?'请输入你的建议...':'请输入你的问题...'"></uv-textarea>
<uv-textarea v-model="formData.bbsContent" height="124" count
:placeholder="formData.bbsTag == 'SUG'?'请输入你的建议...':'请输入你的问题...'"></uv-textarea>
</view>
</view>
</view>
<view class="btn-box font_pf">
<uv-button type="primary">去学习</uv-button>
<uv-button type="primary" @click="submit">提交评价</uv-button>
</view>
</view>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { getCourseDetailApi } from '@/api/courseDetail.js';
// import {formatDate2} from '@/common/common.js'
import common from '@/common/common';
const num = ref(0);
const activeTab = ref(1);
const aaa = ref('')
const changeTab = (type) => {
activeTab.value = type;
};
// tab栏
onLoad((params) => {});
import {
reactive,
ref
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import {
publishCrsEvaluation
} from '@/api/courseDetail.js';
import common from '@/common/common';
const formData = reactive({
"crsNum": null,
"imgIdList": [], // 发表图片ID列表,文件ID集
"bbsGrade": 10, // 综合评分(最高10分)
"bbsTag": 'SUG', // 评价标签 (SUG 建议 ASK 提问 )
"bbsContent": '', // 评价内容
})
const submit = () => {
if (formData.bbsContent === '') {
if (formData.bbsTag == 'SUG') {
return common.msg('请输入你的建议')
} else {
return common.msg('请输入你的问题')
}
}
publishCrsEvaluation(formData).then(res => {
common.msg('发表成功')
setTimeout(() => common.navigateBack(), 500)
})
}
onLoad((params) => {
formData.crsNum = params.crsNum;
});
</script>
<style lang="scss" scoped>
.detail-main {
background-color: #f6f8ff;
}
.detail-body {
box-sizing: border-box;
min-height: calc(100vh - (var(--status-bar-height)+50rpx));
padding: 29rpx 37rpx;
width: 100%;
display: flex;
flex-direction: column;
}
.title {
color: #000000;
font-size: 34rpx;
height: 34rpx;
font-weight: 600;
margin-bottom: 30rpx;
}
.body-content {
flex: 1;
background-color: #ffffff;
border-radius: 15rpx;
padding: 36rpx;
}
.picture {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.pic-item {
width: 170rpx;
height: 170rpx;
border-radius: 8rpx;
background-color: red;
margin-bottom: 24rpx;
}
.tips {
color: #666666;
font-size: 24rpx;
margin-bottom: 28rpx;
}
.num {
display: flex;
width: 100%;
// height: 92rpx;
justify-content: space-between;
margin-bottom: 40rpx;
}
.num-pic {
width: 92rpx;
height: 92rpx;
padding-top: 20rpx;
margin-right: 20rpx;
}
.num-box {
flex: 1;
display: flex;
// height: 100%;
justify-content: space-between;
flex-direction: column;
}
.slider-box {
width: 100%;
:deep(.uv-slider) {
.detail-main {
background-color: #f6f8ff;
}
.detail-body {
box-sizing: border-box;
min-height: calc(100vh - (var(--status-bar-height)+50rpx));
padding: 29rpx 37rpx;
width: 100%;
display: flex;
flex-direction: column;
}
:deep(uni-slider) {
margin: 0 16rpx 10rpx 0;
.title {
color: #000000;
font-size: 34rpx;
height: 34rpx;
font-weight: 600;
margin-bottom: 30rpx;
}
:deep(.uni-slider-tap-area) {
padding: 10rpx 0;
.body-content {
flex: 1;
background-color: #ffffff;
border-radius: 15rpx;
padding: 36rpx;
}
:deep(.uni-slider-thumb) {
border: 2px solid #0066ff;
.picture {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
}
.tab {
display: flex;
margin-bottom: 30rpx;
}
.tab-btn {
width: 78rpx;
height: 36rpx;
font-size: 22rpx;
color: #999999;
text-align: center;
border-radius: 8rpx;
border: 2rpx solid #999999;
margin-right: 30rpx;
}
.is-active {
color: #0066ff;
border: 2rpx solid #0066ff;
}
.input-textarea{
// height: 250rpx;
// padding-bottom: 250rpx;
}
.btn-box {
position: fixed;
bottom: 0;
// height: 187rpx;
width: 100%;
display: flex;
padding-bottom: 30rpx;
justify-content: space-evenly;
:deep(.uv-button) {
border-radius: 14rpx;
width: 616rpx;
height: 80rpx;
.pic-item {
width: 170rpx;
height: 170rpx;
border-radius: 8rpx;
background-color: red;
margin-bottom: 24rpx;
}
}
.c-666 {
color: #666666;
}
.c-000 {
font-weight: 600;
color: #000;
}
.fixed_search_div {
padding: calc(10rpx + var(--status-bar-height)) 15rpx 24rpx 30rpx;
display: flex;
align-items: center;
.back_div {
margin-right: 10rpx;
.back-icon {
position: relative;
width: 40rpx;
height: 40rpx;
cursor: pointer;
.tips {
color: #666666;
font-size: 24rpx;
margin-bottom: 28rpx;
}
.num {
display: flex;
width: 100%;
// height: 92rpx;
justify-content: space-between;
margin-bottom: 40rpx;
}
.num-pic {
width: 92rpx;
height: 92rpx;
padding-top: 20rpx;
margin-right: 20rpx;
}
.num-box {
flex: 1;
display: flex;
// height: 100%;
justify-content: space-between;
flex-direction: column;
}
.slider-box {
width: 100%;
:deep(.uv-slider) {
width: 100%;
}
.back-icon::before,
.back-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
:deep(uni-slider) {
margin: 0 16rpx 10rpx 0;
}
.back-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #2b2c2e;
border-left: 4rpx solid #2b2c2e;
transform: rotate(-45deg);
:deep(.uni-slider-tap-area) {
padding: 10rpx 0;
}
:deep(.uni-slider-thumb) {
border: 2px solid #0066ff;
}
}
}
</style>
.tab {
display: flex;
margin-bottom: 30rpx;
}
.tab-btn {
width: 78rpx;
height: 36rpx;
font-size: 22rpx;
color: #999999;
text-align: center;
border-radius: 8rpx;
border: 2rpx solid #999999;
margin-right: 30rpx;
}
.is-active {
color: #0066ff;
border: 2rpx solid #0066ff;
}
.input-textarea {
// height: 250rpx;
// padding-bottom: 250rpx;
}
.btn-box {
position: fixed;
bottom: 0;
// height: 187rpx;
width: 100%;
display: flex;
padding-bottom: 30rpx;
justify-content: space-evenly;
:deep(.uv-button) {
border-radius: 14rpx;
width: 616rpx;
height: 80rpx;
}
}
.c-666 {
color: #666666;
}
.c-000 {
font-weight: 600;
color: #000;
}
.fixed_search_div {
padding: calc(10rpx + var(--status-bar-height)) 15rpx 24rpx 30rpx;
display: flex;
align-items: center;
.back_div {
margin-right: 10rpx;
.back-icon {
position: relative;
width: 40rpx;
height: 40rpx;
cursor: pointer;
}
.back-icon::before,
.back-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
}
.back-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #2b2c2e;
border-left: 4rpx solid #2b2c2e;
transform: rotate(-45deg);
}
}
}
</style>
+42 -32
View File
@@ -45,7 +45,8 @@
color="rgba(255,255,255,0.7)" :speed="40" direction="column"></uv-notice-bar>
</view>
<!-- 学习时长和飞天兔子为了挡住部分兔子只能多一个盒子 -->
<view class="study_duration_and_profile_div" @click="common.navigateTo('/pages/courseDetail/index?crsNum=meirenmaixiyinchenque')">
<view class="study_duration_and_profile_div"
@click="common.navigateTo('/pages/courseDetail/index?crsNum=meirenmaixiyinchenque')">
<!-- 飞天兔子 -->
<view class="profile_div">
<image src="/static/images/index/fttz.png" class="profile"></image>
@@ -55,20 +56,23 @@
<view class="item">
<view class="top">本年学习时长</view>
<view class="bottom">
<uv-count-to :startVal="statistics_data['stdtTmLen']" :endVal="statistics_data['stdtTmLen']" :useEasing="true" :decimals="1"></uv-count-to>h
<uv-count-to :startVal="statistics_data['stdtTmLen']" :endVal="statistics_data['stdtTmLen']"
:useEasing="true" :decimals="1"></uv-count-to>h
</view>
</view>
<view class="item">
<view class="top">累计训练次数</view>
<view class="bottom">
<uv-count-to :startVal="statistics_data['accmExamCnt']" :endVal="statistics_data['accmExamCnt']" :useEasing="true"></uv-count-to><span
<uv-count-to :startVal="statistics_data['accmExamCnt']"
:endVal="statistics_data['accmExamCnt']" :useEasing="true"></uv-count-to><span
class="number"></span>
</view>
</view>
<view class="item">
<view class="top">累计考试次数</view>
<view class="bottom"><uv-count-to :startVal="statistics_data['accmPracticeCnt']" :endVal="statistics_data['accmPracticeCnt']"
:useEasing="true"></uv-count-to><span class="number"></span>
<view class="bottom"><uv-count-to :startVal="statistics_data['accmPracticeCnt']"
:endVal="statistics_data['accmPracticeCnt']" :useEasing="true"></uv-count-to><span
class="number"></span>
</view>
</view>
</view>
@@ -127,7 +131,7 @@
<uv-skeleton :loading="!item.crsNum" :rows="3" avatar avatar-shape="square" :title="false">
<view class="item" @click="goto_course_detail(item.crsNum)">
<view class="left">
<image-preview class="img-box img" :imgId="item.imgId"></image-preview>
<image-preview class="img-box img" :imgId="item.imgThumbId"></image-preview>
</view>
<view class="right">
<view class="title ellipsis-text">{{item.crsName}}</view>
@@ -160,7 +164,7 @@
<uv-skeleton :loading="!item.crsNum" :rows="3" avatar avatar-shape="square" :title="false">
<view class="item" @click="goto_course_detail(item.crsNum)">
<view class="left">
<image-preview class="img-box img" :imgId="item.imgId"></image-preview>
<image-preview class="img-box img" :imgId="item.imgThumbId"></image-preview>
</view>
<view class="right">
<view class="title ellipsis-text">{{item.crsName}}</view>
@@ -192,7 +196,7 @@
<uv-skeleton :loading="!item.crsNum" :rows="3" avatar avatar-shape="square" :title="false">
<view class="item" @click="goto_course_detail(item.crsNum)">
<view class="left">
<image-preview class="img-box img" :imgId="item.imgId"></image-preview>
<image-preview class="img-box img" :imgId="item.imgThumbId"></image-preview>
</view>
<view class="right">
<view class="title ellipsis-text">{{item.crsName}}</view>
@@ -219,16 +223,17 @@
</template>
<script setup>
import {
computed,
onBeforeMount,
onMounted,
reactive,
ref
} from 'vue'
import {
onShow,
onPageScroll
onPageScroll,
onLoad
} from '@dcloudio/uni-app'
import {
customStyles,
@@ -258,27 +263,25 @@
})
// 滚动消息
const notice_text = ref(['绿色金融政策解析与商业银行绿色水水水水水水水水水水水水水', '绿色金融政策解析与商业银行红色'])
const init_class_data = [
{
crsNum: '',
img: '',
crsName: '',
issuTm: '',
accmStdyCnt: ''
}, {
crsNum: '',
img: '',
crsName: '',
issuTm: '',
accmStdyCnt: ''
}
]
const init_class_data = [{
crsNum: '',
img: '',
crsName: '',
issuTm: '',
accmStdyCnt: ''
}, {
crsNum: '',
img: '',
crsName: '',
issuTm: '',
accmStdyCnt: ''
}]
// 热门课程
const hot_class_list = ref([...init_class_data])
const new_class_list = ref([...init_class_data])
const recommend_class_list = ref([...init_class_data])
const statistics_data = reactive({
'stdtTmLen': 0, // 学习
'accmPracticeCnt': 0, // 训练
@@ -288,7 +291,7 @@
'start_exam': 0, //起始考试
'request_time': 0, //上次请求时间
})
// 获取首页统计数据方法
const get_statistics_data = async () => {
@@ -301,21 +304,25 @@
// if (time_now - statistics_data['request_time'] > 600 * 1000) {
// statistics_data['request_time'] = time_now
// const data = await getStatisticsData()
// console.log(data);
// }
}
// 进入搜索页
const goto_search_page = () => {
common.navigateTo('/pages/search/search')
}
// 进入课程详情页
const goto_course_detail = (crsNum) => {
common.navigateTo('/pages/courseDetail/index?crsNum='+crsNum)
common.navigateTo('/pages/courseDetail/index?crsNum=' + crsNum)
}
onShow(() => {
if(!common.isLogin()){
console.log('222')
common.navigateTo('/pages/login/login')
return
}
get_statistics_data() // 获取首页统计数据
})
onMounted(async () => {
@@ -328,6 +335,8 @@
queryCrsInfoByRecmd().then(res => {
recommend_class_list.value = res.body
})
// 预加载我的页
})
</script>
@@ -487,6 +496,7 @@
display: flex;
align-items: center;
border-bottom: 4rpx solid #efefef;
.fixed_search_input_div {
flex: 1;
}
+19 -11
View File
@@ -66,16 +66,17 @@
<script lang="ts" setup>
// import { v4 as uuid4 } from 'uuid'
import { ref, computed, onMounted } from 'vue'
import {onBackPress} from '@dcloudio/uni-app'
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import common from '@/common/common'
import { useAccountLoginApp, queryCurrentUser } from '@/api/login.js'
import { encryptByAES } from '@/api/encryptAndDecryptData.js'
const show_password = ref<Boolean>(false)
const account = ref<string>('')
const password = ref<string>('')
const read_text_state = ref<Array<unknown>>([])
const back_state = ref(true)
// 登录按钮状态
const login_button_status = computed<boolean>(() => !read_text_state.value.length)
@@ -93,7 +94,7 @@
common.hideLoading()
common.msg('登录成功')
// 登陆成功,缓存账号密码
common.setPageCache('loginAccountData', {
common.setValue('loginAccountData', {
account: account.value,
password: password.value
});
@@ -101,17 +102,19 @@
// this.$common.reLaunch('/pages/homepage/index');
// }, this.GLOBAL_TIMER_SUBMIT_DELAY_TIME);
const pages = getCurrentPages()
if (pages.length === 1) { // 页面栈只有一页,没有返回页,那就返回首页
common.switchTab('/pages/index/index')
} else {
if (pages.length >= 2) { // 页面栈只有一页,没有返回页,那就返回首页
console.log('返回登录的上一页');
back_state.value = false
common.navigateBack() // 返回登录的上一页
} else {
common.switchTab('/pages/index/index')
}
}).catch(res => {
console.log(res);
common.hideLoading()
if (res.rtnCode === "0002") {
common.msg('账号或密码错误,如忘记密码,请去统一身份认证平台修改。')
}
else if (res.rtnCode !== "0005") {
}else if (res.rtnCode !== "0005") {
common.msg('登录出错,请稍后再试')
}
})
@@ -119,13 +122,18 @@
common.hideLoading()
}
}
onMounted(() => {
let loginAccountData = common.getPageCache('loginAccountData');
let loginAccountData = common.getValue('loginAccountData');
if (loginAccountData) {
account.value = loginAccountData.account;
password.value = loginAccountData.password;
}
back_state.value = true
})
// 跳进了登录页,禁止返回操作
onBackPress(() => back_state.value)
</script>
<style lang="scss" scoped>
@@ -157,7 +165,7 @@
border-radius: 16rpx;
background-color: #0066FF;
color: #FFFFFF;
overflow: hidden;
:deep(.uv-button) {
height: 100rpx;
}