接完首页和我的页接口
This commit is contained in:
+10
-2
@@ -3,6 +3,14 @@ ENV = 'development'
|
||||
# 'development'
|
||||
|
||||
# base api
|
||||
#VITE_APP_BASE_API_Url = 'http://25.18.122.66:9786'
|
||||
|
||||
# 苗扬
|
||||
VITE_APP_BASE_API_Url = 'http://25.64.16.133:9786'
|
||||
#VITE_APP_BASE_API_Url = 'http://25.64.16.133:9786'
|
||||
|
||||
|
||||
#VITE_APP_BASE_API_Url = 'http://aitstest.jlbank.com.cn:7002'
|
||||
|
||||
|
||||
# app入口
|
||||
VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
|
||||
#VITE_APP_BASE_API_Url = 'http://25.18.122.66:9786'
|
||||
|
||||
+83
-3
@@ -1,12 +1,92 @@
|
||||
import request from '@/api/request'
|
||||
|
||||
|
||||
// 获取首页统计数据方法
|
||||
// 获取首页统计数据方法(查询个人学习统计信息 )
|
||||
export const getStatisticsData = (data) => {
|
||||
/**
|
||||
userId 学员ID String
|
||||
stdtTmLen 本年学习时长 double
|
||||
accmPracticeCnt 累计训练次数 int
|
||||
accmExamCnt 累计考试次数 int
|
||||
**/
|
||||
return request({
|
||||
url: '/plappro/process/queryProcessList',
|
||||
url: '/traapp/traStdyInfo/queryTraStdyStatisticsPerson',
|
||||
method: 'post',
|
||||
data,
|
||||
suppressErrors:true
|
||||
suppressErrors: true
|
||||
});
|
||||
};
|
||||
|
||||
// 最新课程查询接口
|
||||
export const queryCrsInfoByLastnew = (data) => {
|
||||
/**
|
||||
crsNum 课程编号 String
|
||||
crsName 课程名称 String
|
||||
tagId 课程分类 String
|
||||
prdLineId 生产线分类 String
|
||||
issuTm 发布日期 String
|
||||
imgId 课程封面ID String
|
||||
accmStdyCnt 累计学习次数 int
|
||||
evalGrade 课程评分 Bigdecimal
|
||||
tagCataList 课程标签集 List<Object>
|
||||
tagId 标签ID String
|
||||
tagName 标签名称 String
|
||||
**/
|
||||
return request({
|
||||
url: '/traapp/mycrs/queryCrsInfoByLastnew',
|
||||
method: 'post',
|
||||
data,
|
||||
suppressErrors: true
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 热门课程查询接口
|
||||
export const queryCrsInfoByPopular = (data) => {
|
||||
/**
|
||||
tagId 标签ID(可选填),为空时查全部 必输项:false 类型:String
|
||||
出参:
|
||||
tagId 标签ID(可选填),为空时查全部 必输项:false 类型:String
|
||||
出参:
|
||||
crsId 课程ID StringcrsNum 课程编号 String
|
||||
crsName 课程名称 String
|
||||
tagId 课程分类 String
|
||||
prdLineId 生产线分类 String
|
||||
issuTm 发布日期 String
|
||||
imgId 课程封面ID String
|
||||
accmStdyCnt 累计学习次数 int
|
||||
evalGrade 课程评分 Bigdecimal
|
||||
tagCataList 课程标签集 List<Object>
|
||||
tagId 标签ID String
|
||||
tagName 标签名称 String
|
||||
**/
|
||||
return request({
|
||||
url: '/traapp/mycrs/queryCrsInfoByPopular',
|
||||
method: 'post',
|
||||
data,
|
||||
suppressErrors: true
|
||||
});
|
||||
};
|
||||
|
||||
// 推荐课程查询接口
|
||||
export const queryCrsInfoByRecmd = (data) => {
|
||||
/**
|
||||
crsNum 课程编号 String
|
||||
crsName 课程名称 String
|
||||
tagId 课程分类 String
|
||||
prdLineId 生产线分类 String
|
||||
issuTm 发布日期 String
|
||||
imgId 课程封面ID String
|
||||
accmStdyCnt 累计学习次数 int
|
||||
evalGrade 课程评分 Bigdecimal
|
||||
tagCataList 课程标签集 List<Object>
|
||||
tagId 标签ID String
|
||||
tagName 标签名称 String
|
||||
**/
|
||||
return request({
|
||||
url: '/traapp/mycrs/queryCrsInfoByRecmd',
|
||||
method: 'post',
|
||||
data,
|
||||
suppressErrors: true
|
||||
});
|
||||
};
|
||||
+18
-1
@@ -25,9 +25,19 @@ export const useAccountLoginApp = (data) => request({
|
||||
return user_data.body
|
||||
}
|
||||
return Promise.reject({ rtnCode, body })
|
||||
}).catch(res => {
|
||||
console.log('报错s');
|
||||
console.log(res);
|
||||
})
|
||||
|
||||
// 获取个人信息
|
||||
/**
|
||||
* 获取个人信息
|
||||
* 入参
|
||||
gender F是女 M男
|
||||
imageAddr: 图片
|
||||
loginName ID
|
||||
userName 姓名
|
||||
*/
|
||||
export const queryCurrentUser = (data) => request({
|
||||
url: '/traapp/access/queryCurrentUser',
|
||||
method: 'post',
|
||||
@@ -46,4 +56,11 @@ export const getLoginAppCheckCode = (data) => request({
|
||||
url: '/traapp/access/checkCode',
|
||||
method: 'get',
|
||||
data
|
||||
})
|
||||
|
||||
// 退出登录
|
||||
export const loginOut = (data) => request({
|
||||
url: '/traapp/access/loginOut',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
+27
-11
@@ -15,6 +15,26 @@ export const get_base_url = url => {
|
||||
}
|
||||
}
|
||||
|
||||
// 请求错误码
|
||||
export const REQUES_ERROR_CODES = {
|
||||
NO_LOGIN: ['QQ0005', '0005'] //登录
|
||||
};
|
||||
|
||||
// 去登录弹窗状态
|
||||
let no_login_show_modal_state = false
|
||||
// 去登录方法
|
||||
export const goto_login_fun = () => {
|
||||
// if (no_login_show_modal_state) return;
|
||||
no_login_show_modal_state = true
|
||||
common.hideLoading()
|
||||
common.show('未登录','现在去登录').then(() => {
|
||||
common.navigateTo('/pages/login/login')
|
||||
}).finally(() => {
|
||||
no_login_show_modal_state = false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export default function request({
|
||||
url,
|
||||
method,
|
||||
@@ -46,16 +66,13 @@ export default function request({
|
||||
if (isStream) { // 流式传输,直接返回
|
||||
return resolve(response);
|
||||
}
|
||||
|
||||
// 0005 QQ0005 登录已过期
|
||||
|
||||
// suppressErrors
|
||||
// 模拟拦截器功能
|
||||
const res = response.data
|
||||
if (res?.rtnCode === '0000'){
|
||||
return resolve(res)
|
||||
}
|
||||
//到这里全是异常情况
|
||||
//到这里下面全是异常的处理
|
||||
if(suppressErrors){ // 静默的接口,报错也不处理,因为下面有公共处理
|
||||
return reject()
|
||||
}
|
||||
@@ -63,16 +80,15 @@ export default function request({
|
||||
common.msg("系统异常.")
|
||||
return reject()
|
||||
}
|
||||
if (res.rtnCode === '0005' || res.rtnCode === 'QQ0005'){
|
||||
common.hideLoading()
|
||||
common.show('未登录','现在去登录').then(() => {
|
||||
common.navigateTo('/pages/login/login')
|
||||
})
|
||||
// 0005 QQ0005 登录已过期
|
||||
if(REQUES_ERROR_CODES['NO_LOGIN'].includes(res.rtnCode)) {
|
||||
goto_login_fun()
|
||||
}
|
||||
|
||||
return reject(res)
|
||||
},
|
||||
fail() {
|
||||
console.log('131231');
|
||||
fail(res) {
|
||||
console.log('131231', res, url);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
export default class WebSocketUtil {
|
||||
/**
|
||||
* WebSocket工具类,用于管理WebSocket连接
|
||||
* @param {string} url - WebSocket服务器地址
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {number} [options.maxReconnectCount=5] - 最大重连次数
|
||||
* @param {number} [options.reconnectInterval=3000] - 重连间隔时间(ms)
|
||||
* @param {number} [options.heartbeatInterval=30000] - 心跳间隔时间(ms)
|
||||
* @param {string|Object} [options.heartbeatMsg='ping'] - 心跳消息
|
||||
*/
|
||||
constructor(url, options = {}) {
|
||||
this.url = url;
|
||||
this.options = options;
|
||||
this.socketTask = null; // WebSocket任务实例
|
||||
this.reconnectTimer = null; // 重连计时器
|
||||
this.reconnectCount = 0; // 当前重连次数
|
||||
this.maxReconnectCount = options.maxReconnectCount || 5; // 最大重连次数
|
||||
this.reconnectInterval = options.reconnectInterval || 3000; // 重连间隔(ms)
|
||||
this.heartbeatTimer = null; // 心跳计时器
|
||||
this.heartbeatInterval = options.heartbeatInterval || 30000; // 心跳间隔(ms)
|
||||
this.heartbeatMsg = options.heartbeatMsg || 'ping'; // 心跳消息
|
||||
this.callbacks = {
|
||||
open: [], // 连接打开回调
|
||||
message: [], // 消息接收回调
|
||||
close: [], // 连接关闭回调
|
||||
error: [] // 错误处理回调
|
||||
};
|
||||
this.init(); // 初始化WebSocket连接
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化WebSocket连接
|
||||
*/
|
||||
init() {
|
||||
// 创建WebSocket连接
|
||||
this.socketTask = uni.connectSocket({
|
||||
url: this.url,
|
||||
header: this.options.header || {},
|
||||
protocols: this.options.protocols || [],
|
||||
success: () => {
|
||||
console.log('WebSocket连接创建成功');
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('WebSocket连接创建失败', err);
|
||||
this.triggerEvent('error', err);
|
||||
this.tryReconnect(); // 连接失败时尝试重连
|
||||
}
|
||||
});
|
||||
|
||||
// 监听WebSocket连接打开事件
|
||||
this.socketTask.onOpen(() => {
|
||||
console.log('WebSocket连接已打开');
|
||||
this.reconnectCount = 0; // 重置重连计数
|
||||
clearInterval(this.reconnectTimer); // 清除重连计时器
|
||||
this.startHeartbeat(); // 启动心跳机制
|
||||
this.triggerEvent('open'); // 触发连接打开事件
|
||||
});
|
||||
|
||||
// 监听WebSocket消息接收事件
|
||||
this.socketTask.onMessage((res) => {
|
||||
console.log('收到WebSocket消息', res);
|
||||
this.triggerEvent('message', res); // 触发消息接收事件
|
||||
});
|
||||
|
||||
// 监听WebSocket连接关闭事件
|
||||
this.socketTask.onClose((res) => {
|
||||
console.log('WebSocket连接已关闭', res);
|
||||
clearInterval(this.heartbeatTimer); // 清除心跳计时器
|
||||
this.triggerEvent('close', res); // 触发连接关闭事件
|
||||
this.tryReconnect(); // 尝试重连
|
||||
});
|
||||
|
||||
// 监听WebSocket错误事件
|
||||
this.socketTask.onError((err) => {
|
||||
console.error('WebSocket发生错误', err);
|
||||
clearInterval(this.heartbeatTimer); // 清除心跳计时器
|
||||
this.triggerEvent('error', err); // 触发错误事件
|
||||
this.tryReconnect(); // 尝试重连
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册事件回调
|
||||
* @param {string} event - 事件名称(open/message/close/error)
|
||||
* @param {Function} callback - 回调函数
|
||||
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
||||
*/
|
||||
on(event, callback) {
|
||||
if (this.callbacks[event]) {
|
||||
this.callbacks[event].push(callback);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除事件回调
|
||||
* @param {string} event - 事件名称(open/message/close/error)
|
||||
* @param {Function} callback - 要移除的回调函数
|
||||
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
||||
*/
|
||||
off(event, callback) {
|
||||
if (this.callbacks[event]) {
|
||||
this.callbacks[event] = this.callbacks[event].filter(cb => cb !== callback);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发事件回调
|
||||
* @param {string} event - 事件名称
|
||||
* @param {any} [data] - 传递给回调函数的数据
|
||||
*/
|
||||
triggerEvent(event, data) {
|
||||
if (this.callbacks[event]) {
|
||||
this.callbacks[event].forEach(callback => callback(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过WebSocket发送消息
|
||||
* @param {string|Object} message - 要发送的消息,可以是字符串或对象
|
||||
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
||||
*/
|
||||
send(message) {
|
||||
if (this.socketTask && this.getStatus() === 1) {
|
||||
// 发送消息,对象会自动转换为JSON字符串
|
||||
this.socketTask.send({
|
||||
data: typeof message === 'string' ? message : JSON.stringify(message),
|
||||
success: () => {
|
||||
console.log('WebSocket消息发送成功');
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('WebSocket消息发送失败', err);
|
||||
this.triggerEvent('error', err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('WebSocket连接未打开,无法发送消息');
|
||||
this.triggerEvent('error', new Error('WebSocket连接未打开'));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭WebSocket连接
|
||||
* @param {number} [code=1000] - 关闭码
|
||||
* @param {string} [reason=''] - 关闭原因
|
||||
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
||||
*/
|
||||
close(code = 1000, reason = '') {
|
||||
if (this.socketTask) {
|
||||
clearInterval(this.heartbeatTimer); // 清除心跳计时器
|
||||
clearInterval(this.reconnectTimer); // 清除重连计时器
|
||||
// 关闭WebSocket连接
|
||||
this.socketTask.close({
|
||||
code,
|
||||
reason,
|
||||
success: () => {
|
||||
console.log('WebSocket连接正在关闭');
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('WebSocket关闭失败', err);
|
||||
this.triggerEvent('error', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取WebSocket连接状态
|
||||
* @returns {number} - 连接状态:0-连接中,1-已连接,2-连接关闭中,3-已关闭,-1-未知
|
||||
*/
|
||||
getStatus() {
|
||||
if (this.socketTask) {
|
||||
try {
|
||||
return this.socketTask.readyState;
|
||||
} catch (e) {
|
||||
console.error('获取WebSocket状态失败', e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试重新连接WebSocket
|
||||
*/
|
||||
tryReconnect() {
|
||||
if (this.reconnectCount < this.maxReconnectCount) {
|
||||
clearInterval(this.reconnectTimer);
|
||||
this.reconnectTimer = setTimeout(() => {
|
||||
this.reconnectCount++;
|
||||
console.log(`尝试重新连接WebSocket (${this.reconnectCount}/${this.maxReconnectCount})`);
|
||||
this.init(); // 重新初始化WebSocket连接
|
||||
}, this.reconnectInterval);
|
||||
} else {
|
||||
console.error('达到最大重连次数,停止尝试');
|
||||
this.triggerEvent('error', new Error('达到最大重连次数'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动心跳机制
|
||||
*/
|
||||
startHeartbeat() {
|
||||
clearInterval(this.heartbeatTimer);
|
||||
this.heartbeatTimer = setInterval(() => {
|
||||
if (this.getStatus() === 1) {
|
||||
this.send(this.heartbeatMsg); // 发送心跳消息
|
||||
}
|
||||
}, this.heartbeatInterval);
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -1,11 +1,18 @@
|
||||
import request from '@/api/request'
|
||||
|
||||
|
||||
// 获取列表接口
|
||||
export const process_listPage = (data) => {
|
||||
// 我的-统计信息
|
||||
export const queryTraStdyStatisticsSelf = (data) => {
|
||||
/**
|
||||
userId 学员ID String
|
||||
stdtTmLen 累计学习时长 double
|
||||
accmTaskCnt 累计完成任务 int
|
||||
accmPoint 累计获得积分 int
|
||||
**/
|
||||
return request({
|
||||
url: '/plappro/process/queryProcessList',
|
||||
url: '/traapp/traStdyInfo/queryTraStdyStatisticsSelf',
|
||||
method: 'post',
|
||||
data
|
||||
data,
|
||||
suppressErrors: true
|
||||
});
|
||||
};
|
||||
@@ -9,7 +9,7 @@ function msg(title, duration = 1000) {
|
||||
}
|
||||
|
||||
function show(title, msg, showCancel = true) {
|
||||
let res = new Promise((resolve, reject) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.showModal({
|
||||
title: title,
|
||||
content: msg,
|
||||
@@ -18,11 +18,10 @@ function show(title, msg, showCancel = true) {
|
||||
resolve(res.confirm)
|
||||
},
|
||||
fail: function(res) {
|
||||
reject(false)
|
||||
reject(res)
|
||||
},
|
||||
});
|
||||
})
|
||||
return res;
|
||||
}
|
||||
|
||||
const loading = (title = '加载中', mask = true) => uni.showLoading({
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"path": "pages/courseDetail/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "课程详情",
|
||||
@@ -20,8 +19,6 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
=======
|
||||
>>>>>>> f0015d5ea46c4904ce35c5ec4a03028d9ec6d5b4
|
||||
"path": "pages/study/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "学习",
|
||||
@@ -93,8 +90,6 @@
|
||||
"titleNView": false
|
||||
}
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
},
|
||||
{
|
||||
"path": "pages/course/index",
|
||||
@@ -104,7 +99,6 @@
|
||||
"titleNView": false
|
||||
}
|
||||
}
|
||||
>>>>>>> f0015d5ea46c4904ce35c5ec4a03028d9ec6d5b4
|
||||
}
|
||||
],
|
||||
"tabBar": {
|
||||
|
||||
+107
-73
@@ -27,8 +27,9 @@
|
||||
</view>
|
||||
<!-- 搜索框 -->
|
||||
<view class="search_div">
|
||||
<uv-input shape="circle" @click="goto_search_page" :customStyle="customStyles" :placeholderStyle="placeholderStyle"
|
||||
placeholder="请输入关键字" suffixIcon="search" :suffixIconStyle="suffixIconStyle" :readonly="true">
|
||||
<uv-input shape="circle" @click="goto_search_page" :customStyle="customStyles"
|
||||
:placeholderStyle="placeholderStyle" placeholder="请输入关键字" suffixIcon="search"
|
||||
:suffixIconStyle="suffixIconStyle" :readonly="true">
|
||||
</uv-input>
|
||||
<view class="message_div">
|
||||
<image src="@/static/images/index/message.png" class="message_img"></image>
|
||||
@@ -52,20 +53,22 @@
|
||||
<!-- 学习时长 -->
|
||||
<view class="study_duration_div">
|
||||
<view class="item">
|
||||
<view class="top">年度学习时长</view>
|
||||
<view class="top">本年学习时长</view>
|
||||
<view class="bottom">
|
||||
<uv-count-to :startVal="150" :endVal="256.2" :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="top">累计训练次数</view>
|
||||
<view class="bottom">
|
||||
<uv-count-to :startVal="100" :endVal="224.5" :useEasing="true" :decimals="1"></uv-count-to>h
|
||||
<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="0" :endVal="25" :useEasing="true"></uv-count-to>
|
||||
<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>
|
||||
@@ -121,15 +124,15 @@
|
||||
<scroll-view class="scroll-view" :scroll-x="true" :show-scrollbar="false">
|
||||
<view class="scroll-view-item" v-for="(item,index) in hot_class_list" :key="index">
|
||||
<view class="item_div">
|
||||
<uv-skeleton :loading="!item.title" :rows="3" avatar avatar-shape="square" :title="false">
|
||||
<view class="item">
|
||||
<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 class="img" src="@/static/images/test/1.png"></image>
|
||||
<image-preview class="img-box img" :imgId="item.imgId"></image-preview>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="title ellipsis-text">{{item.title}}</view>
|
||||
<view class="title ellipsis-text">{{item.crsName}}</view>
|
||||
<view class="note ellipsis-text">
|
||||
发布:{{item.date}} 丨已学:{{item.num}}
|
||||
发布:{{item.issuTm.substr(0, 10)}} 丨已学:{{item.accmStdyCnt}}
|
||||
</view>
|
||||
<view class="button_div">
|
||||
<view class="button">去学习</view>
|
||||
@@ -152,17 +155,17 @@
|
||||
<!-- 推荐课程 -->
|
||||
<view class="hot_class_div">
|
||||
<scroll-view class="scroll-view" :scroll-x="true" :show-scrollbar="false">
|
||||
<view class="scroll-view-item" v-for="(item,index) in hot_class_list" :key="index">
|
||||
<view class="scroll-view-item" v-for="(item,index) in recommend_class_list" :key="index">
|
||||
<view class="item_div">
|
||||
<uv-skeleton :loading="!item.title" :rows="3" avatar avatar-shape="square" :title="false">
|
||||
<view class="item">
|
||||
<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 class="img" src="@/static/images/test/1.png"></image>
|
||||
<image-preview class="img-box img" :imgId="item.imgId"></image-preview>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="title ellipsis-text">{{item.title}}</view>
|
||||
<view class="title ellipsis-text">{{item.crsName}}</view>
|
||||
<view class="note ellipsis-text">
|
||||
发布:{{item.date}} 丨已学:{{item.num}}
|
||||
发布:{{item.issuTm.substr(0, 10)}} 丨已学:{{item.accmStdyCnt}}
|
||||
</view>
|
||||
<view class="button_div">
|
||||
<view class="button">去学习</view>
|
||||
@@ -184,17 +187,17 @@
|
||||
<!-- 最新课程 -->
|
||||
<view class="hot_class_div">
|
||||
<scroll-view class="scroll-view" :scroll-x="true" :show-scrollbar="false">
|
||||
<view class="scroll-view-item" v-for="(item,index) in hot_class_list" :key="index">
|
||||
<view class="scroll-view-item" v-for="(item,index) in new_class_list" :key="index">
|
||||
<view class="item_div">
|
||||
<uv-skeleton :loading="!item.title" :rows="3" avatar avatar-shape="square" :title="false">
|
||||
<view class="item">
|
||||
<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 class="img" src="@/static/images/test/1.png"></image>
|
||||
<image-preview class="img-box img" :imgId="item.imgId"></image-preview>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="title ellipsis-text">{{item.title}}</view>
|
||||
<view class="title ellipsis-text">{{item.crsName}}</view>
|
||||
<view class="note ellipsis-text">
|
||||
发布:{{item.date}} 丨已学:{{item.num}}
|
||||
发布:{{item.issuTm.substr(0, 10)}} 丨已学:{{item.accmStdyCnt}}
|
||||
</view>
|
||||
<view class="button_div">
|
||||
<view class="button">去学习</view>
|
||||
@@ -210,15 +213,17 @@
|
||||
<uv-divider text='我是有底线的' lineColor="#9cB0DC" :hairline="true"></uv-divider>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<tabbar-shadow></tabbar-shadow>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import {
|
||||
computed,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref
|
||||
} from 'vue'
|
||||
import {
|
||||
@@ -233,7 +238,10 @@
|
||||
} from './index.js'
|
||||
import common from '@/common/common'
|
||||
import {
|
||||
getStatisticsData
|
||||
getStatisticsData,
|
||||
queryCrsInfoByLastnew,
|
||||
queryCrsInfoByPopular,
|
||||
queryCrsInfoByRecmd,
|
||||
} from '@/api/index.js'
|
||||
const scrollTop = ref(0);
|
||||
// 计算透明度
|
||||
@@ -250,64 +258,81 @@
|
||||
})
|
||||
// 滚动消息
|
||||
const notice_text = ref(['绿色金融政策解析与商业银行绿色水水水水水水水水水水水水水', '绿色金融政策解析与商业银行红色'])
|
||||
const init_class_data = [
|
||||
{
|
||||
crsNum: '',
|
||||
img: '',
|
||||
crsName: '',
|
||||
issuTm: '',
|
||||
accmStdyCnt: ''
|
||||
}, {
|
||||
crsNum: '',
|
||||
img: '',
|
||||
crsName: '',
|
||||
issuTm: '',
|
||||
accmStdyCnt: ''
|
||||
}
|
||||
]
|
||||
// 热门课程
|
||||
const hot_class_list = ref([{
|
||||
img: '',
|
||||
title: '',
|
||||
date: '',
|
||||
num: ''
|
||||
}, {
|
||||
img: '',
|
||||
title: '',
|
||||
date: '',
|
||||
num: ''
|
||||
}])
|
||||
const statistics_data = {
|
||||
'study': 0, // 学习
|
||||
'train': 0, // 训练
|
||||
'exam': 0, //考试
|
||||
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, // 训练
|
||||
'accmExamCnt': 0, //考试
|
||||
'start_tudy': 0, // 起始学习
|
||||
'start_train': 0, // 起始训练
|
||||
'start_exam': 0, //起始考试
|
||||
'request_time': 0, //上次请求时间
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 获取首页统计数据方法
|
||||
const get_statistics_data = async () => {
|
||||
if (!common.isLogin()) return
|
||||
const time_now = Date.now()
|
||||
// 暂时设置10分钟
|
||||
if (time_now - statistics_data['request_time'] > 600 * 1000) {
|
||||
statistics_data['request_time'] = time_now
|
||||
// const data = await getStatisticsData()
|
||||
// console.log(data);
|
||||
}
|
||||
const data = await getStatisticsData()
|
||||
statistics_data['accmExamCnt'] = data['accmExamCnt']
|
||||
statistics_data['accmPracticeCnt'] = data['accmPracticeCnt']
|
||||
statistics_data['stdtTmLen'] = data['stdtTmLen']
|
||||
// const time_now = Date.now()
|
||||
// // 暂时设置10分钟
|
||||
// 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)
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
get_statistics_data() // 获取首页统计数据
|
||||
})
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
hot_class_list.value = [{
|
||||
img: '11',
|
||||
title: '最新课程最新课程最新课程程最新课程程最新课程程最新课程',
|
||||
date: '2025/4/21',
|
||||
num: '44'
|
||||
}, {
|
||||
img: '',
|
||||
title: '',
|
||||
date: '',
|
||||
num: ''
|
||||
}]
|
||||
}, 100)
|
||||
onMounted(async () => {
|
||||
queryCrsInfoByLastnew().then(res => {
|
||||
new_class_list.value = res.body
|
||||
})
|
||||
queryCrsInfoByPopular().then(res => {
|
||||
hot_class_list.value = res.body
|
||||
})
|
||||
queryCrsInfoByRecmd().then(res => {
|
||||
recommend_class_list.value = res.body
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<style scoped lang="scss">
|
||||
$bg-margin-left: 50rpx;
|
||||
|
||||
// :deep(.uni-scroll-view-content) {
|
||||
@@ -319,12 +344,13 @@
|
||||
width: 146rpx !important;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
// 底线样式
|
||||
.bottom_line {
|
||||
margin: 0 auto;
|
||||
width: 240rpx;
|
||||
}
|
||||
|
||||
|
||||
// 热门课程等三个横向滑动模块的样式
|
||||
.hot_class_div {
|
||||
margin-left: $bg-margin-left;
|
||||
@@ -416,7 +442,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.bg_div {
|
||||
height: 100%;
|
||||
padding-bottom: 30rpx;
|
||||
@@ -455,13 +481,12 @@
|
||||
background-color: #f6f8ff;
|
||||
margin-top: var(--status-bar-height);
|
||||
padding: 0 $bg-margin-left 20rpx $bg-margin-left;
|
||||
height: 70rpx;
|
||||
width: calc(100% - 2* $bg-margin-left);
|
||||
height: 90rpx;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 4rpx solid #efefef;
|
||||
|
||||
.fixed_search_input_div {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -578,16 +603,16 @@
|
||||
:deep(.uv-notice__left-icon) .uv-icon__icon {
|
||||
font-size: 24rpx !important;
|
||||
}
|
||||
|
||||
|
||||
// ::v-deep .u-notice-bar {
|
||||
// padding: 14rpx 0;
|
||||
// font-size: 22rpx;
|
||||
// }
|
||||
|
||||
|
||||
// :deep(.u-notice__left-icon) {
|
||||
// margin-right: 5rpx;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 学习时长
|
||||
@@ -643,12 +668,21 @@
|
||||
font-style: normal;
|
||||
text-align: center;
|
||||
|
||||
|
||||
// 数字滚动组件
|
||||
:deep(.uv-count-num) {
|
||||
font-weight: bold !important;
|
||||
font-size: 50rpx !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.number {
|
||||
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
}
|
||||
|
||||
.account_input {
|
||||
height: 76rpx;
|
||||
height: 100rpx;
|
||||
background-color: #F4F8FF;
|
||||
border: none;
|
||||
border-radius: 16rpx;
|
||||
|
||||
+129
-11
@@ -8,20 +8,25 @@
|
||||
<!-- 用户个人信息 -->
|
||||
<view class="personal_information">
|
||||
<view class="profile">
|
||||
<image class="img_100" src="/static/images/test/touxiang.png"></image>
|
||||
<image v-if="user_info.imageAddr" class="img_100" src="/static/images/test/touxiang.png">
|
||||
</image>
|
||||
<image v-else class="img_100" src="/static/images/me/default_user_avatar.png"></image>
|
||||
</view>
|
||||
<view class="personal_information_data">
|
||||
<view class="name_sex_div">
|
||||
<view class="name">
|
||||
顾青裴
|
||||
{{user_info.userName}}
|
||||
</view>
|
||||
<view class="sex">
|
||||
<!-- <image class="img_100" src="/static/images/me/man.png"></image> -->
|
||||
<image class="img_100" src="/static/images/me/wuman.png"></image>
|
||||
<image v-if="user_info.gender === 'F'" class="img_100"
|
||||
src="/static/images/me/wuman.png">
|
||||
</image>
|
||||
<image v-if="user_info.gender === 'M'" class="img_100" src="/static/images/me/man.png">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="work_number_div">
|
||||
工号:15688749934
|
||||
工号:{{user_info.userId}}
|
||||
</view>
|
||||
<view class="fl1"></view>
|
||||
</view>
|
||||
@@ -31,19 +36,19 @@
|
||||
<view class="item">
|
||||
<view class="top">累计学习时长</view>
|
||||
<view class="bottom">
|
||||
<uv-count-to :startVal="15" :endVal="15" :useEasing="true" :decimals="1"></uv-count-to>h
|
||||
<uv-count-to :startVal="statistics_data['accmPoint']" :endVal="statistics_data['accmPoint']" :useEasing="true" :decimals="1"></uv-count-to>h
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="top">累计完成任务</view>
|
||||
<view class="bottom">
|
||||
<uv-count-to :startVal="24" :endVal="24" :useEasing="true"></uv-count-to>
|
||||
<uv-count-to :startVal="statistics_data['accmTaskCnt']" :endVal="statistics_data['accmTaskCnt']" :useEasing="true"></uv-count-to>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="top">累计获得积分</view>
|
||||
<view class="bottom">
|
||||
<uv-count-to :startVal="125" :endVal="125" :useEasing="true"></uv-count-to>
|
||||
<uv-count-to :startVal="statistics_data['stdtTmLen']" :endVal="statistics_data['stdtTmLen']" :useEasing="true"></uv-count-to>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -82,7 +87,8 @@
|
||||
<uv-cell-group :border="false">
|
||||
<uv-cell title='设置' :isLink="true"></uv-cell>
|
||||
<uv-cell title='客服' :isLink="true"></uv-cell>
|
||||
<uv-cell title='退出登录' :isLink="true" :clickable="false" :border="false"></uv-cell>
|
||||
<uv-cell title='退出登录' :isLink="true" :clickable="false" :border="false"
|
||||
@click="click_loginout()"></uv-cell>
|
||||
</uv-cell-group>
|
||||
</view>
|
||||
<tabbar-shadow></tabbar-shadow>
|
||||
@@ -92,14 +98,126 @@
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
computed,
|
||||
reactive
|
||||
} from 'vue';
|
||||
import {
|
||||
onShow
|
||||
} from '@dcloudio/uni-app'
|
||||
import common from '@/common/common'
|
||||
import {
|
||||
getUserInfo
|
||||
} from '@/common/common'
|
||||
import {
|
||||
onPullDownRefresh
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
loginOut
|
||||
} from '@/api/login.js'
|
||||
import {
|
||||
queryTraStdyStatisticsSelf
|
||||
} from '@/api/user.js'
|
||||
const statistics_data = reactive({
|
||||
'study': 0, // 学习
|
||||
'train': 0, // 训练
|
||||
'exam': 0, // 考试
|
||||
'start_study': 0, // 起始学习
|
||||
'start_train': 0, // 起始训练
|
||||
'start_exam': 0, // 起始考试
|
||||
'request_time': 0, // 上次请求时间
|
||||
|
||||
/**
|
||||
* 初始化统计数据
|
||||
*/
|
||||
"init": function() {
|
||||
// 初始化起始数据
|
||||
this.start_study = this.study;
|
||||
this.start_train = this.train;
|
||||
this.start_exam = this.exam;
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取统计数据(带缓存机制)
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
"get_statistics_data": async function() {
|
||||
try {
|
||||
const time_now = Date.now();
|
||||
// 检查缓存是否过期(10分钟)
|
||||
if (time_now - this.request_time > 600 * 1000) {
|
||||
this.request_time = time_now;
|
||||
|
||||
// 获取最新数据
|
||||
const {
|
||||
study,
|
||||
train,
|
||||
exam
|
||||
} = await getStatisticsData();
|
||||
|
||||
// 保存起始值(如果是首次获取)
|
||||
if (this.request_time === 0) {
|
||||
this.start_study = study;
|
||||
this.start_train = train;
|
||||
this.start_exam = exam;
|
||||
}
|
||||
|
||||
// 更新当前值
|
||||
this.study = study;
|
||||
this.train = train; // 修正:之前漏写这一行
|
||||
this.exam = exam;
|
||||
|
||||
console.log('统计数据已更新');
|
||||
} else {
|
||||
console.log('使用缓存的统计数据');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取统计数据失败:', error);
|
||||
// 可以在这里添加重试逻辑或使用默认值
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const user_info = reactive({
|
||||
userName: '',
|
||||
userId: ''
|
||||
});
|
||||
|
||||
|
||||
|
||||
onShow(() => {
|
||||
const user_info_cache = getUserInfo()
|
||||
Object.assign(user_info, user_info_cache)
|
||||
queryTraStdyStatisticsSelf().then(res => {
|
||||
statistics_data['accmPoint'] = res['accmPoint']
|
||||
statistics_data['accmTaskCnt'] = res['accmTaskCnt']
|
||||
statistics_data['stdtTmLen'] = res['stdtTmLen']
|
||||
console.log('res', res);
|
||||
console.log('res', res);
|
||||
console.log('res', res);
|
||||
})
|
||||
// statistics_data['get_statistics_data']() // 获取首页统计数据
|
||||
})
|
||||
|
||||
const click_loginout = () => {
|
||||
common.show('确定退出登录?').then(async (res) => {
|
||||
console.log(res);
|
||||
if (!res) return;
|
||||
try {
|
||||
common.loading('正在退出登录')
|
||||
await loginOut()
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
common.hideLoading()
|
||||
// 主动退出登录后,再次登录应该进首页
|
||||
common.reLaunch('/pages/login/login')
|
||||
})
|
||||
}
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
console.log('下拉刷新');
|
||||
// uni.stopPullDownRefresh();
|
||||
uni.stopPullDownRefresh();
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -8,10 +8,45 @@
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
<script setup>
|
||||
import WebSocketUtil from '@/api/socket.js';
|
||||
|
||||
const ws = new WebSocketUtil('ws://127.0.0.1', {
|
||||
maxReconnectCount: 10,
|
||||
reconnectInterval: 5000,
|
||||
heartbeatInterval: 30000,
|
||||
heartbeatMsg: 'ping'
|
||||
});
|
||||
|
||||
ws.on('open', () => {
|
||||
console.log('WebSocket连接已打开');
|
||||
ws.send({
|
||||
type: 'init',
|
||||
data: {
|
||||
userId: 123
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ws.on('message', (res) => {
|
||||
console.log('收到消息:', res);
|
||||
});
|
||||
|
||||
ws.on('close', (res) => {
|
||||
console.log('WebSocket连接已关闭:', res);
|
||||
});
|
||||
|
||||
ws.on('error', (err) => {
|
||||
console.error('WebSocket错误:', err);
|
||||
});
|
||||
|
||||
// 一段时间后关闭连接
|
||||
setTimeout(() => {
|
||||
ws.close(1000, '正常关闭');
|
||||
}, 60000);
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.main_div{
|
||||
.main_div {
|
||||
background-color: #f9faff;
|
||||
// background-color: red;
|
||||
display: flex;
|
||||
@@ -19,21 +54,24 @@
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.empty_div{
|
||||
|
||||
.empty_div {
|
||||
// margin-top: 40%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
//
|
||||
.img{
|
||||
.img {
|
||||
width: 388rpx;
|
||||
height: 335rpx;
|
||||
}
|
||||
.text{
|
||||
|
||||
|
||||
.text {
|
||||
|
||||
margin-top: 20rpx;
|
||||
height: 40rpx;
|
||||
|
||||
|
||||
font-family: PingFangSC, PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 29rpx;
|
||||
|
||||
+1
-2
@@ -33,8 +33,7 @@
|
||||
"navigationBarTitleText": "我的",
|
||||
"app-plus": {
|
||||
"titleNView": false
|
||||
},
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Reference in New Issue
Block a user