From f4ed2c4a1412f7256614e04e18683ca15a89bb25 Mon Sep 17 00:00:00 2001
From: 祖安之光 <11848914+light-of-zuan@user.noreply.gitee.com>
Date: Wed, 05 Nov 2025 08:58:21 +0800
Subject: [PATCH] 新增
---
api/review.js | 16
pages/tabBar/firstPage/firstPage.vue | 1068 +++++++++++++++-------------
pages/review/signPage.vue | 388 ++++++++++
pages.json | 102 +-
common/constant.js | 4
pages/review/index.vue | 305 ++++++++
pages/tabBar/count/count.vue | 14
static/educate.png | 0
static/review.png | 0
pages/menuPage/index.vue | 172 ++++
pages/tabBar/count/countDetail.vue | 2
pages/index/index.vue | 18
pages/tabBar/current/detail.vue | 95 ++
13 files changed, 1,613 insertions(+), 571 deletions(-)
diff --git a/api/review.js b/api/review.js
new file mode 100644
index 0000000..1ec4510
--- /dev/null
+++ b/api/review.js
@@ -0,0 +1,16 @@
+import {service} from '../common/request.js';
+
+export function getProjectList(id) {
+ return service({
+ url: '/app/item/review/approvalList?userId=' + id ,
+ method: 'GET'
+ })
+}
+
+export function postSignaure(data) {
+ return service({
+ url: '/app/item/review/approval',
+ method: 'POST',
+ data
+ })
+}
\ No newline at end of file
diff --git a/common/constant.js b/common/constant.js
index 94fdf35..0a686af 100644
--- a/common/constant.js
+++ b/common/constant.js
@@ -2,8 +2,8 @@
let VUE_APP_BASE_URL= null;
if (process.env.NODE_ENV == 'development') {
// VUE_APP_BASE_URL = 'http://106.15.95.149:8056/api'
- // VUE_APP_BASE_URL = 'http://192.168.2.30:8056/api'
- VUE_APP_BASE_URL = 'https://reagent.sinanoaq.cn/exam'
+ VUE_APP_BASE_URL = 'http://192.168.2.28:8056/api'
+ // VUE_APP_BASE_URL = 'https://reagent.sinanoaq.cn/exam'
}else {
// VUE_APP_BASE_URL = 'http://192.168.2.15:8082'
// 正式环境
diff --git a/pages.json b/pages.json
index 53eaeba..e3f87a2 100644
--- a/pages.json
+++ b/pages.json
@@ -7,16 +7,37 @@
}
},
{
- "path" : "pages/tabBar/firstPage/firstPage",
- "style" :
- {
- "navigationBarTitleText": "首页"
+ "path": "pages/menuPage/index",
+ "style": {
+ "navigationBarTitleText": "主页面",
+ "navigationStyle": "custom"
}
},
{
- "path" : "pages/tabBar/firstPage/exam",
- "style" :
- {
+ "path": "pages/review/index",
+ "style": {
+ "navigationBarTitleText": "项目审批",
+ "enablePullDownRefresh": false,
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/review/signPage",
+ "style": {
+ "navigationBarTitleText": "电子签名"
+ }
+ },
+ {
+ "path": "pages/tabBar/firstPage/firstPage",
+ "style": {
+ "navigationBarTitleText": "首页",
+ "navigationStyle": "custom",
+ "enablePullDownRefresh": false
+ }
+ },
+ {
+ "path": "pages/tabBar/firstPage/exam",
+ "style": {
"navigationBarTitleText": "题目内容",
"enablePullDownRefresh": false,
"app-plus": {
@@ -25,20 +46,18 @@
}
},
{
- "path" : "pages/tabBar/count/count",
- "style" :
- {
- "navigationBarTitleText": "我的",
- "enablePullDownRefresh": false,
+ "path": "pages/tabBar/count/count",
+ "style": {
+ "navigationBarTitleText": "我的",
+ "enablePullDownRefresh": false,
"app-plus": {
"scrollIndicator": "none"
}
- }
+ }
},
{
- "path" : "pages/tabBar/count/countDetail",
- "style" :
- {
+ "path": "pages/tabBar/count/countDetail",
+ "style": {
"navigationBarTitleText": "我的成绩",
"enablePullDownRefresh": false,
"app-plus": {
@@ -47,9 +66,8 @@
}
},
{
- "path" : "pages/tabBar/current/current",
- "style" :
- {
+ "path": "pages/tabBar/current/current",
+ "style": {
"navigationBarTitleText": "课程",
"enablePullDownRefresh": false,
"app-plus": {
@@ -58,9 +76,8 @@
}
},
{
- "path" : "pages/tabBar/current/detail",
- "style" :
- {
+ "path": "pages/tabBar/current/detail",
+ "style": {
"navigationBarTitleText": "课程详情",
"enablePullDownRefresh": false,
"app-plus": {
@@ -69,20 +86,18 @@
}
},
{
- "path" : "pages/tabBar/wearhouse/wearhouse",
- "style" :
- {
- "navigationBarTitleText": "刷题",
- "enablePullDownRefresh": false,
+ "path": "pages/tabBar/wearhouse/wearhouse",
+ "style": {
+ "navigationBarTitleText": "刷题",
+ "enablePullDownRefresh": false,
"app-plus": {
"scrollIndicator": "none"
}
- }
+ }
},
{
- "path" : "pages/tabBar/wearhouse/questions",
- "style" :
- {
+ "path": "pages/tabBar/wearhouse/questions",
+ "style": {
"navigationBarTitleText": "题目内容",
"enablePullDownRefresh": false,
"app-plus": {
@@ -97,16 +112,16 @@
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
- "pagePath": "pages/tabBar/firstPage/firstPage",
- "iconPath": "static/home.png",
- "selectedIconPath": "static/home_sel.png",
- "text": "首页"
- },{
- "pagePath": "pages/tabBar/current/current",
- "iconPath": "/static/notice.png",
- "selectedIconPath": "/static/notice-sel.png",
- "text": "课程"
- },{
+ "pagePath": "pages/tabBar/firstPage/firstPage",
+ "iconPath": "static/home.png",
+ "selectedIconPath": "static/home_sel.png",
+ "text": "首页"
+ }, {
+ "pagePath": "pages/tabBar/current/current",
+ "iconPath": "/static/notice.png",
+ "selectedIconPath": "/static/notice-sel.png",
+ "text": "课程"
+ }, {
"pagePath": "pages/tabBar/wearhouse/wearhouse",
"iconPath": "/static/wearhouse.png",
"selectedIconPath": "/static/wearhouse_sel.png",
@@ -117,7 +132,8 @@
"iconPath": "/static/my.png",
"selectedIconPath": "/static/my_sel.png",
"text": "我的"
- }]
+ }
+ ]
},
"globalStyle": {
"navigationBarTextStyle": "black",
@@ -126,4 +142,4 @@
"backgroundColor": "#f5f7fa"
},
"uniIdRouter": {}
-}
+}
\ No newline at end of file
diff --git a/pages/index/index.vue b/pages/index/index.vue
index a3117b9..fef7e9a 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -4,7 +4,7 @@
<view class="main">
<view class="header">
<view class="titleFirst">
- 你好~<br/>欢迎来到安全教育平台</view>
+ 你好~<br/>欢迎来到体系合规化平台</view>
</view>
<!-- <view class="form-area"> -->
<u--form :model="form" ref="uForm" class="form" >
@@ -129,22 +129,18 @@
login(data).then(res => {
if (res.code === 200) {
t.isLogining = false;
- //登录成功后
- //设置别名
- // jpushModule.setAlias({
- // 'alias': this.phone,
- // 'sequence': 1
- // })
+
uni.setStorageSync("name", t.form.username);
uni.setStorageSync("pwd", t.form.password);
uni.setStorageSync("tk", res.data.token);
uni.setStorageSync("uid",res.data.id);
uni.setStorageSync('user', res.data);
- // t.$store.commit('setRoleId', 'user_leader');
- uni.switchTab({
- url: '/pages/tabBar/firstPage/firstPage'
+ // uni.switchTab({
+ // url: '/pages/tabBar/firstPage/firstPage'
+ // })
+ uni.navigateTo({
+ url: '/pages/menuPage/index'
})
- // }
}else{
uni.showToast({
icon: "none",
diff --git a/pages/menuPage/index.vue b/pages/menuPage/index.vue
new file mode 100644
index 0000000..adc68c4
--- /dev/null
+++ b/pages/menuPage/index.vue
@@ -0,0 +1,172 @@
+<template>
+ <view>
+ <!-- 自定义导航栏 -->
+ <view class="custom-navbar">
+ <view class="navbar-content">
+ <text class="navbar-title">主页面</text>
+ </view>
+ </view>
+ <view class="page-content" :style="{ paddingTop: navbarHeight + 'px' }">
+ <view class="navBtn" @click="toReview()">
+ <u-image radius="16px" width="140rpx" height="140rpx" :show-loading="true" :src="reviewIcon" mode="aspectFill">
+ </u-image>
+ <view class="cardTit">
+ 项目审批
+ </view>
+ </view>
+ <view class="navBtn" @click="toEducate()">
+ <u-image radius="16px" width="140rpx" height="140rpx" :show-loading="true" :src="educateIcon" mode="aspectFill">
+ </u-image>
+ <view class="cardTit">
+ 安全教育
+ </view>
+ </view>
+ <view class="loginBtn">
+ <u-button @click="loginOut" type="primary" text="退出登录" shape="circle"></u-button>
+ </view>
+ </view>
+
+ </view>
+</template>
+
+<script>
+ import VUE_APP_BASE_URL from 'common/constant.js'
+ import {loginOut} from "../../api"
+ import reviewIcon from '../../static/review.png'
+ import educateIcon from '../../static/educate.png'
+ export default {
+ components: {},
+ data() {
+ return {
+ navbarHeight: 0,
+ reviewIcon: reviewIcon,
+ educateIcon: educateIcon
+ }
+
+ },
+ onLoad() {
+ this.getNavbarHeight()
+ },
+ onShow() {
+
+ },
+ created() {
+
+ },
+ mounted() {
+
+ },
+ methods: {
+ getNavbarHeight() {
+ const systemInfo = uni.getSystemInfoSync()
+ const statusBarHeight = systemInfo.statusBarHeight
+ const navbarHeight = 44
+ this.navbarHeight = statusBarHeight + navbarHeight
+ },
+ toReview() {
+ uni.navigateTo({
+ url: '/pages/review/index'
+ })
+ },
+
+ toEducate() {
+ uni.switchTab({
+ url: '/pages/tabBar/firstPage/firstPage'
+ })
+ },
+ loginOut(){
+ uni.showModal({
+ title: '提示',
+ content: '是否确认退出该账号?',
+ success: async function (res) {
+ if (res.confirm) {
+ loginOut().then(res=>{
+ if(res.code == 200){
+ uni.showToast({
+ title: '账户已退出',
+ duration: 800
+ })
+ setTimeout(()=>{
+ uni.clearStorageSync();
+ uni.clearStorage();
+ uni.navigateTo({
+ url: '/pages/index/index'
+ })
+ },800)
+ }
+ })
+ } else if (res.cancel) {
+ console.log('用户点击取消');
+ }
+ }
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ .custom-navbar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 999;
+ background: #ffffff;
+
+ .navbar-content {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 44px;
+ padding-top: var(--status-bar-height);
+ }
+
+ .navbar-title {
+ font-size: 16px;
+ font-weight: bold;
+ color: #333;
+ }
+
+ }
+ .page-content {
+ min-height: 100vh;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 0 15px;
+ .navBtn{
+ width: 100%;
+ padding: 15px 30px;
+ box-sizing: border-box;
+ margin-top: 15px;
+ background: #fff;
+ border-radius: 20rpx;
+ display: flex;
+ align-items: center;
+ box-shadow: 0 10rpx 20rpx rgba(0,0,0,.05);
+ transition: box-shadow .15s ease !important;
+
+ &:active{
+ box-shadow: none;
+ }
+
+ .cardTit{
+ font-size: 36rpx;
+ font-weight: bold;
+ margin-left: 30px;
+ }
+
+ }
+ .loginBtn{
+ width: 100%;
+ position: fixed;
+ bottom: 90px;
+
+ ::v-deep .u-button{
+ width: 80%;
+ }
+ }
+ }
+</style>
\ No newline at end of file
diff --git a/pages/review/index.vue b/pages/review/index.vue
new file mode 100644
index 0000000..ce9f1a7
--- /dev/null
+++ b/pages/review/index.vue
@@ -0,0 +1,305 @@
+<template>
+ <view>
+ <view class="custom-navbar">
+ <view class="navbar-content">
+ <view class="nav-left" @click="handleBack">
+ <view class="back-btn">
+ <text class="back-text">返回</text>
+ </view>
+ </view>
+ <text class="navbar-title">项目审批</text>
+ <view class="nav-right"></view>
+ </view>
+ </view>
+ <view class="page-content" :style="{ paddingTop: navbarHeight + 'px'}">
+ <view class="card-t">
+ <span class="card-t-l">项目审批</span>
+ <div>
+ <u-tabs :list="examSelect" :current="currentTab" @click="changeState"></u-tabs>
+ </div>
+ </view>
+ <view>
+ <view class="cardList" v-if="projectList && projectList.length>0">
+ <scroll-view scroll-y="true" class="scroll-Y" @scrolltoupper="upper" @scrolltolower="lower"
+ lower-threshold="150" @scroll="scrollView" style="height:100%">
+ <view style="padding: 0 0 20px">
+ <view class="card-i" v-for="(item,index) in projectList" :key="index">
+ <view class="card-line">
+ <view class="card-tit">项目名称</view>
+ <view class="card-cont">{{item.fileName}}</view>
+ </view>
+ <view class="card-line">
+ <view class="card-tit">项目阶段</view>
+ <view class="card-cont">{{item.stage}}</view>
+ </view>
+ <view class="card-line">
+ <u-button text="项目文档" type="primary" @click="viewProject(item)"></u-button>
+ <u-button text="电子签名" type="primary" @click="toSign(item)"></u-button>
+ </view>
+ </view>
+ </view>
+ </scroll-view>
+ </view>
+ <u-empty v-else text="暂无记录" mode="data"></u-empty>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import {
+ getProjectList
+ } from '../../api/review.js'
+ import VUE_APP_BASE_URL from "../../common/constant";
+ export default {
+ components: {},
+ data() {
+ return {
+ navbarHeight: 0,
+ currentTab: 0,
+ examSelect: [{
+ name: "待审批"
+ }],
+ projectList: []
+ }
+
+ },
+ onLoad() {
+ //获取手机状态栏高度
+ this.getNavbarHeight()
+ this.getList()
+ },
+ onShow() {
+
+ },
+ created() {},
+ methods: {
+ getNavbarHeight() {
+ const systemInfo = uni.getSystemInfoSync()
+ const statusBarHeight = systemInfo.statusBarHeight
+ const navbarHeight = 44
+ this.navbarHeight = statusBarHeight + navbarHeight
+ },
+
+ handleBack() {
+ uni.navigateTo({
+ url: '/pages/menuPage/index'
+ })
+ },
+ changeState(e) {
+ this.currentTab = e.index
+ },
+ viewProject(item) {
+ wx.showLoading({
+ title: '文件获取中...',
+ mask: true
+ })
+ wx.downloadFile({
+ url: VUE_APP_BASE_URL + '/' + item.filePath,
+ success: function(res) {
+ if (res.statusCode !== 200 || !res.tempFilePath) {
+ wx.hideLoading()
+ uni.showToast({
+ icon: 'none',
+ title: '文件下载失败',
+ duration: 2000
+ })
+ return
+ }
+ var filePath = res.tempFilePath
+ wx.openDocument({
+ filePath: filePath,
+ showMenu: true,
+ success: function(res) {
+ wx.hideLoading()
+ },
+ fail: function(res) {
+ uni.showToast({
+ icon: 'none',
+ duration: 2000,
+ position: 'top',
+ title: `打开文件失败: ${res.errMsg || '未知错误'}`
+ });
+ wx.hideLoading()
+ }
+ })
+ },
+ fail: function(res) {
+ uni.showToast({
+ icon: 'none',
+ duration: 2000,
+ position: 'top',
+ title: `下载失败: ${res.errMsg || '网络错误'}`
+ });
+ wx.hideLoading()
+ }
+ })
+ },
+ toSign(item) {
+ uni.navigateTo({
+ url: `/pages/review/signPage?id=` + encodeURIComponent(JSON.stringify(item.id))
+ })
+ },
+ async getList() {
+ const res = await getProjectList(uni.getStorageSync('uid'))
+ if (res.code == 200) {
+ this.projectList = res.data || []
+ } else {
+ uni.$u.toast(res.message)
+ }
+ },
+ upper(e) {
+ // console.log(e)
+ },
+ lower(e) {
+ //并且让页码+1,调用获取数据的方法获取第二页数据
+ this.classParams.pageNum++
+ if (this.classParams.pageNum > this.totalPage) {
+ uni.$u.toast('已加载全部数据')
+ return
+ }
+ //此处调用自己获取数据列表的方法
+ this.getClass()
+ },
+ scrollView(e) {
+ // console.log(e)
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ .custom-navbar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 999;
+ background: #ffffff;
+
+ .navbar-content {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 44px;
+ padding-top: var(--status-bar-height);
+ }
+
+ .nav-left {
+ flex-shrink: 0;
+ width: 80px;
+ padding-left: 15px;
+ box-sizing: border-box;
+ }
+
+ .back-btn {
+ display: flex;
+ align-items: center;
+ padding: 8px 12px 8px 0;
+ }
+
+ .back-text {
+ font-size: 16px;
+ color: #333;
+ }
+
+ .navbar-title {
+ flex: 1;
+ font-size: 16px;
+ text-align: center;
+ font-weight: bold;
+ color: #333;
+ }
+
+ .nav-right {
+ flex-shrink: 0;
+ width: 80px;
+ }
+
+
+ }
+
+ .page-content {
+ min-height: calc(100vh - 44px);
+ box-sizing: border-box;
+ padding: 0 15px;
+
+ .card-t {
+ width: 100%;
+ padding: 0 6rpx;
+ box-sizing: border-box;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 20rpx;
+
+ .card-t-l {
+ font-size: 36rpx;
+ font-weight: bold;
+ }
+
+ .card-t-r {
+ color: #999;
+ cursor: pointer;
+ font-size: 28rpx;
+ }
+
+ .uni-stat__select {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 2rpx 20rpx;
+ border: 1rpx solid #ccc;
+ border-radius: 99rpx;
+ background: #fff;
+ cursor: pointer;
+
+
+ text {
+ color: #999;
+ font-size: 28rpx;
+ margin-right: 6rpx;
+ }
+ }
+ }
+
+ .cardList {
+ width: 100%;
+ height: calc(100vh - 130px);
+ box-sizing: border-box;
+
+ .card-i {
+ width: 100%;
+ background: #fff;
+ border-radius: 20rpx;
+ padding: 15px;
+ margin-bottom: 15px;
+ box-sizing: border-box;
+ box-shadow: 4px 4px 12px rgba(150, 150, 150, .05);
+
+ .card-line {
+ margin-bottom: 15px;
+ display: flex;
+ align-items: flex-start;
+
+ &:last-of-type {
+ margin-bottom: 0;
+ }
+
+ .card-tit {
+ flex-shrink: 0;
+ width: 140rpx;
+ }
+
+ .u-button {
+ margin-right: 30px;
+
+ &:last-of-type {
+ margin-right: 0;
+ }
+ }
+ }
+ }
+ }
+ }
+</style>
\ No newline at end of file
diff --git a/pages/review/signPage.vue b/pages/review/signPage.vue
new file mode 100644
index 0000000..2d2179e
--- /dev/null
+++ b/pages/review/signPage.vue
@@ -0,0 +1,388 @@
+<template>
+ <view class="signature-container">
+ <view class="canvas-container">
+ <canvas canvas-id="signatureCanvas" id="signatureCanvas" class="signature-canvas"
+ @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd"
+ disable-scroll></canvas>
+ <view class="toast" v-if="toastVisible">请签写您的名字</view>
+ </view>
+ <view class="controls">
+ <view></view>
+ <view class="btn-group">
+ <button class="btn btn-clear" @tap="clearCanvas" :disabled="uploading">清空</button>
+ <button class="btn btn-confirm" @tap="saveSignature" :disabled="uploading || !hasDrawn">
+ {{ uploading ? '上传中...' : '确定' }}
+ </button>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import VUE_APP_BASE_URL from "../../common/constant";
+ import {
+ postSignaure
+ } from "../../api/review.js"
+ export default {
+ name: 'SignaturePad',
+ data() {
+ return {
+ canvas: null,
+ ctx: null,
+ isDrawing: false,
+ hasDrawn: false,
+ lastX: 0,
+ lastY: 0,
+ toastVisible: true,
+ systemInfo: null,
+ uploading: false,
+ id: null
+ }
+ },
+ onReady() {
+ this.initCanvas();
+ },
+ onLoad(e) {
+ this.getSystemInfo();
+ this.id = e.id && JSON.parse(decodeURIComponent(e.id))
+ },
+ onUnload() {
+ this.cleanup();
+ },
+ methods: {
+ getSystemInfo() {
+ const that = this;
+ wx.getSystemInfo({
+ success(res) {
+ that.systemInfo = res;
+ that.initCanvas();
+ }
+ });
+ },
+
+ initCanvas() {
+ if (!this.systemInfo) return;
+ this.ctx = wx.createCanvasContext('signatureCanvas', this);
+ this.ctx.setLineCap('round');
+ this.ctx.setLineJoin('round');
+ this.ctx.setStrokeStyle('#1A1A1A');
+ this.ctx.setLineWidth(2);
+ this.ctx.setFillStyle('#1A1A1A');
+ this.clearCanvas();
+ },
+
+ handleTouchStart(e) {
+ if (!this.ctx) return;
+
+ const touch = e.touches[0];
+ this.isDrawing = true;
+ [this.lastX, this.lastY] = [touch.x, touch.y];
+ this.drawDot(this.lastX, this.lastY);
+ this.hideToast();
+ this.hasDrawn = true;
+ },
+
+ handleTouchMove(e) {
+ if (!this.isDrawing || !this.ctx) return;
+
+ const touch = e.touches[0];
+ const x = touch.x;
+ const y = touch.y;
+
+ // 绘制线条
+ this.ctx.beginPath();
+ this.ctx.moveTo(this.lastX, this.lastY);
+ this.ctx.lineTo(x, y);
+ this.ctx.stroke();
+ this.ctx.draw(true);
+
+ this.drawDot(x, y);
+
+ [this.lastX, this.lastY] = [x, y];
+ },
+
+ handleTouchEnd() {
+ this.isDrawing = false;
+ },
+
+ drawDot(x, y) {
+ if (!this.ctx) return;
+
+ this.ctx.beginPath();
+ this.ctx.arc(x, y, 1, 0, 2 * Math.PI);
+ this.ctx.fill();
+ this.ctx.draw(true);
+ },
+
+ clearCanvas() {
+ if (!this.ctx) return;
+
+
+ this.ctx.clearRect(0, 0, 1000, 1000);
+ this.ctx.setFillStyle('#F5F7FB');
+ this.ctx.fillRect(0, 0, 1000, 1000);
+ this.ctx.draw(true);
+
+ this.hasDrawn = false;
+ this.showToast();
+ },
+
+ showToast() {
+ this.toastVisible = true;
+ },
+
+ hideToast() {
+ this.toastVisible = false;
+ },
+
+ async saveSignature() {
+ if (!this.hasDrawn) {
+ wx.showToast({
+ title: '您还未签名!',
+ icon: 'none',
+ duration: 2000
+ });
+ return;
+ }
+ if (this.uploading) return;
+ this.uploading = true;
+ try {
+ const tempFilePath = await this.canvasToTempFile();
+ const uploadResult = await this.uploadToServer(tempFilePath);
+ await this.handleUploadSuccess(uploadResult);
+
+ } catch (error) {
+ this.handleUploadError(error);
+ } finally {
+ this.uploading = false;
+ }
+ },
+
+ canvasToTempFile() {
+ return new Promise((resolve, reject) => {
+ wx.canvasToTempFilePath({
+ canvasId: 'signatureCanvas',
+ quality: 1,
+ fileType: 'png',
+ success: (res) => {
+ resolve(res.tempFilePath);
+ },
+ fail: (err) => {
+ reject(new Error('生成图片失败:' + JSON.stringify(err)));
+ }
+ }, this);
+ });
+ },
+
+ uploadToServer(tempFilePath) {
+ return new Promise((resolve, reject) => {
+ wx.uploadFile({
+ url: `${VUE_APP_BASE_URL}/system/common/uploadFile`, // 替换为你的上传接口
+ filePath: tempFilePath,
+ name: 'file',
+ formData: {},
+ header: {
+ 'Authorization': uni.getStorageSync('tk'), // 如果有token认证
+ 'Content-Type': 'multipart/form-data'
+ },
+ success: (res) => {
+ if (res.statusCode === 200) {
+ try {
+ const data = JSON.parse(res.data);
+ resolve(data);
+ } catch (e) {
+ reject(new Error('解析响应数据失败'));
+ }
+ } else {
+ reject(new Error(`上传失败,状态码:${res.statusCode}`));
+ }
+ },
+ fail: (err) => {
+ reject(new Error('网络请求失败:' + JSON.stringify(err)));
+ }
+ });
+ });
+ },
+
+ async handleUploadSuccess(res) {
+ try {
+ if (!res.data || !res.data.path) {
+ throw new Error('未获取到文件路径');
+ }
+ const filePath = res.data.path;
+ const submitResult = await this.submitSignatureInfo(filePath);
+ this.handleFinalSuccess(submitResult);
+ } catch (error) {
+ throw new Error('提交签名信息失败:' + error.message);
+ }
+ },
+
+ async submitSignatureInfo(path) {
+ const res = await postSignaure({
+ id: this.id,
+ sign: path
+ })
+ if (res.code == 200) {
+ return res
+ } else {
+ reject(new Error(`提交失败,状态码:${res.code}`));
+ }
+ },
+
+ handleFinalSuccess(result) {
+ wx.showToast({
+ title: '签名提交成功',
+ icon: 'success',
+ duration: 2000
+ });
+ setTimeout(() => {
+ // const pages = getCurrentPages();
+ // if (pages.length > 1) {
+ // const prevPage = pages[pages.length - 2];
+ // if (prevPage) {
+ // prevPage.needRefresh = true;
+ // }
+ // wx.navigateBack({
+ // delta: 1,
+ // success: () => {
+ // console.log('返回成功,页面应该刷新');
+ // }
+ // });
+ // } else {
+ wx.reLaunch({
+ url: '/pages/review/index'
+ });
+ // }
+ }, 1500);
+ },
+
+ handleUploadError(error) {
+ console.error('上传失败:', error);
+
+ wx.showToast({
+ title: '上传失败,请重试',
+ icon: 'none',
+ duration: 2000
+ });
+ },
+
+ cleanup() {
+ this.ctx = null;
+ this.isDrawing = false;
+ }
+ }
+ }
+</script>
+
+<style scoped>
+ .signature-container {
+ width: 100vw;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background: #ffffff;
+ }
+
+ .canvas-container {
+ flex: 1;
+ position: relative;
+ background: #F5F7FB;
+ border: 1px solid rgba(0, 0, 0, 0.08);
+ border-radius: 4px;
+ margin: 10px;
+ overflow: hidden;
+ }
+
+ .signature-canvas {
+ width: 100%;
+ height: 100%;
+ background: #F5F7FB;
+ }
+
+ .toast {
+ position: absolute;
+ top: 50%;
+ left: 40%;
+ transform: translate(-50%, -50%);
+ transform: rotate(90deg);
+ font-size: 40rpx;
+ color: rgba(58, 65, 85, 0.4);
+ pointer-events: none;
+ z-index: 100;
+ }
+
+ .controls {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 32px;
+ background: #ffffff;
+ border-top: 1px solid #e5e7eb;
+ }
+
+ .btn {
+ padding: 8px 20px;
+ border: none;
+ border-radius: 4px;
+ font-size: 14px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ }
+
+ .btn-clear {
+ background: rgba(103, 149, 255, 0.2);
+ color: #3670F5;
+ margin-right: 12px;
+ }
+
+ .btn-clear:hover {
+ background: rgba(103, 149, 255, 0.3);
+ }
+
+ .btn-confirm {
+ background: #3670F5;
+ color: #FFFFFF;
+ }
+
+ .btn-confirm:hover {
+ background: #2563eb;
+ }
+
+ .btn-group {
+ display: flex;
+ gap: 10px;
+ }
+
+ /* 微信小程序适配样式 */
+ button {
+ margin: 0;
+ padding: 8px 20px;
+ border-radius: 4px;
+ font-size: 14px;
+ }
+
+ button::after {
+ border: none;
+ }
+
+ /* 横竖屏适配 */
+ @media (orientation: landscape) {
+ .signature-container {
+ flex-direction: column;
+ }
+
+ .canvas-container {
+ height: calc(100vh - 80px);
+ }
+ }
+
+ @media (orientation: portrait) {
+ .signature-container {
+ flex-direction: column;
+ }
+
+ .canvas-container {
+ height: calc(100vh - 120px);
+ }
+ }
+</style>
\ No newline at end of file
diff --git a/pages/tabBar/count/count.vue b/pages/tabBar/count/count.vue
index 8f78d50..402566f 100644
--- a/pages/tabBar/count/count.vue
+++ b/pages/tabBar/count/count.vue
@@ -63,7 +63,11 @@
return {
page: 'pages/tabBar/count/count',
statusBarHeight: '',
- user: {},
+ user: {
+ name: '',
+ phone: '',
+ company: {},
+ },
examParams: {
pageNum: 1,
pageSize: 10,
@@ -75,11 +79,13 @@
},
created(){
-
+ this.getUserDetail()
},
+ onShow(){
+ this.getUserDetail()
+ },
onLoad() {
this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight'];
- this.getUserInfo()
},
methods: {
@@ -89,7 +95,7 @@
});
},
- getUserInfo(){
+ getUserDetail(){
getUserInfo(uni.getStorageSync('uid')).then(res => {
if(res.code == 200) {
this.user = res.data
diff --git a/pages/tabBar/count/countDetail.vue b/pages/tabBar/count/countDetail.vue
index ef8c402..c61c3cd 100644
--- a/pages/tabBar/count/countDetail.vue
+++ b/pages/tabBar/count/countDetail.vue
@@ -21,7 +21,7 @@
丨
<view>{{item.passed == 0?'不合格':'合格'}}</view>
</view>
- <u-button @tap.stop="reExam(item)" class="re-exam-button" plain type="warning" text="重新考试" shape="circle" size="small"></u-button>
+ <u-button @tap.native.stop="reExam(item)" class="re-exam-button" plain type="warning" text="重新考试" shape="circle" size="small"></u-button>
</view>
</view>
</scroll-view>
diff --git a/pages/tabBar/current/detail.vue b/pages/tabBar/current/detail.vue
index b8807b1..ec9d330 100644
--- a/pages/tabBar/current/detail.vue
+++ b/pages/tabBar/current/detail.vue
@@ -237,22 +237,58 @@
this.detail = res.data
this.showDetail = true
if(this.detail.resourceType == 1){
+ wx.showLoading({
+ title: '课程获取中...',
+ mask: true
+ })
this.$nextTick(() => {
- // this.videoUrl = this.videoBaseUrl + this.detail.resourcePath
+ if (!this.detail.resourcePath) {
+ wx.hideLoading()
+ uni.showToast({
+ icon: 'none',
+ title: '文件路径不存在',
+ duration: 2000
+ })
+ return
+ }
this.videoUrl = this.detail.resourcePath
this.moduleKey++
this.$nextTick(() => {
if(isClick == true){
+ wx.hideLoading()
uni.createVideoContext('myVideo', this).play();
}
+ wx.hideLoading()
})
})
+ wx.hideLoading()
}else{
const t = this
- uni.downloadFile({
- url: this.detail.resourcePath,
- // url: 'http://106.15.95.149:8056/api/images/20250718/00571736c0c741e895318c2edd8a3f9d.PDF',
+ wx.showLoading({
+ title: '课程获取中...',
+ mask: true
+ })
+ if (!t.detail.resourcePath) {
+ wx.hideLoading()
+ uni.showToast({
+ icon: 'none',
+ title: '文件路径不存在',
+ duration: 2000
+ })
+ return
+ }
+ wx.downloadFile({
+ url: t.detail.resourcePath,
success: function (res) {
+ if (res.statusCode !== 200 || !res.tempFilePath) {
+ wx.hideLoading()
+ uni.showToast({
+ icon: 'none',
+ title: '文件下载失败',
+ duration: 2000
+ })
+ return
+ }
const data = {
chapterId: chapterId,
courseId: courseId,
@@ -262,29 +298,60 @@
}
postNewStudy(data).then(re=>{
if(re.code == 200){
- this.studyId = re.data
- this.handleUpdate(3)
+ t.studyId = re.data
+ t.handleUpdate(3)
}else{
- uni.$u.toast(res.message)
+ uni.showToast({
+ icon: 'none',
+ duration: 2000,
+ position: 'top',
+ title: `${res.message}`
+ });
}
- })
+ }).catch(err => {
+ console.error('学习记录提交失败:', err)
+ })
var filePath = res.tempFilePath
- uni.openDocument({
+ wx.openDocument({
filePath: filePath,
showMenu: true,
success: function (res) {
- console.log('打开文档成功');
- }
+ wx.hideLoading()
+ },
+ fail: function(res){
+ uni.showToast({
+ icon: 'none',
+ duration: 2000,
+ position: 'top',
+ title: `打开文件失败: ${res.errMsg || '未知错误'}`
+ });
+ wx.hideLoading()
+ }
})
- }
+ },
+ fail: function(res){
+ uni.showToast({
+ icon: 'none',
+ duration: 2000,
+ position: 'top',
+ title: `下载失败: ${res.errMsg || '网络错误'}`
+ });
+ wx.hideLoading()
+ }
})
}
}
}else{
uni.$u.toast(res.message)
}
- })
-
+ }).catch(err => {
+ console.error('获取课程详情失败:', err)
+ uni.showToast({
+ icon: 'none',
+ title: '网络请求失败',
+ duration: 2000
+ })
+ })
},
goBack(){
diff --git a/pages/tabBar/firstPage/firstPage.vue b/pages/tabBar/firstPage/firstPage.vue
index 5dac134..615a143 100644
--- a/pages/tabBar/firstPage/firstPage.vue
+++ b/pages/tabBar/firstPage/firstPage.vue
@@ -1,161 +1,195 @@
<template>
+ <!-- 自定义导航栏 -->
<view>
- <!-- 自定义导航栏 -->
-<!-- <view class="navBarBox fix">
- <view class="statusBar" :style="{ paddingTop: statusBarHeight + 'px' }"></view>
- <view class="navBar">
- <view class="barText">首页</view>
+ <view class="custom-navbar">
+ <view class="navbar-content">
+ <view class="nav-left" @click="handleBack">
+ <view class="back-btn">
+ <text class="back-text">返回</text>
+ </view>
+ </view>
+ <text class="navbar-title">安全教育</text>
+ <view class="nav-right"></view>
</view>
- </view> -->
- <view style="width: 100%;padding: 0 15px;box-sizing: border-box;margin: 20px 0">
- <u-swiper :list="swiperList" indicatorMode="dot" bgColor="#f5f7fa" circular height="160" indicator previousMargin="30" nextMargin="30"></u-swiper>
- </view>
-
- <scroll-view scroll-y="true" class="scroll-Y" @scrolltoupper="upper"
- @scrolltolower="lower" lower-threshold="150" @scroll="scrollView" style="height:calc(100vh - 180px)">
- <view class="m-p-15">
- <view class="card" style="width:100%">
- <view class="card-t">
- <span class="card-t-l">我的线上课程</span>
- <span class="card-t-r" @click="toCourses">查看全部</span>
- </view>
- <view class="card-c" v-if="Array.isArray(classList) && classList.length>0">
- <view class="card-i" v-for="(item,index) in classList" :key="index">
- <u-image radius="16px" width="200rpx" height="200rpx" :show-loading="true" :src="getImageUrl(item.course.logo)" mode="aspectFill">
- </u-image>
- <!-- <view class="card-i-t">目前已学:{{item.totalProgress}}分钟</view>-->
- <view class="card-i-r">
- <view class="card-i-r-t">
- <view>{{item.phaseName + '-' + item.course.name}}</view>
- <span style="color: #999;font-size: 12px;display: flex;align-items: center"><u-icon name="account" color="#999" size="18" style="margin-bottom: 0;margin-right: 2px"></u-icon>{{item.createName +'('+ item.createTime +')'}}</span>
- </view>
- <view class="card-i-r-b">
- <u-tag icon="clock" :text="secondsToHms(item.course.period)" type="success" size="mini" shape="circle" plain plainFill></u-tag>
- <u-button class="study-button" type="primary" text="开始学习" shape="circle" size="small" @click="toStudy(item)"></u-button>
- </view>
- </view>
- </view>
- </view>
- <view class="card-c" v-else>
- <span style="font-size: 28rpx;color: #999;">暂无课程信息</span>
</view>
- </view>
- </view>
- <view class="m-p-15">
- <view class="card" style="width:100%">
- <view class="card-t">
- <span class="card-t-l">我的考试</span>
-<!-- <uni-data-select
+ <view class="page-content" :style="{ paddingTop: navbarHeight + 'px' }">
+ <view style="width: 100%;padding: 0 15px;box-sizing: border-box;margin: 20px 0">
+ <u-swiper :list="swiperList" indicatorMode="dot" bgColor="#f5f7fa" circular height="160" indicator
+ previousMargin="30" nextMargin="30"></u-swiper>
+ </view>
+ <scroll-view scroll-y="true" class="scroll-Y" @scrolltoupper="upper" @scrolltolower="lower"
+ lower-threshold="150" @scroll="scrollView" style="height:calc(100vh - 244px)">
+ <view class="m-p-15">
+ <view class="card" style="width:100%">
+ <view class="card-t">
+ <span class="card-t-l">我的线上课程</span>
+ <span class="card-t-r" @click="toCourses">查看全部</span>
+ </view>
+ <view class="card-c" v-if="Array.isArray(classList) && classList.length>0">
+ <view class="card-i" v-for="(item,index) in classList" :key="index">
+ <u-image radius="16px" width="200rpx" height="200rpx" :show-loading="true"
+ :src="getImageUrl(item.course.logo)" mode="aspectFill">
+ </u-image>
+ <!-- <view class="card-i-t">目前已学:{{item.totalProgress}}分钟</view>-->
+ <view class="card-i-r">
+ <view class="card-i-r-t">
+ <view>{{item.phaseName + '-' + item.course.name}}</view>
+ <span
+ style="color: #999;font-size: 12px;display: flex;align-items: center"><u-icon
+ name="account" color="#999" size="18"
+ style="margin-bottom: 0;margin-right: 2px"></u-icon>{{item.createName +'('+ item.createTime +')'}}</span>
+ </view>
+ <view class="card-i-r-b">
+ <u-tag icon="clock" :text="secondsToHms(item.course.period)" type="success"
+ size="mini" shape="circle" plain plainFill></u-tag>
+ <u-button class="study-button" type="primary" text="开始学习" shape="circle"
+ size="small" @click="toStudy(item)"></u-button>
+ </view>
+ </view>
+ </view>
+ </view>
+ <view class="card-c" v-else>
+ <span style="font-size: 28rpx;color: #999;">暂无课程信息</span>
+ </view>
+ </view>
+ </view>
+ <view class="m-p-15">
+ <view class="card" style="width:100%">
+ <view class="card-t">
+ <span class="card-t-l">我的考试</span>
+ <!-- <uni-data-select
v-model="examParams.state"
placeholder="完成状态"
:localdata="examSelect"
:clear="true"
@change="changeExam"
></uni-data-select> -->
- <div>
-<!-- <span @click="showSelect = true" class="uni-stat__select"><text>{{examSelect[0][examParams.state].text}}</text><u-icon name="arrow-down" color="#999" size="14"></u-icon></span>
+ <div>
+ <!-- <span @click="showSelect = true" class="uni-stat__select"><text>{{examSelect[0][examParams.state].text}}</text><u-icon name="arrow-down" color="#999" size="14"></u-icon></span>
<u-picker :show="showSelect" :columns="examSelect" @confirm="confirm" @cancel="showSelect = false" keyName="text"></u-picker> -->
- <u-tabs :list="examSelect" :current="currentTab" @click="changeState"></u-tabs>
- </div>
-
-
- </view>
- <view class="card-c card-d" v-if="examList && examList.length>0">
- <view class="paper-card" v-for="(item,index) in examList" :key="index" @click="toExam(item)">
- <view class="paper-card-t">
- <!-- <span :class="item.state == 0?'blue':item.state == 1?'red':'green'">[{{item.state == 0?'待考试':item.state == 1?'待批阅':'批阅完成'}}]</span> -->
- {{item.examPaper.name}}</view>
- <view class="tag-area">
- <u-tag :text="item.examPaper.categoryName" plain size="mini"></u-tag>
- <u-tag :text="item.examPaper.limited == 1?'时长:' + item.examPaper.limitTime + '分钟':'不限时'" type="warning" plain size="mini"></u-tag>
- </view>
- <view class="paper-card-b">
- <view style="font-size: 12px;margin-top: 5px;color: #999">
- <view style="margin-bottom: 2px">创建人:{{item.createName}}</view>
- <view>截止日期:{{item.examPaper.deadline.substring(0,10)}}</view>
- </view>
-<!-- <view class="btn-area" v-if="item.state == 0">
+ <u-tabs :list="examSelect" :current="currentTab" @click="changeState"></u-tabs>
+ </div>
+
+
+ </view>
+ <view class="card-c card-d" v-if="examList && examList.length>0">
+ <view class="paper-card" v-for="(item,index) in examList" :key="index"
+ @click="toExam(item)">
+ <view class="paper-card-t">
+ <!-- <span :class="item.state == 0?'blue':item.state == 1?'red':'green'">[{{item.state == 0?'待考试':item.state == 1?'待批阅':'批阅完成'}}]</span> -->
+ {{item.examPaper.name}}
+ </view>
+ <view class="tag-area">
+ <u-tag :text="item.examPaper.categoryName" plain size="mini"></u-tag>
+ <u-tag
+ :text="item.examPaper.limited == 1?'时长:' + item.examPaper.limitTime + '分钟':'不限时'"
+ type="warning" plain size="mini"></u-tag>
+ </view>
+ <view class="paper-card-b">
+ <view style="font-size: 12px;margin-top: 5px;color: #999">
+ <view style="margin-bottom: 2px">创建人:{{item.createName}}</view>
+ <view>截止日期:{{item.examPaper.deadline.substring(0,10)}}</view>
+ </view>
+ <!-- <view class="btn-area" v-if="item.state == 0">
<u-button @click="toExam(item,1)" class="exam-button" type="primary" text="开始考试" shape="circle" size="small"></u-button>
</view> -->
- <view class="btn-area" v-if="item.state == 2">
- <u-button @tap.stop="reExam(item)" class="exam-button" type="primary" text="重新考试" shape="circle" size="small"></u-button>
- <!-- <u-button @click="toExam(item,2)" class="re-exam-button" type="primary" text="查看" shape="circle" size="small"></u-button> -->
+ <view class="btn-area" v-if="item.state == 2">
+ <u-button @tap.native.stop="reExam(item)" class="exam-button" type="primary"
+ text="重新考试" shape="circle" size="small"></u-button>
+ <!-- <u-button @click="toExam(item,2)" class="re-exam-button" type="primary" text="查看" shape="circle" size="small"></u-button> -->
+ </view>
+ </view>
+ </view>
+ </view>
+ <view class="card-c card-d" v-else>
+ <u-empty text="该状态暂无记录" mode="data"></u-empty>
+ </view>
+ </view>
</view>
- </view>
- </view>
- </view>
- <view class="card-c card-d" v-else>
- <u-empty text="该状态暂无记录" mode="data"></u-empty>
- </view>
- </view>
- </view>
- </scroll-view>
+ </scroll-view>
+ </view>
</view>
</template>
<script>
- import {getClassList, getExamList, getSwiperList} from '../../../api/index.js'
+ import {
+ getClassList,
+ getExamList,
+ getSwiperList
+ } from '../../../api/index.js'
import VUE_APP_BASE_URL from 'common/constant.js'
- import {postEndExam, postAgainExam} from "../../../api/wearhouse";
+ import {
+ postEndExam,
+ postAgainExam
+ } from "../../../api/wearhouse";
export default {
- components:{},
+ components: {},
data() {
return {
- showSelect:false,
- swiperList: [
- '/static/defaultCover.jpg','/static/defaultCover.jpg','/static/defaultCover.jpg'
- ],
- titleList:[
- {
- label: '默认排序',
- value: 1,
- }
- ],
- classList: [],
- examList: [],
- totalPage: 0,
- page: 'pages/tabBar/firstPage/firstPage',
- statusBarHeight: '',
- classParams:{
- pageNum: 1,
- pageSize: 3,
- },
- examParams: {
- pageNum: 1,
- pageSize: 10,
- state: 0
- },
- currentTab: 0,
- examSelect: [
- { name: "待考试" },
- { name: "批阅完成" }
- ],
+ navbarHeight: 0,
+ showSelect: false,
+ swiperList: [
+ '/static/defaultCover.jpg', '/static/defaultCover.jpg', '/static/defaultCover.jpg'
+ ],
+ titleList: [{
+ label: '默认排序',
+ value: 1,
+ }],
+ classList: [],
+ examList: [],
+ totalPage: 0,
+ page: 'pages/tabBar/firstPage/firstPage',
+ statusBarHeight: '',
+ classParams: {
+ pageNum: 1,
+ pageSize: 3,
+ },
+ examParams: {
+ pageNum: 1,
+ pageSize: 10,
+ state: 0
+ },
+ currentTab: 0,
+ examSelect: [{
+ name: "待考试"
+ },
+ {
+ name: "批阅完成"
+ }
+ ],
role: '',
- realname:''
+ realname: ''
}
-
+
},
onLoad() {
//获取手机状态栏高度
- this.statusBarHeight = uni.getSystemInfoSync()['statusBarHeight'];
-
- this.examList = []
- this.classParams.pageNum = 1
- this.examParams.pageNum = 1
- this.getSwiper()
- this.getClass()
- this.getExamList()
+ this.getNavbarHeight()
+
+ this.examList = []
+ this.classParams.pageNum = 1
+ this.examParams.pageNum = 1
+ this.getSwiper()
+ this.getClass()
+ this.getExamList()
},
- onShow(){
- // this.role = uni.getStorageSync('roleName');
- // this.realname = uni.getStorageSync('user').realName
- // this.tabBarLists = uni.getStorageSync('tabBarList');
+ onShow() {
},
- created(){
- },
+ created() {},
methods: {
+ getNavbarHeight() {
+ const systemInfo = uni.getSystemInfoSync()
+ const statusBarHeight = systemInfo.statusBarHeight
+ const navbarHeight = 44
+ this.navbarHeight = statusBarHeight + navbarHeight
+ },
+ handleBack() {
+ uni.navigateTo({
+ url: '/pages/menuPage/index'
+ })
+ },
loginOut() {
uni.clearStorageSync();
uni.clearStorage();
@@ -164,414 +198,456 @@
})
},
- confirm(e) {
- this.examParams.state = e.value[0].value
- this.examParams.pageNum = 1
- this.getExamList()
- this.showSelect = false
- },
+ confirm(e) {
+ this.examParams.state = e.value[0].value
+ this.examParams.pageNum = 1
+ this.getExamList()
+ this.showSelect = false
+ },
- changeState(e){
- this.currentTab = e.index
- this.examParams.state = e.index == 0?0:2
- this.examParams.pageNum = 1
- this.getExamList()
- },
+ changeState(e) {
+ this.currentTab = e.index
+ this.examParams.state = e.index == 0 ? 0 : 2
+ this.examParams.pageNum = 1
+ this.getExamList()
+ },
- async getSwiper(){
- const res = await getSwiperList()
- if(res.code == 200){
- let list = res.data.list || []
- if(list.length>0){
- this.swiperList = list.map(i=>VUE_APP_BASE_URL + '/api/' + i.imgUrl) || []
- }
- }else{
- uni.$u.toast(res.message)
- }
- },
+ async getSwiper() {
+ const res = await getSwiperList()
+ if (res.code == 200) {
+ let list = res.data.list || []
+ if (list.length > 0) {
+ this.swiperList = list.map(i => VUE_APP_BASE_URL + '/api/' + i.imgUrl) || []
+ }
+ } else {
+ uni.$u.toast(res.message)
+ }
+ },
- getClass(){
- getClassList(this.classParams).then(res => {
- if(res.code == 200) {
- if(res.data && res.data.list.length > 0){
+ getClass() {
+ getClassList(this.classParams).then(res => {
+ if (res.code == 200) {
+ if (res.data && res.data.list.length > 0) {
this.classList = res.data.list
- }else {
- this.classList = []
+ } else {
+ this.classList = []
}
- }else{
+ } else {
uni.$u.toast(res.message)
}
})
},
- getExamList(){
- getExamList(this.examParams).then(res => {
- if(res.code == 200) {
- let list = res.data.list?res.data.list: [];
- if (res.data.pageNum != 1) {
- this.examList = this.examList.concat(list)
- } else {
- this.examList = res.data.list
- }
- this.totalPage = res.data.totalPage
- }else{
- uni.$u.toast(res.message)
- }
- })
- },
+ getExamList() {
+ getExamList(this.examParams).then(res => {
+ if (res.code == 200) {
+ let list = res.data.list ? res.data.list : [];
+ if (res.data.pageNum != 1) {
+ this.examList = this.examList.concat(list)
+ } else {
+ this.examList = res.data.list
+ }
+ this.totalPage = res.data.totalPage
+ } else {
+ uni.$u.toast(res.message)
+ }
+ })
+ },
- getImageUrl(logo) {
- return logo ? VUE_APP_BASE_URL + '/api/' + logo : '/static/defaultCover.jpg';
- },
+ getImageUrl(logo) {
+ return logo ? VUE_APP_BASE_URL + '/api/' + logo : '/static/defaultCover.jpg';
+ },
- toStudy(item) {
- uni.setStorageSync("prevPage", '/pages/tabBar/firstPage/firstPage');
- uni.navigateTo({
- url: `/pages/tabBar/current/detail?bank=` + encodeURIComponent(JSON.stringify(item))
- })
- },
+ toStudy(item) {
+ uni.setStorageSync("prevPage", '/pages/tabBar/firstPage/firstPage');
+ uni.navigateTo({
+ url: `/pages/tabBar/current/detail?bank=` + encodeURIComponent(JSON.stringify(item))
+ })
+ },
- toExam(item){
- console.log(item,'item')
- if(item.state == 0 && item.examPaper.deadline){
- const deadline = item.examPaper.deadline
- const deadlineTime = new Date(deadline).getTime()
- const currentTime = new Date().getTime()
- if (currentTime > deadlineTime) {
- uni.$u.toast('已超过考试截止时间,不可重新考试')
- return
- }
- }
- if(item.state == 0){
- uni.showModal({
- title: '提示',
- content: item.examPaper.limited == 1?'该考试限制时长为:' + item.examPaper.limitTime + '分钟,进入后开始计时,计时结束自动交卷,是否继续?':'是否确认考试?',
- success: function (res) {
- if (res.confirm) {
- uni.setStorageSync("prevPage", '/pages/tabBar/firstPage/firstPage');
- uni.navigateTo({
- url: `/pages/tabBar/firstPage/exam?bank=` + encodeURIComponent(JSON.stringify(item)) + `&type=` + encodeURIComponent(JSON.stringify(1))
- })
- } else if (res.cancel) {
- console.log('用户点击取消');
- }
- }
- })
- }else{
- uni.setStorageSync("prevPage", '/pages/tabBar/firstPage/firstPage');
- uni.navigateTo({
- url: `/pages/tabBar/firstPage/exam?bank=` + encodeURIComponent(JSON.stringify(item)) + `&type=` + encodeURIComponent(JSON.stringify(2))
- })
- }
- },
-
- async reExam(item){
- const t = this
- if(item.examPaper.deadline){
- const deadline = item.examPaper.deadline
- const deadlineTime = new Date(deadline).getTime()
- const currentTime = new Date().getTime()
- if (currentTime > deadlineTime) {
- uni.$u.toast('已超过考试截止时间,不可重新考试')
- return
+ toExam(item) {
+ if (item.state == 0 && item.examPaper.deadline) {
+ const deadline = item.examPaper.deadline
+ const deadlineTime = new Date(deadline).getTime()
+ const currentTime = new Date().getTime()
+ if (currentTime > deadlineTime) {
+ uni.$u.toast('已超过考试截止时间,不可重新考试')
+ return
+ }
}
- }
- uni.showModal({
- title: '提示',
- content: '是否重新考试?',
- success: async function (res) {
- if (res.confirm) {
- const res = await postAgainExam({paperId: item.paperId,studentId: uni.getStorageSync('uid')})
- if(res.code == 200){
- uni.$u.toast(res.message)
- t.currentTab = 0
- t.examParams.state = 0
- t.examParams.pageNum = 1
- t.getExamList()
- }else{
- uni.$u.toast(res.message)
- }
- } else if (res.cancel) {
- console.log('用户点击取消');
- }
- }
- })
- },
+ if (item.state == 0) {
+ uni.showModal({
+ title: '提示',
+ content: item.examPaper.limited == 1 ? '该考试限制时长为:' + item.examPaper.limitTime +
+ '分钟,进入后开始计时,计时结束自动交卷,是否继续?' : '是否确认考试?',
+ success: function(res) {
+ if (res.confirm) {
+ uni.setStorageSync("prevPage", '/pages/tabBar/firstPage/firstPage');
+ uni.navigateTo({
+ url: `/pages/tabBar/firstPage/exam?bank=` + encodeURIComponent(JSON
+ .stringify(item)) + `&type=` + encodeURIComponent(JSON
+ .stringify(1))
+ })
+ } else if (res.cancel) {
+ console.log('用户点击取消');
+ }
+ }
+ })
+ } else {
+ uni.setStorageSync("prevPage", '/pages/tabBar/firstPage/firstPage');
+ uni.navigateTo({
+ url: `/pages/tabBar/firstPage/exam?bank=` + encodeURIComponent(JSON.stringify(item)) +
+ `&type=` + encodeURIComponent(JSON.stringify(2))
+ })
+ }
+ },
- secondsToHms(seconds) {
- seconds = Number(seconds);
- const h = Math.floor(seconds / 3600);
- const m = Math.floor(seconds % 3600 / 60);
- const s = Math.floor(seconds % 3600 % 60);
+ async reExam(item) {
+ const t = this
+ if (item.examPaper.deadline) {
+ const deadline = item.examPaper.deadline
+ const deadlineTime = new Date(deadline).getTime()
+ const currentTime = new Date().getTime()
+ if (currentTime > deadlineTime) {
+ uni.$u.toast('已超过考试截止时间,不可重新考试')
+ return
+ }
+ }
+ uni.showModal({
+ title: '提示',
+ content: '是否重新考试?',
+ success: async function(res) {
+ if (res.confirm) {
+ const res = await postAgainExam({
+ paperId: item.paperId,
+ studentId: uni.getStorageSync('uid')
+ })
+ if (res.code == 200) {
+ uni.$u.toast(res.message)
+ t.currentTab = 0
+ t.examParams.state = 0
+ t.examParams.pageNum = 1
+ t.getExamList()
+ } else {
+ uni.$u.toast(res.message)
+ }
+ } else if (res.cancel) {
+ console.log('用户点击取消');
+ }
+ }
+ })
+ },
- const hDisplay = h > 0 ? String(h).padStart(2, '0') : '00';
- const mDisplay = m > 0 ? String(m).padStart(2, '0') : '00';
- const sDisplay = s > 0 ? String(s).padStart(2, '0') : '00';
- return `${hDisplay}:${mDisplay}:${sDisplay}`;
- },
+ secondsToHms(seconds) {
+ seconds = Number(seconds);
+ const h = Math.floor(seconds / 3600);
+ const m = Math.floor(seconds % 3600 / 60);
+ const s = Math.floor(seconds % 3600 % 60);
- upper(e) {
- // console.log(e)
- },
- lower(e) {
- //并且让页码+1,调用获取数据的方法获取第二页数据
- this.examParams.pageNum++
- //此处调用自己获取数据列表的方法
- if (this.examParams.pageNum > this.totalPage){
- uni.$u.toast('已加载全部数据')
- return
- }
- this.getExamList()
- },
- scrollView(e) {
- // console.log(e)
- },
+ const hDisplay = h > 0 ? String(h).padStart(2, '0') : '00';
+ const mDisplay = m > 0 ? String(m).padStart(2, '0') : '00';
+ const sDisplay = s > 0 ? String(s).padStart(2, '0') : '00';
+ return `${hDisplay}:${mDisplay}:${sDisplay}`;
+ },
- toCourses(){
- uni.switchTab({
- url: '/pages/tabBar/current/current'
- })
- },
+ upper(e) {
+ // console.log(e)
+ },
+ lower(e) {
+ //并且让页码+1,调用获取数据的方法获取第二页数据
+ this.examParams.pageNum++
+ //此处调用自己获取数据列表的方法
+ if (this.examParams.pageNum > this.totalPage) {
+ uni.$u.toast('已加载全部数据')
+ return
+ }
+ this.getExamList()
+ },
+ scrollView(e) {
+ // console.log(e)
+ },
+
+ toCourses() {
+ uni.switchTab({
+ url: '/pages/tabBar/current/current'
+ })
+ },
}
}
-
</script>
-<style lang="scss">
-.navBarBox .navBar {
- background-color:#fff;
- height: 50px;
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
- box-shadow: 0 3px 12px rgba(0,0,0,0.05);
-
-}
-.fix{
- position: sticky;
- top: 0;
- left: 0;
- right: 0;
- width: 100%;
- z-index: 1;
-}
-.barText{
- /* text-align: center; */
- font-size: 16px;
- font-weight: 600;
- flex: 2;
- margin-left: 45%;
-}
-.statusBar{
- background-color:lightgrey;
-}
-.m-p-15{
- width: 100%;
- box-sizing: border-box;
- padding: 0 15px;
-}
-.card{
- width: 100%;
- margin-bottom: 40rpx;
+<style lang="scss" scoped>
+ .custom-navbar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 999;
+ background: #ffffff;
+ border-bottom: 1px solid #f0f0f0;
- .card-t{
- width: 100%;
- padding: 0 6rpx;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 20rpx;
-
- .card-t-l{
- font-size: 36rpx;
- font-weight: bold;
- }
- .card-t-r{
- color: #999;
- cursor: pointer;
- font-size: 28rpx;
- }
- .uni-stat__select{
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 2rpx 20rpx;
- border: 1rpx solid #ccc;
- border-radius: 99rpx;
- background: #fff;
- cursor: pointer;
-
-
- text{
- color: #999;
- font-size: 28rpx;
- margin-right: 6rpx;
+ .navbar-content {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 44px;
+ padding-top: var(--status-bar-height);
}
- }
- }
- .card-c{
- background: #fff;
- border-radius: 20rpx;
- padding: 15px;
+ .nav-left {
+ flex-shrink: 0;
+ width: 80px;
+ padding-left: 15px;
+ box-sizing: border-box;
+ }
- ::v-deep .u-empty{
- margin-top: 40rpx !important;
+ .back-btn {
+ display: flex;
+ align-items: center;
+ padding: 8px 12px 8px 0;
+ }
+
+ .back-text {
+ font-size: 16px;
+ color: #000000;
+ }
+
+ .navbar-title {
+ flex: 1;
+ font-size: 16px;
+ text-align: center;
+ font-weight: bold;
+ color: #000000;
+ }
+
+ .nav-right {
+ flex-shrink: 0;
+ width: 80px;
+ }
+
+
}
-
- .card-i{
- padding-bottom: 15px;
- margin-bottom: 15px;
- border-bottom: 1px solid #f0f0f0;
- position: relative;
- display: flex;
- align-items: flex-start;
- box-sizing: border-box;
- &:last-of-type{
- margin-bottom: 0;
- padding-bottom: 0;
- border-bottom: none;
- }
- .card-i-t{
- position: absolute;
- width: 250rpx;
- height: 30px;
- border-radius: 8rpx;
- line-height: 30px;
- color: #fff;
- padding: 0 10rpx;
- box-sizing: border-box;
- left: 0;
- bottom: 0;
- background: rgba(0,0,0,.4);
- }
- .card-i-r{
- width: 100%;
- height: 200rpx;
- margin-left: 20rpx;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- .card-i-r-t{
- view{
- font-size: 36rpx;
- margin-bottom: 10rpx;
- font-family: "PingFang SC";
- font-weight: 800;
- overflow: hidden;
- text-overflow: ellipsis;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
- }
- }
- .card-i-r-b{
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: space-between;
+ .page-content {
+ min-height: calc(100vh - 44px);
+ }
- ::v-deep .u-button{
- width: 220rpx;
- margin: 0;
- box-shadow: 3px 3px 12px rgba(51,133,217,.3), -2px -2px 6px #fff;
- border: 1px solid rgba(255,255,255,.8);
- }
- }
- }
- }
- }
- .card-d{
- background: none;
- padding: 0 0 15px;
- .paper-card{
- background: #fff;
- margin-bottom: 15px;
- padding: 15px;
- box-sizing: border-box;
- position: relative;
- border-radius: 20rpx;
+ .m-p-15 {
+ width: 100%;
+ box-sizing: border-box;
+ padding: 0 15px;
+ }
- &:last-of-type{
- margin-bottom: 0;
- }
+ .card {
+ width: 100%;
+ margin-bottom: 40rpx;
- .paper-card-t{
- font-size: 36rpx;
- margin-bottom: 10rpx;
- font-family: "PingFang SC";
- font-weight: 800;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-
- .blue{
- font-size: 32rpx;
- color: #0f7ff9
- }
-
- .green{
- font-size: 32rpx;
- color: #5ac725
- }
- .red{
- font-size: 32rpx;
- color: #f56c6c
- }
- }
-
- .tag-area{
+ .card-t {
width: 100%;
- display: flex;
-
- ::v-deep .u-tag-wrapper{
- margin-right: 10rpx;
- }
- }
-
- .paper-card-b{
- display: flex;
- align-items: flex-end;
- justify-content: space-between;
-
-
- .btn-area{
+ padding: 0 6rpx;
+ box-sizing: border-box;
display: flex;
align-items: center;
-
- ::v-deep .u-button{
- width: 220rpx;
- margin: 0;
- box-shadow: 3px 3px 12px rgba(51,133,217,.3), -2px -2px 6px #fff;
- border: 1px solid rgba(255,255,255,.8);
+ justify-content: space-between;
+ margin-bottom: 20rpx;
+
+ .card-t-l {
+ font-size: 36rpx;
+ font-weight: bold;
}
- }
- .btn-area2{
- display: flex;
- align-items: center;
-
- ::v-deep .u-button{
- width: 150rpx;
- margin: 0;
-
- &:last-of-type{
- box-shadow: 3px 3px 12px rgba(51,133,217,.3), -2px -2px 6px #fff;
- border: 1px solid rgba(255,255,255,.8);
- margin-left: 20rpx;
+
+ .card-t-r {
+ color: #999;
+ cursor: pointer;
+ font-size: 28rpx;
+ }
+
+ .uni-stat__select {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 2rpx 20rpx;
+ border: 1rpx solid #ccc;
+ border-radius: 99rpx;
+ background: #fff;
+ cursor: pointer;
+
+
+ text {
+ color: #999;
+ font-size: 28rpx;
+ margin-right: 6rpx;
}
}
}
- }
- }
- }
-}
-.badge span{
- text-align: center;
- width: 100%;
-}
+ .card-c {
+ background: #fff;
+ border-radius: 20rpx;
+ padding: 15px;
+ ::v-deep .u-empty {
+ margin-top: 40rpx !important;
+ }
+
+ .card-i {
+ padding-bottom: 15px;
+ margin-bottom: 15px;
+ border-bottom: 1px solid #f0f0f0;
+ position: relative;
+ display: flex;
+ align-items: flex-start;
+ box-sizing: border-box;
+
+ &:last-of-type {
+ margin-bottom: 0;
+ padding-bottom: 0;
+ border-bottom: none;
+ }
+
+ .card-i-t {
+ position: absolute;
+ width: 250rpx;
+ height: 30px;
+ border-radius: 8rpx;
+ line-height: 30px;
+ color: #fff;
+ padding: 0 10rpx;
+ box-sizing: border-box;
+ left: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, .4);
+ }
+
+ .card-i-r {
+ width: 100%;
+ height: 200rpx;
+ margin-left: 20rpx;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ .card-i-r-t {
+ view {
+ font-size: 36rpx;
+ margin-bottom: 10rpx;
+ font-family: "PingFang SC";
+ font-weight: 800;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ }
+ }
+
+ .card-i-r-b {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ ::v-deep .u-button {
+ width: 220rpx;
+ margin: 0;
+ box-shadow: 3px 3px 12px rgba(51, 133, 217, .3), -2px -2px 6px #fff;
+ border: 1px solid rgba(255, 255, 255, .8);
+ }
+ }
+ }
+ }
+ }
+
+ .card-d {
+ background: none;
+ padding: 0 0 15px;
+
+ .paper-card {
+ background: #fff;
+ margin-bottom: 15px;
+ padding: 15px;
+ box-sizing: border-box;
+ position: relative;
+ border-radius: 20rpx;
+
+ &:last-of-type {
+ margin-bottom: 0;
+ }
+
+ .paper-card-t {
+ font-size: 36rpx;
+ margin-bottom: 10rpx;
+ font-family: "PingFang SC";
+ font-weight: 800;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ .blue {
+ font-size: 32rpx;
+ color: #0f7ff9
+ }
+
+ .green {
+ font-size: 32rpx;
+ color: #5ac725
+ }
+
+ .red {
+ font-size: 32rpx;
+ color: #f56c6c
+ }
+ }
+
+ .tag-area {
+ width: 100%;
+ display: flex;
+
+ ::v-deep .u-tag-wrapper {
+ margin-right: 10rpx;
+ }
+ }
+
+ .paper-card-b {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+
+
+ .btn-area {
+ display: flex;
+ align-items: center;
+
+ ::v-deep .u-button {
+ width: 220rpx;
+ margin: 0;
+ box-shadow: 3px 3px 12px rgba(51, 133, 217, .3), -2px -2px 6px #fff;
+ border: 1px solid rgba(255, 255, 255, .8);
+ }
+ }
+
+ .btn-area2 {
+ display: flex;
+ align-items: center;
+
+ ::v-deep .u-button {
+ width: 150rpx;
+ margin: 0;
+
+ &:last-of-type {
+ box-shadow: 3px 3px 12px rgba(51, 133, 217, .3), -2px -2px 6px #fff;
+ border: 1px solid rgba(255, 255, 255, .8);
+ margin-left: 20rpx;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .badge span {
+ text-align: center;
+ width: 100%;
+ }
</style>
\ No newline at end of file
diff --git a/static/educate.png b/static/educate.png
new file mode 100644
index 0000000..2c7b7ac
--- /dev/null
+++ b/static/educate.png
Binary files differ
diff --git a/static/review.png b/static/review.png
new file mode 100644
index 0000000..547fd8c
--- /dev/null
+++ b/static/review.png
Binary files differ
--
Gitblit v1.9.2