34 Commits

Author SHA1 Message Date
f122640068 毕设-dev-8.21 2025-08-21 10:39:12 +08:00
4807d0547b 毕设-dev-first 2025-08-19 13:41:17 +08:00
3dc4d64215 青橙1.1.2 2025-08-16 22:14:42 +08:00
a3ffe71ccb ------1.0.2----- 2025-08-15 15:34:05 +08:00
342e97d5d6 小程序1.0.2 2025-08-15 15:19:05 +08:00
e0684ec229 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	pages/dashboardModule/performanceRanking/performanceRanking.wxss
#	pages/personCenter/resetPwd/resetPwd.js
2025-08-15 14:17:17 +08:00
f47e375bfa 美化了样式3.0 2025-08-15 14:15:10 +08:00
23ab2798d8 美化了样式2.0 2025-08-15 11:14:42 +08:00
1b4d3e310b 美化了样式 2025-08-15 00:36:04 +08:00
2b48faf50d Merge branch 'yt' into dev 2025-08-13 10:52:19 +08:00
fab8d88faf 小程序修改代码 2025-08-13 10:52:02 +08:00
5fc1378051 -------- 2025-08-12 19:36:03 +08:00
12480f3706 Merge remote-tracking branch 'origin/dev' into dev 2025-08-10 16:22:31 +08:00
05af3d221c 修复了验证码bug 2025-08-10 16:22:02 +08:00
f17226cc97 小程序修改代码 2025-08-10 11:43:30 +08:00
d5e4f0d7eb 小程序修改代码 2025-08-10 11:28:38 +08:00
d17f6f09c5 修复了验证码bug 2025-08-10 11:25:09 +08:00
8a085da7dc 修复了验证码bug 2025-08-09 22:30:47 +08:00
f871831cbc 修复了禅道的一系列bug 2025-08-09 01:21:59 +08:00
c1817b6255 模拟了微信支付功能 2025-08-08 19:21:04 +08:00
85df7bfc4e 添加了修改头像的功能 2025-08-08 13:48:37 +08:00
990f1850b1 加入了搜索功能 2025-08-07 20:18:00 +08:00
c7dd90f669 修改部分bug 2025-08-07 19:56:53 +08:00
d1b4fa8ca3 修改了经理端部分代码 2025-08-07 11:45:28 +08:00
3996895c0d Merge remote-tracking branch 'origin/dev' into dev 2025-08-06 13:31:59 +08:00
c5f3287e80 ------- 2025-08-06 13:31:38 +08:00
b6a59ce3d8 小程序修改代码 2025-08-06 13:16:08 +08:00
2a1082fc9f Merge remote-tracking branch 'origin/dev' into dev 2025-08-04 20:16:18 +08:00
90162ad74f ------- 2025-08-04 20:15:51 +08:00
50e892adc4 小程序提交 2025-08-04 16:33:23 +08:00
0587539253 小程序提交 2025-08-04 16:31:21 +08:00
5c2082adf4 小程序提交 2025-08-04 16:27:52 +08:00
fa2a7b3499 小程序提交 2025-07-20 18:22:59 +08:00
a1d21c67b8 commission--yt-commit 2025-06-30 13:12:06 +08:00
151 changed files with 7918 additions and 2765 deletions

2
app.js
View File

@ -1,6 +1,6 @@
const { checkLogin } = require('./utils/logcheck');
App({
onLaunch: function () {
// checkLogin()
}
});

View File

@ -1,11 +1,11 @@
{
"pages": [
"pages/personCenter/mine/mine",
"pages/welcome/homePage/homePage",
"pages/loginModule/pwdLogin/pwdLogin",
"pages/personCenter/mine/mine",
"pages/loginModule/agreement/agreement",
"pages/loginModule/privacyPolicy/privacyPolicy",
"pages/personCenter/subCommissionSetting/subCommissionSetting",
"pages/test/testVideo/testVideo",
"pages/personCenter/withdrawal/withdrawal",
"pages/personCenter/withdrawalAccount/withdrawalAccount",
"pages/personCenter/accountSetting/accountSetting",
@ -30,11 +30,20 @@
"pages/course/courseList/courseList",
"pages/course/courseDetail/courseDetail",
"pages/course/createCourseOrder/createCourseOrder",
"pages/course/waitPayOrder/waitPayOrder",
"pages/course/orderDetail/orderDetail",
"pages/course/applyPromotion/applyPromotion",
"pages/course/recommendUser/recommendUser",
"pages/course/courseOrderList/courseOrderList",
"pages/course/courseSettlementRecord/courseSettlementRecord"
"pages/course/courseSettlementRecord/courseSettlementRecord",
"pages/loginModule/employeeAccountApply/employeeAccountApply",
"pages/loginModule/employeeAccountNotice/employeeAccountNotice",
"pages/loginModule/employeeApplyQuery/employeeApplyQuery",
"pages/dashboardModule/overviewPerformance/overviewPerformance",
"pages/dashboardModule/supervisorPerformance/supervisorPerformance",
"pages/dashboardModule/staffPerformance/staffPerformance",
"pages/dashboardModule/userOrderPerformance/userOrderPerformance",
"pages/dashboardModule/performanceRanking/performanceRanking",
"pages/personCenter/component/modifyNamePop/modifyNamePop"
],
"window": {
"navigationBarTextStyle": "black",
@ -52,16 +61,16 @@
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/projectModule/projectList/projectList",
"text": "接单",
"iconPath": "/static/jd1.png",
"selectedIconPath": "/static/jd2.png"
"pagePath": "pages/course/homepage/homepage",
"text": "主页",
"iconPath": "/static/kc1.png",
"selectedIconPath": "/static/kc2.png"
},
{
"pagePath": "pages/course/homepage/homepage",
"text": "课程",
"iconPath": "/static/course.png",
"selectedIconPath": "/static/courseselected.png"
"pagePath": "pages/projectModule/projectList/projectList",
"text": "接单",
"iconPath": "/static/kc1.png",
"selectedIconPath": "/static/kc2.png"
},
{
"pagePath": "pages/personCenter/mine/mine",

View File

@ -1,9 +1,43 @@
import { baseUrl, globalImgUrl } from "../../../request";
import { decodeBase64 } from "../../../utils/decodebase64";
const { notLogin } = require('../../../utils/util')
// pages/course/courseDetail/courseDetail.js
Page({
data: {
items: [null, null, null,null, null, null],
activeTab: 'intro', // 默认选中“课程简介”
activeIndex: null, // 默认没有任何标题被选中
cid: 0, // 课程ID
courseObj: '', // 课程对象
richText: '', // 课程概述富文本
globalImgUrl,
},
// 获取课程详情
getCourseDetail() {
const cid = this.data.cid;
wx.request({
url: baseUrl + '/course/query/id',
method: 'POST',
data: {
id: cid
},
header: {
Authorization :wx.getStorageSync('token'),
},
success : res => {
console.log(res);
if (res.data.code === 1) {
this.setData({
courseObj: res.data.data,
richText: decodeBase64(res.data.data.detail)
})
} else {
notLogin(res.data.message)
}
}
})
},
/** 切换选项卡 */
@ -28,6 +62,7 @@ Page({
})
},
// 好像不要了
// 跳转申请推广页面
gotoApplyPromotion(e) {
const courseId = e.currentTarget.dataset.id;
@ -40,7 +75,13 @@ Page({
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {},
onLoad(options) {
console.log(options);
this.setData({
cid: options.id,
})
this.getCourseDetail()
},
onReady() {},
@ -50,7 +91,11 @@ Page({
onUnload() {},
onPullDownRefresh() {},
onPullDownRefresh() {
this.getCourseDetail()
// 停止下拉刷新动画
wx.stopPullDownRefresh();
},
onReachBottom() {},

View File

@ -1,3 +1,4 @@
{
"usingComponents": {}
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -1,89 +1,47 @@
<view class="flex-col page">
<view class="flex-col">
<!-- 背景 + 支付信息 -->
<view class="flex-col justify-start section">
<view class="flex-col section_2">
<view class="flex-row items-baseline self-start no-wrap">
<text class="shrink-0 font">券后支付</text>
<text class="shrink-0 font_2 text text_2 mx-15">168元</text>
<text class="flex-1 font">即可观看所有视频</text>
<!-- pages/course/courseDetail/courseDetail.wxml -->
<view class="page">
<!-- 滚动内容 -->
<scroll-view scroll-y class="content no-scrollbar">
<!-- 顶部主图 -->
<view class="hero">
<image class="hero-img" src="{{ globalImgUrl + courseObj.image }}" mode="aspectFill" lazy-load="true" />
</view>
<view class="mt-18 flex-col justify-start items-center self-center text-wrapper" bind:tap="gotoCourseOrder" data-id="{{ '1' }}">
<text class="font_3 text_3">立即购买</text>
<!-- 价格 + 标题 -->
<view class="card">
<view class="price-row">
<view class="price-now">
<text class="price-num">{{ courseObj.discountPrice }}</text>
<text class="price-suffix">元券后价</text>
</view>
<view class="price-origin">
<text class="origin-text">{{ courseObj.originPrice }}元</text>
</view>
</view>
<text class="title">{{ courseObj.name }}</text>
</view>
<!-- 选项卡 -->
<view class="flex-col section_3">
<view class="flex-row justify-center group_2">
<text bindtap="selectTab" data-tab="intro" class="text-tab {{activeTab==='intro'?'tab-active':'tab-inactive'}}">课程简介</text>
<text bindtap="selectTab" data-tab="catalog" class="text-tab {{activeTab==='catalog'?'tab-active':'tab-inactive'}}">课程目录</text>
<!-- 课程概述 -->
<view class="card">
<view class="card-head">
<image class="head-icon" src="./image/cal.png" mode="aspectFit" />
<text class="head-text">课程概述</text>
</view>
<rich-text class="rt" nodes="{{ richText }}"></rich-text>
</view>
<!-- 标题+价格 -->
<view class="flex-col section_4">
<view class="flex-row items-center group_4">
<view class="shrink-0 group_5">
<text class="text_6">168</text>
<text class="font_3 text_7">元券后价</text>
</view>
<view class="ml-4 flex-col justify-start items-start shrink-0 relative group_6">
<text class="font_2 text text_8">268元</text>
<view class="divider pos"></view>
</view>
</view>
<text class="group_4 text_9 mt-9">【早鸟42折】掌握CAD技能+++++++实战工作训练营</text>
</view>
<!-- 占位,避免被底部栏遮挡 -->
<view class="bottom-gap"></view>
</scroll-view>
<!-- 课程概述(仅当 activeTab==='intro' -->
<view wx:if="{{activeTab==='intro'}}" class="flex-col section_5">
<view class="flex-row items-center group_7">
<image class="image" src="./image/cal.png" />
<text class="ml-6 font_2 text_10">课程概述</text>
</view>
<view class="section_6"></view>
</view>
<!-- 课程目录(仅当 activeTab==='catalog' -->
<view wx:if="{{activeTab==='catalog'}}" class="flex-col mt-35">
<view class="flex-col section_7">
<view class="flex-col list">
<view class="flex-col list-item mt-15" wx:for="{{items}}" wx:for-item="item" wx:for-index="index" wx:key="index">
<view class="flex-col justify-start self-end text-wrapper_2">
<text class="font_4 text_11">全集试看</text>
</view>
<view class="flex-row self-start group_8 mt-1">
<text class="shrink-0 self-start font_5 text_12">{{ index + 1}}</text>
<text class="ml-16 flex-1 font_2 {{activeIndex === index ? 'active-title' : ''}}" bindtap="selectCourse" data-index="{{index}}">
推荐片:带你透视中国基层干部的生态图景推荐片:带你透视中国基层干部的生态图景
</text>
</view>
<view class="flex-row justify-between self-stretch group_9 mt-1">
<text class="self-start font_6 text_13" style="margin-top: 10rpx;">视频课·27分59秒</text>
<image class="image_2" src="./image/lock.png" />
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 底部固定按钮栏 -->
<view class="flex-row items-center section_8 section_8_fixed">
<view class="flex-col items-center shrink-0" style="margin-left: 30rpx;">
<image class="image_3" src="./image/messge.png" />
<text class="font_6 text_16 mt-1">咨询</text>
</view>
<view class="ml-44 flex-row flex-1">
<view class="flex-col justify-start items-center text-wrapper_3" bind:tap="gotoApplyPromotion" data-id="{{ '1' }}">
<text class="font_7 text_14">申请推广</text>
</view>
<view class="flex-col justify-start items-center text-wrapper_4 ml-15" bind:tap="gotoCourseOrder" data-id="{{ '1' }}">
<text class="font_7 text_15">立即购买</text>
<!-- 固定底部购买栏 -->
<view class="buy-bar">
<view class="buy-left">
<image class="consult-icon" src="./image/messge.png" mode="aspectFit" />
<text class="consult-text">咨询</text>
</view>
<view class="buy-btn" bindtap="gotoCourseOrder" data-id="{{ courseObj.id }}">
<text class="buy-btn-text">立即购买</text>
</view>
</view>
</view>

View File

@ -1,336 +1,148 @@
/* pages/course/courseDetail/courseDetail.wxss */
/* 通用间距 */
.mt-9 {
margin-top: 16.88rpx;
}
/* .mt-35 {
margin-top: 65.63rpx;
} */
.mt-15 {
margin-top: 28.13rpx;
}
.mt-7 {
margin-top: 13.13rpx;
}
.mt-1 {
margin-top: 1.88rpx;
}
.ml-15 {
margin-left: 28.13rpx;
}
/* 页面容器 */
/* ===== 页面骨架:整页固定、内容滚动、底部栏固定 ===== */
.page {
background-color: #f6f7f9;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
padding-bottom: 100rpx; /* 为底部固定栏预留空间 */
}
/* 背景图 */
.section {
background-image: url('https://ide.code.fun/api/image?token=6858ee4b4ae84d0012334127&name=1f211c9a259577e8af923158ce6e4ab6.png');
background-size: 100% 100%;
background-repeat: no-repeat;
}
/* 顶部遮罩 */
.section_2 {
padding: 131.25rpx 176.25rpx 101.25rpx;
background-color: #00000063;
backdrop-filter: blur(9.38rpx);
}
/* 宽度组 */
.group {
width: 344.34rpx;
}
/* 白色文字 */
.font {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 31.88rpx;
color: #ffffff;
}
/* 橙色按钮 */
.text-wrapper {
padding: 15rpx 0;
background-color: #ff8d1a;
border-radius: 187.5rpx;
width: 208.13rpx;
}
/* 橙色小字体 */
.font_3 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.6rpx;
color: #ff8d1a;
}
.text_3 {
color: #ffffff;
}
/* 选项卡容器 */
.section_3 {
padding: 0 135rpx 7.5rpx 142.5rpx;
background-color: #ffffff;
border-bottom: solid 1.88rpx #9c9c9c;
}
.group_2 {
padding: 22.5rpx 0 11.25rpx;
height: 100vh;
display: flex;
justify-content: center; /* 增加选项卡间隔 */
flex-direction: column;
background: #f6f7f9;
overflow: auto; /* 禁止整页滚动 */
box-sizing: border-box;
font-family: SourceHanSansCN, PingFang SC, Microsoft YaHei, system-ui, -apple-system, sans-serif;
}
/* 标题+价格 */
.section_4 {
padding: 37.5rpx 7.5rpx 30rpx 22.5rpx;
background-color: #ffffff;
/* 独立滚动内容区(隐藏滚动条) */
.content {
flex: 1;
-webkit-overflow-scrolling: touch;
}
.group_4 {
padding: 0 3.75rpx;
.no-scrollbar::-webkit-scrollbar { display: none; width: 0; height: 0; background: transparent; }
.no-scrollbar { scrollbar-width: none; }
/* ===== 顶部主图(自适应圆角阴影) ===== */
.hero {
padding: 24rpx 24rpx 0;
box-sizing: border-box;
}
.group_5 {
line-height: 28.8rpx;
height: 30.58rpx;
.hero-img {
width: 100%;
height: 420rpx; /* 沉浸横幅高度 */
border-radius: 20rpx;
object-fit: cover;
box-shadow: 0 12rpx 30rpx rgba(0,0,0,0.06);
}
.text_6 {
color: #f84947;
font-size: 37.5rpx;
font-family: SourceHanSansCN;
/* ===== 通用卡片容器 ===== */
.card {
margin: 20rpx 24rpx 0;
padding: 22rpx;
border-radius: 20rpx;
background: #ffffff;
box-shadow: 0 10rpx 30rpx rgba(0,0,0,0.05);
box-sizing: border-box;
}
/* ===== 价格区:券后价 + 原价 ===== */
.price-row {
display: flex;
align-items: flex-end;
justify-content: space-between;
}
.price-now { display: inline-flex; align-items: baseline; gap: 8rpx; }
.price-num {
font-size: 44rpx;
line-height: 1;
color: #ff6a00; /* 主题橙 */
font-weight: 700;
line-height: 28.8rpx;
}
.text_7 {
color: #f84947;
line-height: 24.43rpx;
}
.group_6 {
margin-right: 453.75rpx;
width: 75.02rpx;
}
.divider {
background-color: #8c8c8c;
width: 75.02rpx;
height: 1.88rpx;
}
.pos {
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}
.text_9 {
color: #000000;
font-size: 33.75rpx;
font-family: SourceHanSansCN;
line-height: 41.25rpx;
}
.price-suffix { font-size: 24rpx; color: #ff6a00; opacity: .9; }
.price-origin .origin-text { font-size: 24rpx; color: #9aa0a6; text-decoration: line-through; }
/* 课程概述 */
.section_5 {
margin-top: 28.13rpx;
padding: 0 30rpx 52.5rpx;
background-color: #ffffff;
}
.group_7 {
padding: 26.25rpx 0;
}
.image {
width: 39.38rpx;
height: 39.38rpx;
}
/* 概述内容区 */
.section_6 {
background-color: #ffffff00;
height: 791.25rpx;
border-left: solid 1.88rpx #000000;
border-right: solid 1.88rpx #000000;
border-top: solid 1.88rpx #000000;
border-bottom: solid 1.88rpx #000000;
}
/* 目录列表 */
.section_7 {
padding: 31.88rpx 0;
background-color: #ffffff;
}
.list {
margin: 0 22.5rpx;
}
.group_8 {
width: 590.81rpx;
display: flex;
align-items: center; /* 序号垂直居中 */
margin-top: 3rpx !important; /* 视频标题与上方内容的间距 */
}
.list-item {
padding-left: 37.5rpx;
padding-bottom: 18.75rpx;
background-color: #f6f7f9;
border-radius: 10.63rpx;
}
.list-item:first-child {
margin-top: 0;
}
/* 全局试看按钮 */
.text-wrapper_2 {
padding: 3.75rpx 0;
background-color: #ff8d1a;
border-radius: 0rpx 9.38rpx 0rpx 9.38rpx;
}
.font_4 {
font-size: 24rpx; /* 放大字体 */
font-family: SourceHanSansCN;
line-height: 28rpx; /* 放大行高 */
color: #ffffff;
}
.text_11 {
margin: 0 7.5rpx;
line-height: 28rpx; /* 放大行高 */
}
/* 列表文本 */
.font_5 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 19.24rpx;
color: #8f8f8f;
}
.text_12 {
margin-top: 0; /* 垂直居中序号 */
align-self: center !important;
}
.font_2 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 31.88rpx;
color: #000000;
}
/* 其他文本 */
.text {
word-break: break-all;
}
.text_8 {
color: #8c8c8c;
}
.text_2 {
color: #ff8d1a;
}
.group_9 {
padding-left: 41.25rpx;
padding-right: 20.63rpx;
}
.font_6 {
font-size: 22.5rpx;
font-family: SourceHanSansCN;
line-height: 19.24rpx;
color: #8f8f8f;
}
.text_13 {
line-height: 20.79rpx;
}
.image_2 {
width: 30rpx;
height: 30rpx;
}
/* 底部原有按钮组 */
.section_8 {
padding: 15rpx 26.25rpx;
background-color: #ffffff;
}
.image_3 {
width: 52.5rpx;
height: 52.5rpx;
}
.text_16 {
color: #000000;
line-height: 20.94rpx;
}
.text-wrapper_3 {
padding: 22.5rpx 0;
flex: 1 1 268.13rpx;
background-color: #a5d63f;
border-radius: 75rpx;
height: 71.25rpx;
}
.font_7 {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 28.8rpx;
color: #ffffff;
}
.text_14 {
line-height: 28.29rpx;
}
.text-wrapper_4 {
padding: 22.5rpx 0;
flex: 1 1 268.13rpx;
background-color: #ff8d1a;
border-radius: 75rpx;
height: 71.25rpx;
}
.text_15 {
line-height: 28.11rpx;
}
/* 新增:选项卡文字基础样式 */
.text-tab {
/* 课程标题 */
.title {
display: block;
margin-top: 14rpx;
font-size: 32rpx;
font-family: SourceHanSansCN;
line-height: 38rpx;
padding-bottom: 8rpx; /* 文字与下划线之间留白 */
margin: 0 80rpx; /* 增大间距 */
line-height: 46rpx;
color: #111;
font-weight: 600;
word-break: break-word;
}
/* 新增:选中/未选中状态 */
.tab-active {
color: #ff8d1a;
border-bottom: 2rpx solid #ff8d1a;
/* ===== 概述标题行 ===== */
.card-head {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 22rpx;
}
.tab-inactive {
color: #000000;
border-bottom: none;
.head-icon { width: 34rpx; height: 34rpx; }
.head-text { font-size: 28rpx; color: #111; font-weight: 600; }
/* rich-text 内容排版(图片适配) */
.rt {
font-size: 26rpx;
line-height: 42rpx;
color: #333;
white-space: normal;
word-break: break-word;
}
.rt p { margin: 8rpx 0; }
.rt img { max-width: 100%; height: auto !important; border-radius: 12rpx; }
/* 底部占位,避免被购买栏遮挡 */
.bottom-gap {
height: calc(env(safe-area-inset-bottom));
}
/* 覆盖:让 .group_2 居中其子元素,增强间距控制 */
.group_2 {
justify-content: center !important;
/* ===== 固定底部购买栏(含安全区) ===== */
.buy-bar {
position: sticky;
bottom: 0; left: 0; right: 0;
display: flex; align-items: center; justify-content: space-between;
gap: 20rpx;
padding: 12rpx 24rpx calc(12rpx + env(safe-area-inset-bottom));
background: #ffffff;
box-shadow: 0 -8rpx 20rpx rgba(0,0,0,0.06);
z-index: 10;
}
/* 新增:底部固定按钮栏 */
.section_8_fixed {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 999;
background-color: #ffffff;
/* 左侧咨询 */
.buy-left {
display: inline-flex; align-items: center; gap: 10rpx;
padding: 12rpx 16rpx;
border-radius: 16rpx;
background: #f0f2f5;
}
/* 禁止容器内元素换行 */
.no-wrap {
flex-wrap: nowrap !important;
.consult-icon { width: 36rpx; height: 36rpx; }
.consult-text { font-size: 24rpx; color: #333; }
/* 右侧按钮 */
.buy-btn {
flex: 1;
height: 72rpx;
border-radius: 9999rpx;
background: linear-gradient(90deg, #ff6a00, #ff8a2a);
box-shadow: 0 10rpx 24rpx rgba(255,106,0,0.26);
display: flex; align-items: center; justify-content: center;
}
/* 强制所有 text 不换行 */
.no-wrap text {
white-space: nowrap;
.buy-btn-text {
font-size: 28rpx;
color: #fff;
font-weight: 700;
letter-spacing: 1rpx;
}
.mx-15 {
margin-left: 15rpx;
margin-right: 15rpx;
}
/* 课程目录的点击状态 */
.active-title {
color: #ff8d1a; /* 点击后的颜色:橙色 */
/* ===== 小的间距工具(保留你原有语义) ===== */
.mt-9 { margin-top: 16rpx; }
.mt-37 { margin-top: 68rpx; }
.mt-1 { margin-top: 2rpx; }
/* 你之前的 class 若仍在别处使用,可继续保留或删去:
.image, .section, .group, .group_2, .group_3, .divider, .pos, .text_4, .section_2, .group_4, .image_2, .font, .text_3, .text_2, .text_5, .section_3, .section_4, .image_3, .text_7, .text-wrapper, .text_6
当前新版未依赖它们。 */
::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 753 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

View File

@ -1,3 +1,6 @@
import { baseUrl, globalImgUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
// pages/course/courseList/courseList.js
Page({
@ -5,8 +8,11 @@ Page({
* 页面的初始数据
*/
data: {
items:[null,null,null,null,null,null,null,null,null],
courseList:[], // 课程列表
courseType: '', // 课程类别
globalImgUrl,
tempCourseList: [],
searchKeyword: ''
},
// 跳转课程详情页面
@ -19,14 +25,64 @@ Page({
})
},
onSearchInput(e) {
const keyword = (e.detail.value || '').trim();
this.setData({ searchKeyword: keyword });
},
// 键盘“搜索/回车”触发:立即搜索
onSearch() {
const { tempCourseList } = this.data
const keyword = (this.data.searchKeyword || '').trim();
if (!keyword) {
this.setData({courseList: tempCourseList})
return;
}
// 模糊匹配 name
const filtered = this.data.courseList.filter(item => item.name.includes(keyword)
);
this.setData({ courseList: filtered });
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// console.log('option--->',options);
// 接收路由参数 type 作为搜索关键字
const courseType = options.type || '';
this.setData({ courseType }, () => {
this.fetchCourseList();
});
},
// 从后端拉取课程列表
fetchCourseList() {
wx.request({
url: baseUrl + '/course/query/type',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: {
templateString: this.data.courseType
},
success: res => {
console.log('课程列表',res.data.data);
if (res.data.code === 1) {
this.setData({
courseType: options.type
})
courseList: res.data.data,
tempCourseList: res.data.data
});
} else {
notLogin(res.data.message)
}
},
fail: err => {
console.error('request failed', err);
wx.showToast({
icon: 'none',
title: '网络请求失败',
});
}
});
},
/**

View File

@ -1,35 +1,38 @@
<!--pages/course/courseList/courseList.wxml-->
<view class="flex-col page">
<text class="self-center text">{{ courseType }}</text>
<image
class="shrink-0 self-start image image_2"
src="./image/line.png"
<!-- pages/course/searchCourses/searchCourses.wxml -->
<view class="page">
<!-- 顶部搜索条(固定) -->
<view class="search-bar" hover-class="hover">
<image class="search-icon" src="./image/sousuo.png" mode="aspectFit"/>
<input
class="search-input"
placeholder="搜索更多好课"
placeholder-class="search-ph"
bindinput="onSearchInput"
confirm-type="search"
bindconfirm="onSearch"
/>
<image
class="shrink-0 self-end image image_3"
src="./image/line.png"
/>
<view class="flex-col self-stretch list">
<view
class="flex-col justify-start list-item"
wx:for="{{items}}"
wx:for-item="item"
wx:for-index="index"
wx:key="index"
>
<view class="flex-row items-center relative group" bind:tap="gotoCourseDetail" data-id="{{ '1' }}">
<image
class="shrink-0 image_4"
src="https://ide.code.fun/api/image?token=6858ee4b4ae84d0012334127&name=9c2a22f14e2bd768cbd40d939693e4a8.png"
/>
<view class="flex-col flex-1 ml-12">
<text class="font">区块链和加密数字货币(随报随学认证班)</text>
<view class="flex-row justify-between items-baseline mt-17">
<text class="font_2">券后99元起</text>
<text class="font_3">18523人学习</text>
</view>
</view>
<!-- 搜索结果(独立滚动 & 隐藏滚动条) -->
<scroll-view scroll-y class="list no-scrollbar">
<block wx:for="{{courseList}}" wx:for-item="item" wx:key="item.id">
<view class="course-card" bindtap="gotoCourseDetail" data-id="{{item.id}}" hover-class="hover">
<image class="cover" src="{{ globalImgUrl + item.image }}" mode="aspectFill" lazy-load="true"/>
<view class="info">
<text class="title">{{item.name}}</text>
<view class="meta">
<text class="price-pill">券后{{item.discountPrice}}元起</text>
<text class="people">{{item.orderCount}}人学习</text>
</view>
</view>
</view>
</block>
<!-- 空状态(可选) -->
<view wx:if="{{!courseList || courseList.length === 0}}" class="empty">
<image class="empty-icon" src="/static/empty.png" mode="aspectFit"/>
<text class="empty-text">没找到相关课程,换个关键词试试~</text>
</view>
</scroll-view>
</view>

View File

@ -1,63 +1,131 @@
/* pages/course/courseList/courseList.wxss */
.mt-17 {
margin-top: 31.88rpx;
}
/* pages/course/searchCourses/searchCourses.wxss */
/* ===== 页面骨架:整页固定,列表单独滚动 ===== */
.page {
/* padding: 38.53rpx 0 ; */
background-color: #ffffff;
height: 100%;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100vh;
display: flex;
flex-direction: column;
background: #ffffff;
overflow: hidden; /* 禁止整页滚动 */
box-sizing: border-box;
font-family: SourceHanSansCN, PingFang SC, Microsoft YaHei, system-ui, -apple-system, sans-serif;
}
.text {
color: #000000;
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.64rpx;
::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}
.image {
width: 255rpx;
height: 1.88rpx;
/* 轻触反馈 */
.hover { opacity: .86; transition: opacity .18s ease; }
/* ===== 顶部搜索条(固定) ===== */
.search-bar {
padding: 24rpx 28rpx;
box-sizing: border-box;
display: flex;
align-items: center;
gap: 16rpx;
background: #fff;
}
.image_2 {
margin-left: 40.78rpx;
margin-top: -14.7rpx;
}
.image_3 {
margin-right: 37.97rpx;
.search-icon { width: 36rpx; height: 36rpx; opacity: .9; }
/* 胶囊输入框 */
.search-input {
flex: 1;
height: 72rpx;
padding: 0 26rpx;
border-radius: 9999rpx;
background: #f5f6f7;
font-size: 26rpx;
color: #111;
line-height: 72rpx;
box-shadow: inset 0 0 0 1rpx rgba(0,0,0,.04);
}
.search-ph { color: #a8a8a8; font-size: 26rpx; }
/* ===== 列表:占满剩余高度,单独滚动,隐藏滚动条 ===== */
.list {
padding-top: 20.21rpx;
flex: 1;
padding: 0 24rpx 28rpx;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
background: #fff;
}
.list-item {
height: 178.13rpx;
.no-scrollbar::-webkit-scrollbar { display: none; width: 0; height: 0; background: transparent; }
.no-scrollbar { scrollbar-width: none; }
/* ===== 课程卡片(左图右文) ===== */
.course-card {
display: flex;
gap: 22rpx;
padding: 20rpx;
margin-top: 20rpx;
background: #ffffff;
border-radius: 20rpx;
border: 1rpx solid #f1f1f1;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,.05);
}
.group {
margin: -18.24rpx 29.46rpx 0 35.63rpx;
padding: 57.19rpx 0 26.27rpx;
border-bottom: solid 1.88rpx #d6d6d6;
.cover {
width: 280rpx; /* 3:2 比例更舒服 */
height: 186rpx;
flex: 0 0 280rpx;
border-radius: 14rpx;
object-fit: cover;
}
.image_4 {
border-radius: 9.38rpx;
width: 208.13rpx;
height: 133.13rpx;
.info {
flex: 1;
min-width: 0; /* 防文字溢出 */
display: flex;
flex-direction: column;
justify-content: space-between;
}
.font {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 31.88rpx;
color: #000000;
.title {
font-size: 28rpx;
line-height: 40rpx;
color: #111;
font-weight: 600;
display: -webkit-box;
-webkit-line-clamp: 2; /* 两行省略 */
-webkit-box-orient: vertical;
overflow: hidden;
word-break: break-word;
}
.font_2 {
font-size: 26.25rpx;
font-family: AlibabaPuHuiTi;
line-height: 24.15rpx;
color: #ff5733;
.meta {
margin-top: 12rpx;
display: flex;
align-items: baseline;
justify-content: space-between;
}
.font_3 {
font-size: 22.5rpx;
font-family: AlibabaPuHuiTi;
line-height: 20.34rpx;
color: #a6a6a6;
.price-pill {
padding: 6rpx 14rpx;
font-size: 24rpx;
color: #fff;
border-radius: 9999rpx;
background: linear-gradient(90deg, #ff6a00, #ff8a2a);
box-shadow: 0 6rpx 16rpx rgba(255,106,0,.22);
white-space: nowrap;
}
.people {
font-size: 22rpx;
color: #9aa0a6;
white-space: nowrap;
}
/* ===== 空状态 ===== */
.empty {
padding: 120rpx 0 80rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 18rpx;
color: #9aa0a6;
}
.empty-icon { width: 240rpx; height: 240rpx; opacity: .7; }
.empty-text { font-size: 24rpx; line-height: 34rpx; }
/* ===== 兼容你项目里可能已有的工具类(可留可删) ===== */
.ml-3 { margin-left: 6rpx; }
.mt-17 { margin-top: 12rpx; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

View File

@ -1,88 +1,242 @@
import { baseUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
// pages/course/courseOrderList/courseOrderList.js
Page({
/**
* 页面的初始数据
*/
data: {
items: [null, null, null],
countDown: 30 * 60 , // 初始倒计时
countDownStr: '' // 用于在视图中渲染的倒计时文本
orderList: [], // 后端返回的订单列表
hasModalShown: false, // 本次停留页面只弹一次
isMaskVisible: false
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.startCountDown();
// —— 内部状态(不放 data避免多余 setData
_timer: null,
_isActive: false, // 页面是否处于“可见/激活”状态
_justEnteredAt: 0, // 进入页面时刻(可按需使用)
onLoad() {
this._isActive = true;
this._justEnteredAt = Date.now();
this.fetchOrders();
},
onShow() {
this._isActive = true;
this.fetchOrders(); // 如不想重复拉取可注释
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
clearInterval(this.intervalId);
this._isActive = false;
this._clearTimer();
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
clearInterval(this.intervalId);
this._isActive = false;
this._clearTimer();
},
/**
* 启动倒计时
*/
startCountDown() {
this.updateCountDownStr();
this.intervalId = setInterval(() => {
let cd = this.data.countDown;
if (cd <= 1) {
clearInterval(this.intervalId);
this.setData({
countDown: 0,
countDownStr: '00分00秒'
onPullDownRefresh() {
this.fetchOrders(); // stopPullDownRefresh 在 complete 里
},
// ========= 工具函数 =========
_clearTimer() {
if (this._timer) {
clearInterval(this._timer);
this._timer = null;
}
},
_pad2(n) {
return String(n).padStart(2, '0');
},
_fmtCountDownStr(totalSec) {
const sec = Math.max(0, totalSec | 0);
const m = Math.floor(sec / 60);
const s = sec % 60;
return `${this._pad2(m)}${this._pad2(s)}`;
},
// ========= 拉单 =========
fetchOrders() {
wx.request({
url: baseUrl + '/courseOrder/query/list',
method: 'POST',
header: { Authorization: wx.getStorageSync('token') },
success: res => {
if (res.data.code === 1) {
const now = Date.now();
const list = (res.data.data || []).map(it => {
// 解析时间iOS 兼容 + NaN 兜底)
const ts = new Date(String(it.createTime).replace(/-/g, '/')).getTime();
const createMs = Number.isFinite(ts) ? ts : now;
// 统一按 15 分钟有效期(若后端返回 expireTime建议直接用
const ttlMs = 15 * 60 * 1000;
let diff = Math.floor((createMs + ttlMs - now) / 1000);
diff = Math.max(0, diff);
if (it.orderStatus === '待支付') {
it.countDown = diff;
it.countDownStr = this._fmtCountDownStr(diff);
it._expiredNotified = false; // 每单的本地防重复标记
// 初始化阶段如果已经超时diff=0静默转关闭不弹窗
if (diff === 0) {
it.orderStatus = '交易关闭';
it.countDownStr = '';
}
} else {
it.countDown = 0;
it.countDownStr = '';
}
return it;
});
// 渲染 + 启动定时器
this.setData({ orderList: list }, () => this._startTimer());
} else {
notLogin(res.data.message);
}
},
fail: () => {
wx.showToast({ title: '网络错误', icon: 'none' });
},
complete: () => {
wx.stopPullDownRefresh();
}
});
},
// ========= 定时器刷新 =========
_startTimer() {
this._clearTimer();
// 如果已经没有“待支付”的订单,就不启动定时器
const hasPending = this.data.orderList.some(o => o.orderStatus === '待支付' && o.countDown > 0);
if (!hasPending) return;
this._timer = setInterval(() => {
// 不在激活页时不做任何 UI 相关动作(同时兜底不弹窗)
if (!this._isActive) return;
let needRerender = false;
const updated = this.data.orderList.map(item => {
if (item.orderStatus === '待支付' && item.countDown > 0) {
const next = item.countDown - 1;
item.countDown = next;
item.countDownStr = this._fmtCountDownStr(next);
needRerender = true;
if (next <= 0) {
item.orderStatus = '交易关闭';
item.countDownStr = '';
// —— 仅在“当前页面可见”时弹一次,并且每单只弹一次;本页全局也只弹一次
if (this._isActive && !item._expiredNotified && !this.data.hasModalShown) {
item._expiredNotified = true;
wx.showModal({
title: '提示',
content: '订单超时未支付,已关闭',
showCancel: false
});
this.setData({ hasModalShown: true });
}
}
}
return item;
});
if (needRerender) {
this.setData({ orderList: updated }, () => {
// 如果已经没有可继续倒计时的订单,关掉定时器
const stillPending = this.data.orderList.some(o => o.orderStatus === '待支付' && o.countDown > 0);
if (!stillPending) this._clearTimer();
});
} else {
cd--;
this.setData({ countDown: cd });
this.updateCountDownStr();
// 没有需要更新的也关掉
this._clearTimer();
}
}, 1000);
},
/**
* 更新倒计时显示字符串
*/
updateCountDownStr() {
const minutes = Math.floor(this.data.countDown / 60);
const seconds = this.data.countDown % 60;
const str = `${minutes}${seconds < 10 ? '0' + seconds : seconds}`;
this.setData({ countDownStr: str });
// ========= 支付相关 =========
showIsPayModal(e) {
const orderId = e.currentTarget.dataset.orderId;
wx.showModal({
title: '确认支付',
content: '是否立即支付该订单?',
cancelText: '取消',
confirmText: '去支付',
success: (res) => {
if (res.confirm) {
this.payOrder(orderId);
} else if (res.cancel) {
this.setData({ isMaskVisible: false });
}
},
fail: () => {
wx.hideLoading();
wx.showToast({ title: '网络错误', icon: 'none' });
}
});
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {}
payOrder(orderId) {
this.setData({ isMaskVisible: true });
wx.showLoading({ title: '支付中...' });
wx.request({
url: baseUrl + '/courseOrder/payment',
method: 'POST',
header: { Authorization: wx.getStorageSync('token') },
data: { id: orderId }, // 与后端约定:支付接口传 id若传 orderId 则改键名
success: res => {
wx.hideLoading();
if (res.data.code === 1) {
wx.redirectTo({
url: `/pages/course/orderDetail/orderDetail?id=${orderId}`,
complete: () => {
this.setData({ isMaskVisible: false });
}
});
} else {
this.setData({ isMaskVisible: false });
wx.showToast({ title: res.data.message || '支付失败', icon: 'none' });
}
},
fail: () => {
wx.hideLoading();
this.setData({ isMaskVisible: false });
wx.showToast({ title: '网络错误,支付失败', icon: 'none' });
}
});
},
// ========= 跳转 & 取消 =========
gotoOrderDetail(e) {
const orderId = e.currentTarget.dataset.id;
wx.navigateTo({
url: `/pages/course/orderDetail/orderDetail?id=${orderId}`,
});
},
cancelOrder(e) {
const id = e.currentTarget.dataset.id;
wx.showModal({
title: '取消订单',
content: '是否要取消该订单?',
success: res => {
if (res.confirm) {
wx.request({
url: baseUrl + "/courseOrder/cancel",
method: 'POST',
header: { Authorization: wx.getStorageSync('token') },
data: { id }, // 如果后端需要 { orderId: id },改这里的键名即可
success: r => {
if (r.data && r.data.code !== 1) {
wx.showToast({ title: r.data.message || '取消失败', icon: 'none' });
}
this.fetchOrders();
},
fail: () => wx.showToast({ title: '网络错误', icon: 'none' })
});
}
}
});
}
});

View File

@ -1,3 +1,4 @@
{
"usingComponents": {}
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -1,25 +1,55 @@
<!-- pages/course/courseOrderList/courseOrderList.wxml -->
<view class="flex-col justify-start page">
<view class="flex-col group_1">
<view class="flex-col list-item mt-17" wx:for="{{items}}" wx:for-item="item" wx:for-index="index" wx:key="index">
<view class="flex-row self-stretch group">
<text class="font text">订单号202506191307440406460485418</text>
<text class="font_2 ml-37">待支付</text>
</view>
<text class="self-stretch font_3 text_2">区块链和加密数字货币(随报随学认证班)(随报随学认证班)</text>
<text class="self-end font_4 text_3">¥999.00</text>
<text class="self-end font_5 text_4">请在 {{countDownStr}} 内完成支付</text>
<view class="flex-row justify-between items-center self-stretch group_2">
<text class="font_6 text_5">2025-06-17 13:00:33</text>
<view class="flex-row">
<view class="flex-col justify-start items-center text-wrapper">
<text class="font_7">取消订单</text>
</view>
<view class="flex-col justify-start items-center text-wrapper_2 ml-11">
<text class="font_8">支付</text>
<view class="page">
<!-- 列表滚动区 -->
<scroll-view scroll-y class="content no-scrollbar">
<!-- 空状态(可选) -->
<view wx:if="{{ !orderList || orderList.length === 0 }}" class="empty">
<image class="empty-img" src="./image/empty.png" mode="aspectFit" />
<text class="empty-text">暂无订单</text>
</view>
<!-- 订单卡片列表 -->
<view wx:for="{{ orderList }}"
wx:for-item="item"
wx:for-index="index"
wx:key="id"
class="card order-item"
bind:tap="gotoOrderDetail"
data-id="{{ item.id }}">
<!-- 顶部:订单号 + 状态徽标 -->
<view class="topline">
<text class="order-no">订单号:{{ item.orderNumber }}</text>
<view class="status-badge {{ item.orderStatus === '待支付' ? 'status-pending' : (item.orderStatus === '已支付' || item.orderStatus === '交易成功' ? 'status-success' : 'status-default') }}">
<text class="status-text">{{ item.orderStatus }}</text>
</view>
</view>
<!-- 课程名称 -->
<text class="course-name ellipsis-2">{{ item.name }}</text>
<!-- 价格 + 倒计时(仅待支付显示) -->
<view class="price-line">
<text class="amount">¥{{ item.totalAmount }}</text>
<view wx:if="{{ item.orderStatus === '待支付' }}" class="countdown-pill">
<text class="countdown-text">请在 {{ item.countDownStr }} 内完成支付</text>
</view>
</view>
<!-- 底部:下单时间 + 操作按钮(仅待支付显示) -->
<view class="bottomline">
<text class="ctime">{{ item.createTime }}</text>
<view class="actions" wx:if="{{ item.orderStatus === '待支付' }}">
<view class="btn btn-ghost" catch:tap="cancelOrder" data-id="{{ item.id }}">取消订单</view>
<view class="btn btn-primary" catch:tap="showIsPayModal" data-order-id="{{ item.id }}">支付</view>
</view>
</view>
</view>
</scroll-view>
<!-- 遮罩 -->
<view wx:if="{{ isMaskVisible }}" class="page-mask"></view>
</view>

View File

@ -1,125 +1,169 @@
/* pages/course/courseOrderList/courseOrderList.wxss */
.mt-17 {
margin-top: 31.88rpx;
}
.ml-37 {
margin-left: 69.38rpx;
}
.ml-11 {
margin-left: 20.63rpx;
}
/* ===== 页面与滚动 ===== */
.page {
padding: 26.25rpx 0 350.63rpx;
background-color: #f8f8f8;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
background: #f7f7f7;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.group_1 {
margin-left: 20.63rpx;
margin-right: 18.77rpx;
.content {
flex: 1;
padding: 24rpx 24rpx; /* 统一外边距 */
box-sizing: border-box;
}
.list-item {
padding-left: 22.5rpx;
padding-right: 3.51rpx;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
background-color: #ffffff;
border-radius: 9.66rpx;
.no-scrollbar::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
.list-item:first-child {
margin-top: 0;
/* 遮罩 */
.page-mask {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.35);
z-index: 9999;
}
.group {
padding: 32.51rpx 0 25.82rpx;
border-bottom: solid 1.88rpx #e3e3e3;
/* ===== 空状态 ===== */
.empty {
padding: 100rpx 0;
display: flex;
flex-direction: column;
align-items: center;
color: #999999;
}
.font {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.17rpx;
color: #696969;
.empty-img { width: 280rpx; height: 280rpx; margin-bottom: 20rpx; }
.empty-text { font-size: 28rpx; }
/* ===== 卡片通用 ===== */
.card {
background: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.05);
}
.text {
line-height: 24.02rpx;
.card + .card { margin-top: 20rpx; }
/* ===== 列表项排版 ===== */
.order-item {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.font_2 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.17rpx;
color: #f84947;
/* 顶部行:订单号 + 状态 */
.topline {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
}
.font_3 {
.order-no {
font-size: 26rpx;
color: #666666;
}
.status-badge {
height: 40rpx;
padding: 0 18rpx;
border-radius: 999rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.status-text {
font-size: 24rpx;
font-weight: 600;
}
.status-pending { background: #fff6e6; color: #ff8d1a; } /* 待支付:主题橙 */
.status-success { background: #e9fbef; color: #12b05b; } /* 已/成功:绿色 */
.status-default { background: #f0f0f0; color: #666666; } /* 其他:灰 */
/* 课程名称 */
.course-name {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 35.63rpx;
color: #000000;
font-weight: 600;
color: #1f1f1f;
line-height: 44rpx;
}
.text_2 {
margin-top: 25.69rpx;
.ellipsis-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.font_4 {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 24.17rpx;
color: #3d3d3d;
/* 价格 + 倒计时 */
.price-line {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
}
.text_3 {
margin-top: 58.09rpx;
line-height: 22.76rpx;
margin-right: 50rpx; /* 向左移动:增加右侧间距 */
.amount {
font-size: 34rpx;
color: #ff5a1a; /* 与你的小程序橙色系统一 */
font-weight: 700;
}
.font_5 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 26.32rpx;
color: #f84947;
.countdown-pill {
background: #fff4f2;
border: 1rpx solid #ffd6cc;
padding: 0 16rpx;
height: 40rpx;
border-radius: 999rpx;
display: inline-flex;
align-items: center;
}
.text_4 {
margin-right: 7.13rpx;
margin-top: 34.91rpx;
font-size: 28.13rpx;
.countdown-text {
font-size: 22rpx;
color: #ff5a1a;
}
.group_2 {
margin-right: 20.87rpx;
margin-top: 30.30rpx;
padding: 15.94rpx 0 17.81rpx;
border-top: solid 1.88rpx #e3e3e3;
/* 底部行:时间 + 操作区 */
.bottomline {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
padding-top: 8rpx;
border-top: 1rpx dashed #f0f0f0;
}
.font_6 {
font-size: 22.5rpx;
font-family: SourceHanSansCN;
line-height: 26.25rpx;
color: #a1a1a1;
.ctime {
font-size: 24rpx;
color: #888888;
}
.text_5 {
width: 206.25rpx;
.actions {
display: flex;
align-items: center;
gap: 16rpx;
}
.text-wrapper {
padding: 10.8rpx 0 8.16rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
width: 142.5rpx;
height: 46.88rpx;
border: solid 1.88rpx #ff8d1a;
/* 按钮 */
.btn {
height: 64rpx;
min-width: 180rpx;
padding: 0 24rpx;
border-radius: 999rpx;
font-size: 26rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
}
.font_7 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.17rpx;
color: #ff8d1a;
.btn-ghost {
background: #ffffff;
color: #333333;
border: 2rpx solid #e6e6e6;
}
.text-wrapper_2 {
padding: 11.89rpx 0 8.94rpx;
background-color: #ff8d1a;
border-radius: 9.38rpx;
width: 140.63rpx;
height: 45rpx;
}
.font_8 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.17rpx;
.btn-primary {
background: linear-gradient(180deg, #ffa64a 0%, #ff8d1a 100%);
color: #ffffff;
box-shadow: 0 6rpx 14rpx rgba(255, 141, 26, 0.25);
}
/* ===== 迁移提示:以下旧的散装类可删除(如无外部依赖) ===== */
/* .mt-17, .ml-37, .ml-11, .group_1, .list-item, .group, .font*, .text* 等 */

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -1,3 +1,7 @@
import { baseUrl, globalImgUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
import { decodeBase64 } from "../../../utils/decodebase64";
// pages/course/createCourseOrder/createCourseOrder.js
Page({
@ -6,13 +10,169 @@ Page({
*/
data: {
courseId: 0, // 课程id
courseObj: '', // 课程对象
globalImgUrl, // 全局图片
isMaskVisible: false,
isNoticeVisible: true,
noticeHtml: '',
},
// 打开/关闭弹窗
openNotice() {
this.setData({ isNoticeVisible: true });
},
closeNotice() {
this.setData({ isNoticeVisible: false });
},
// 阻止冒泡/滚动穿透的空函数
noop() {},
// 创建订单方法
createOrder(e) {
const courseId = e.currentTarget.dataset.id;
createOrder() {
const { courseId } = this.data;
// 1. 显示遮罩,阻止二次点击
this.setData({ isMaskVisible: true });
wx.showLoading({ title: '正在创建订单...' });
let orderId ;
wx.request({
url: baseUrl + '/courseOrder/add',
method: 'POST',
data: {
courseId: courseId
},
header: {
Authorization :wx.getStorageSync('token'),
},
success : res => {
orderId = res.data.data
this.setData({ orderId })
wx.hideLoading();
if (res.data.code === 1) {
this.showIsPayModal(orderId)
} else {
// 下单失败,关闭遮罩
this.setData({ isMaskVisible: false });
wx.showModal({
title: '下单失败',
content: res.data.message || '下单失败',
showCancel: false,
confirmText: '知道了'
});
}
},
fail: () => {
wx.hideLoading();
this.setData({ isMaskVisible: false });
wx.showToast({ title: '网络错误,下单失败', icon: 'none' });
}
})
},
showIsPayModal(orderId) {
wx.showModal({
title: '下单成功',
content: '您确定要支付吗?',
cancelText: '取消',
confirmText: '确定',
success: (res) => {
if (res.confirm) {
this.payOrder(orderId);
} else if (res.cancel) {
wx.navigateTo({
url: `/pages/course/waitPayOrder/waitPayOrder?id=${courseId}`,
url: `/pages/course/orderDetail/orderDetail?id=${orderId}`,
success: res => {
// 先把遮罩关掉
this.setData({ isMaskVisible: false });
}
});
}
},
fail: () => {
wx.hideLoading();
wx.showToast({
title: '网络错误,下单失败',
icon: 'none'
});
}
});
},
payOrder(orderId) {
// 同样先显示遮罩
this.setData({ isMaskVisible: true });
wx.showLoading({ title: '支付中...'});
wx.request({
url: baseUrl + '/courseOrder/payment',
method: 'POST',
header: { Authorization: wx.getStorageSync('token') },
data: { id: orderId },
success: res => {
wx.hideLoading();
if (res.data.code === 1) {
// 支付成功,跳转详情页
wx.navigateTo({
url: `/pages/course/orderDetail/orderDetail?id=${orderId}`,
success: res => {
// 先把遮罩关掉
this.setData({ isMaskVisible: false });
}
});
} else {
this.setData({ isMaskVisible: false });
wx.showToast({ title: res.data.message || '支付失败', icon: 'none' });
}
},
fail: () => {
wx.hideLoading();
this.setData({ isMaskVisible: false });
wx.showToast({ title: '网络错误,支付失败', icon: 'none' });
}
});
},
// 获取课程详情
getCourseDetail() {
const cid = this.data.courseId;
wx.request({
url: baseUrl + '/course/detail/id',
method: 'POST',
data: {
id: cid
},
header: {
Authorization :wx.getStorageSync('token'),
},
success : res => {
console.log(res);
if (res.data.code === 1) {
this.setData({
courseObj: res.data.data,
})
} else {
notLogin(res.data.message)
}
},
fail: () => {
wx.showToast({ title: '网络错误', icon: 'none' });
}
})
},
getCourseDesc() {
wx.request({
url: baseUrl + '/userInfo/query/courseDesc',
method: 'POST',
success: res => {
console.log('====>购买须知', res.data)
if (res.data.code === 1) {
this.setData({noticeHtml: decodeBase64(res.data.data)})
} else {
notLogin(res.data.message)
}
},
fail: () => {
wx.showToast({ title: '网络错误', icon: 'none' });
}
})
},
@ -24,6 +184,8 @@ Page({
this.setData({
courseId: options.id,
})
this.getCourseDetail()
this.getCourseDesc()
},
/**

View File

@ -1,46 +1,77 @@
<!-- pages/course/createCourseOrder/createCourseOrder.wxml -->
<view class="flex-col page">
<view class="flex-col content">
<view class="flex-row items-center section">
<view class="page">
<!-- 可滚动内容区:为固定底部预留内边距,避免遮挡 -->
<scroll-view scroll-y class="content no-scrollbar">
<!-- 商品信息卡片 -->
<view class="card product">
<image
class="shrink-0 image"
src="https://ide.code.fun/api/image?token=6859f7a14ae84d0012334fa9&name=9c2a22f14e2bd768cbd40d939693e4a8.png"
class="cover"
src="{{ globalImgUrl + courseObj.image }}"
mode="aspectFill"
lazy-load="true"
/>
<view class="flex-col flex-1 ml-11">
<text class="self-start text">区块链和加密数字货币(随报随学认证班)(随报随学认证班)</text>
<view class="flex-row items-center self-stretch group mt-15">
<text class="text_2">¥999</text>
<view class="flex-col justify-start relative ml-1">
<text class="text_3">¥999</text>
<view class="divider pos"></view>
<view class="info">
<text class="title ellipsis-2">{{ courseObj.name }}</text>
<view class="price-line">
<text class="price-now">¥{{ courseObj.discountPrice }}</text>
<text class="price-origin">¥{{ courseObj.originPrice }}</text>
</view>
</view>
</view>
<!-- 商品价格行 -->
<view class="card row">
<text class="row-left">商品价格</text>
<text class="row-right accent">¥{{ courseObj.discountPrice }}</text>
</view>
<view class="flex-row justify-between items-center section_2 mt-14">
<text class="font">商品价格</text>
<text class="font text_4">¥999</text>
<!-- 支付方式 -->
<view class="card pay">
<view class="pay-left">
<image class="pay-icon" src="./image/wxpay.png" mode="aspectFit" />
<text class="pay-text">微信支付</text>
</view>
<view class="flex-row justify-between items-center section_3 mt-14">
<view class="flex-row items-center">
<image
class="shrink-0 image_2"
src="./image/wxpay.png"
/>
<text class="font ml-12">微信支付</text>
</view>
<radio-group class="image_3">
<radio checked="true"></radio>
<radio-group class="pay-right" bindchange="onPayMethodChange">
<radio value="wxpay" checked></radio>
</radio-group>
</view>
</view>
<!-- 固定在底部的区域 -->
</scroll-view>
<!-- 固定底部结算栏 -->
<view class="footer">
<view class="flex-row justify-between items-center section_4">
<text class="font text_5">应付¥999</text>
<view class="flex-col justify-center items-center text-wrapper" bind:tap="createOrder" data-id="{{ '1' }}">
<text class="font text_6">立即支付</text>
<view class="footer-inner">
<text class="to-pay">应付 <text class="to-pay-amount">¥{{ courseObj.discountPrice }}</text></text>
<view class="btn-pay" bindtap="createOrder">立即支付</view>
</view>
</view>
<!-- 遮罩 -->
<view wx:if="{{isMaskVisible}}" class="page-mask"></view>
</view>
<!-- ===== 购买须知弹窗(富文本) ===== -->
<view wx:if="{{isNoticeVisible}}" class="modal-mask" catchtouchmove="noop">
<view class="modal" catchtap="noop">
<view class="modal-title">课程购买须知</view>
<!-- 富文本内容:支持 p/h1-h6/strong/em/ul/ol/a 等常见标签 -->
<scroll-view scroll-y class="modal-body">
<rich-text nodes="{{noticeHtml}}"></rich-text>
</scroll-view>
<view class="modal-actions">
<button class="btn-primary" bindtap="closeNotice">我知道了</button>
</view>
</view>
</view>
<!-- 右上角购买须知按钮 -->
<view class="notice-icon" bindtap="openNotice">
<image src="./image/info.png" mode="aspectFit" class="notice-icon-img" />
<text class="notice-icon-text">购买须知</text>
</view>

View File

@ -1,118 +1,320 @@
.ml-11 {
margin-left: 20.63rpx;
}
.mt-15 {
margin-top: 28.13rpx;
}
.ml-1 {
margin-left: 1.88rpx;
}
/* 页面与滚动容器 */
.page {
background-color: #f7f7f7;
width: 100%;
height: 100vh;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
overflow-y: auto;
}
.section {
padding: 20.63rpx 22.5rpx 27.58rpx;
background-color: #ffffff;
border-radius: 3.94rpx;
}
.image {
border-radius: 9.38rpx;
width: 208.13rpx;
height: 133.13rpx;
}
.text {
color: #000000;
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 35.63rpx;
width: 429.38rpx;
}
.group {
padding: 0 4.29rpx;
}
.text_2 {
color: #f84947;
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 22.76rpx;
}
.text_3 {
color: #8c8c8c;
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 19.93rpx;
}
.divider {
background-color: #8c8c8c;
width: 69.56rpx;
height: 1.88rpx;
}
.pos {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
.section_2 {
padding: 48.69rpx 29.21rpx 43.35rpx 44.96rpx;
background-color: #ffffff;
}
.font {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.96rpx;
color: #323232;
}
.text_4 {
line-height: 22.91rpx;
}
.section_3 {
padding: 39.38rpx 46.88rpx 897.38rpx 48.75rpx;
background-color: #ffffff;
}
.image_2 {
width: 52.5rpx;
height: 52.5rpx;
}
.image_3 {
width: 41.25rpx;
height: 41.25rpx;
}
.section_4 {
padding: 16.88rpx 24.38rpx 16.88rpx 31.09rpx;
background-color: #ffffff;
}
.text_5 {
color: #000000;
line-height: 28.05rpx;
}
.text-wrapper {
padding: 14.07rpx 0 19.07rpx;
background-color: #ff8d1a;
border-radius: 75rpx;
width: 268.13rpx;
height: 71.25rpx;
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
padding: 24rpx 24rpx 160rpx; /* bottom 预留给固定底部栏 */
box-sizing: border-box;
}
.text_6 {
color: #ffffff;
line-height: 28.11rpx;
.no-scrollbar::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
/* 通用卡片 */
.card {
background-color: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.04);
}
.card + .card {
margin-top: 20rpx;
}
/* 商品信息卡片 */
.product {
display: flex;
flex-direction: row;
align-items: stretch;
gap: 20rpx;
}
.cover {
width: 260rpx;
height: 180rpx;
border-radius: 12rpx;
flex-shrink: 0;
background: #f2f2f2;
}
.info {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
min-width: 0; /* 使多行省略生效 */
}
.title {
font-size: 32rpx;
font-weight: 600;
color: #1f1f1f;
line-height: 48rpx;
}
.ellipsis-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.price-line {
display: flex;
align-items: baseline;
gap: 12rpx;
margin-top: 8rpx;
}
.price-now {
font-size: 36rpx;
font-weight: 700;
color: #ff5a1a; /* 与主题橙统一 */
line-height: 1;
}
.price-origin {
font-size: 26rpx;
color: #9f9f9f;
text-decoration: line-through; /* 用样式处理中划线 */
}
/* 通用行(键值对) */
.row {
display: flex;
align-items: center;
justify-content: space-between;
}
.row-left {
font-size: 30rpx;
color: #4a4a4a;
}
.row-right {
font-size: 30rpx;
color: #1f1f1f;
}
.accent {
color: #ff5a1a;
font-weight: 600;
}
/* 支付方式 */
.pay {
display: flex;
align-items: center;
justify-content: space-between;
}
.pay-left {
display: flex;
align-items: center;
gap: 16rpx;
}
.pay-icon {
width: 56rpx;
height: 56rpx;
border-radius: 8rpx;
}
.pay-text {
font-size: 30rpx;
color: #333333;
}
.pay-right {
display: flex;
align-items: center;
}
/* 固定底部 */
.footer {
margin-top: auto;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
right: 0;
bottom: 0;
background: #ffffff;
box-shadow: 0 -6rpx 20rpx rgba(0,0,0,0.06);
padding-bottom: env(safe-area-inset-bottom);
/* 兼容旧版 iOS */
padding-bottom: constant(safe-area-inset-bottom);
}
.footer-inner {
height: 120rpx;
display: flex;
align-items: center;
justify-content: space-between;
gap: 24rpx;
padding: 0 24rpx;
box-sizing: border-box;
}
.to-pay {
font-size: 28rpx;
color: #666666;
}
.to-pay-amount {
font-size: 36rpx;
color: #ff5a1a;
font-weight: 700;
margin-left: 8rpx;
}
/* 支付按钮:使用 view自定义橙色主题 */
.btn-pay {
min-width: 260rpx;
height: 88rpx;
border-radius: 999rpx;
background: linear-gradient(180deg, #ffa64a 0%, #ff8d1a 100%);
color: #ffffff;
font-size: 30rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 6rpx 14rpx rgba(255, 141, 26, 0.35);
active-opacity: 0.85;
}
/* 遮罩层 */
.page-mask {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.35);
z-index: 9999;
}
/* 旧样式中可能用到的零散类,若无依赖可移除 */
.ml-11 { margin-left: 20rpx; }
.mt-15 { margin-top: 28rpx; }
.ml-1 { margin-left: 2rpx; }
/* 入口小字 */
.notice-entry {
margin-right: 16rpx;
font-size: 24rpx;
color: #8a8a8a;
text-decoration: underline;
}
/* 弹窗遮罩 */
.modal-mask {
position: fixed;
z-index: 999; /* 确保在你的 .footer 与其他遮罩之上 */
inset: 0;
background: rgba(0,0,0,0.45);
display: flex;
justify-content: center;
align-items: center;
padding: 40rpx;
}
/* 弹窗容器 */
.modal {
width: 86%;
max-width: 640rpx;
max-height: 70vh;
background: #fff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 12rpx 40rpx rgba(0,0,0,0.18);
}
/* 标题 */
.modal-title {
padding: 28rpx 32rpx 12rpx;
font-size: 32rpx;
font-weight: 600;
color: #222;
}
/* 内容区滚动 */
.modal-body {
max-height: 48vh;
padding: 8rpx 32rpx 24rpx;
}
rich-text {
padding-bottom: 32rpx;
}
/* 富文本默认样式优化 */
.modal-body rich-text {
display: block;
font-size: 26rpx;
line-height: 1.75;
color: #444;
}
.modal-body h3 { font-size: 28rpx; margin: 18rpx 0 8rpx; color: #222; }
.modal-body p { margin: 10rpx 0; }
.modal-body ul, .modal-body ol { margin: 10rpx 0 10rpx 28rpx; }
.modal-body a { color: #1677ff; word-break: break-all; }
/* 底部按钮区 */
.modal-actions {
padding: 20rpx 24rpx 28rpx;
}
.btn-primary {
width: 100%;
height: 84rpx;
line-height: 84rpx;
text-align: center;
border-radius: 16rpx;
background: #ff8a00; /* 你的主色调(可换成项目变量) */
color: #fff;
font-size: 30rpx;
font-weight: 600;
}
.btn-primary:active {
opacity: 0.85;
}
.notice-icon {
position: absolute;
top: 20rpx;
right: 20rpx;
z-index: 10;
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.92);
border-radius: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
padding: 6rpx 14rpx;
}
.notice-icon-img {
width: 34rpx;
height: 34rpx;
margin-right: 8rpx;
}
.notice-icon-text {
font-size: 24rpx;
color: #333;
}
.notice-icon:active {
opacity: 0.85;
}
::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -1,11 +1,14 @@
import { baseUrl } from "../../../request";
const { globalImgUrl } = require("../../../request")
const { notLogin } = require('../../../utils/util')
// pages/course/homepage/homepage.js
Page({
data: {
// 初始时置空,待接口返回后再渲染
courseList: []
courseList: [],
bannerList: [],
globalImgUrl
},
// 跳转课程列表页
@ -31,10 +34,9 @@ Page({
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// 获取热门课程
getCourseList() {
// 请求后端接口
wx.request({
url: baseUrl + '/course/query/hot', // ← 替换为真实接口
@ -44,15 +46,13 @@ Page({
},
success: (res) => {
if (res.data.code === 1) {
console.log('课程列表---->',res.data.data);
// 将后端的 data 数组绑定到 items
this.setData({
courseList: res.data.data
});
} else {
wx.showToast({
title: res.data.message || '获取课程数据失败',
icon: 'none'
});
notLogin(res.data.message)
}
},
fail: () => {
@ -64,6 +64,40 @@ Page({
});
},
getBannerList() {
const token = wx.getStorageSync('token')
wx.request({
url: baseUrl + '/banner/mini/list',
method: 'GET',
header: {
'Authorization': token
},
success: res => {
if (res.data.code === 1) {
this.setData({
bannerList: res.data.data
});
} else {
notLogin(res.data.message)
}
},
fail: () => {
wx.showToast({
title: '网络异常,请稍后重试',
icon: 'none'
});
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad() {
this.getBannerList()
this.getCourseList()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
@ -96,7 +130,10 @@ Page({
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
this.getBannerList()
this.getCourseList()
// 停止下拉刷新动画
wx.stopPullDownRefresh();
},
/**

View File

@ -1,3 +1,4 @@
{
"usingComponents": {}
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -1,62 +1,64 @@
<view class="flex-col page">
<view class="flex-col self-stretch group">
<view class="flex-row justify-center items-center section" bind:tap="gotoSearch">
<image
class="image"
src="./image/sousuo.png"
/>
<text class="text ml-3">搜索更多好课</text>
<view class="page">
<!-- 顶部内容:搜索 + 轮播 -->
<view class="top">
<view class="search-bar" bindtap="gotoSearch" hover-class="hover">
<image class="search-icon" src="./image/sousuo.png" mode="aspectFit"/>
<text class="search-text">搜索更多好课</text>
</view>
<swiper class="swiper" autoplay="true" circular="true"></swiper>
<swiper class="swiper" autoplay="true" interval="3000" circular="true" indicator-dots="true" indicator-active-color="#ff6a00">
<block wx:for="{{bannerList}}" wx:for-item="img" wx:key="index">
<swiper-item>
<image src="{{globalImgUrl + img}}" class="swiper-image" mode="aspectFill" lazy-load="true"/>
</swiper-item>
</block>
</swiper>
</view>
<view class="flex-row equal-division">
<view class="flex-col items-center group_2 group_1" bind:tap="gotoCourseList" data-type="{{ '考公考研' }}">
<image
class="image_3"
src="./image/kgky.png"
/>
<text class="font text_1 mt-12">考公考研</text>
<!-- 三分类 -->
<view class="category-row">
<view class="category-card" bindtap="gotoCourseList" data-type="考编" hover-class="hover">
<image class="category-icon" src="./image/考编.png" mode="aspectFit" lazy-load="true"/>
<text class="category-text">考编</text>
</view>
<view class="flex-col items-center group_2 group_3" bind:tap="gotoCourseList" data-type="{{ '自媒体' }}">
<image
class="image_3"
src="./image/zmt.png"
/>
<text class="font text_3 mt-12">自媒体</text>
<view class="category-card" bindtap="gotoCourseList" data-type="考公" hover-class="hover">
<image class="category-icon" src="./image/考公.png" mode="aspectFit" lazy-load="true"/>
<text class="category-text">考公</text>
</view>
<view class="flex-col items-center group_2 group_4" bind:tap="gotoCourseList" data-type="{{ '财经' }}">
<image
class="image_3"
src="./image/cj.png"
/>
<text class="font text_4 mt-12">财经</text>
<view class="category-card" bindtap="gotoCourseList" data-type="考证" hover-class="hover">
<image class="category-icon" src="./image/考证.png" mode="aspectFit" lazy-load="true"/>
<text class="category-text">考证</text>
</view>
</view>
<text class="self-start text_2">热门课程</text>
<view class="flex-col self-stretch list">
<!-- items 数组循环 -->
<view
class="flex-row relative group_5"
wx:for="{{courseList}}"
wx:for-item="item"
wx:for-index="index"
wx:key="item.id"
>
<view bind:tap="gotoCourseDetail" data-id="{{item.id}}">
<view class="list-divider pos_3"></view>
<!-- 绑定课程封面图 -->
<image class="image_4 pos" src="{{ globalImgUrl + item.image}}" />
<view class="flex-col group_6 pos_2">
<!-- 绑定课程名称 -->
<text class="font_2">{{item.name}}</text>
<view class="flex-row justify-between items-baseline mt-17">
<!-- 绑定卷后价格 -->
<text class="font_3">券后{{item.discountPrice}}元起</text>
<!-- 绑定下单/学习人数 -->
<text class="font_4">{{item.orderCount}}人学习</text>
<!-- 热门课程标题 -->
<view class="section-head">
<text class="section-title">热门课程</text>
</view>
<!-- 热门课程两列宫格 -->
<scroll-view scroll-y class="list no-scrollbar">
<view class="grid">
<block wx:for="{{courseList}}" wx:key="item.id" wx:for-item="item">
<view class="grid-item" bindtap="gotoCourseDetail" data-id="{{item.id}}" hover-class="hover">
<image class="grid-cover" src="{{ globalImgUrl + item.image }}" mode="aspectFill" lazy-load="true"/>
<view class="grid-info">
<text class="grid-title">{{item.name}}</text>
<view class="grid-meta">
<text class="grid-price">¥{{item.discountPrice}}</text>
<text class="grid-people">{{item.orderCount}}人学习</text>
</view>
</view>
</view>
</block>
</view>
<!-- 空状态 -->
<view wx:if="{{!courseList || courseList.length == 0}}" class="empty">
<image class="empty-icon" src="/static/empty.png" mode="aspectFit"/>
<text class="empty-text">暂无课程,去看看其他分类吧~</text>
</view>
</scroll-view>
</view>

View File

@ -1,137 +1,118 @@
.ml-3 {
margin-left: 5.63rpx;
}
.mt-17 {
margin-top: 31.88rpx;
}
.page {
padding: 0rpx 0 10.88rpx;
background-color: #ffffff;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
height: 100vh;
display: flex;
flex-direction: column;
background: #ffffff;
overflow: hidden;
font-family: SourceHanSansCN, PingFang SC, Microsoft YaHei, system-ui, -apple-system, sans-serif;
}
.group {
padding-left: 30rpx;
padding-right: 28.13rpx;
.hover { opacity: 0.8; transition: opacity .2s ease; }
::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}
.section {
padding: 11.25rpx 0;
background-color: #f2f2f2;
border-radius: 93.75rpx;
}
.image {
width: 35.63rpx;
height: 35.63rpx;
}
.text {
color: #a8a8a8;
font-size: 22.5rpx;
font-family: SourceHanSerifCN;
line-height: 20.83rpx;
}
.equal-division {
align-self: stretch;
margin: 21.88rpx 31.46rpx 0 29.48rpx;
}
.group_2 {
flex: 1 1 229.69rpx;
}
.group_1 {
padding: 13.56rpx 0 9.99rpx;
}
.image_3 {
width: 96rpx;
height: 96rpx;
}
.font {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.15rpx;
color: #000000;
}
.text_1 {
line-height: 24.26rpx;
}
.group_3 {
padding: 13.56rpx 0 10.09rpx;
}
.text_3 {
line-height: 24.23rpx;
}
.group_4 {
padding: 13.56rpx 0 10.13rpx;
}
.text_4 {
line-height: 24.13rpx;
}
.text_2 {
margin-left: 35.04rpx;
margin-top: 38.16rpx;
color: #000000;
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.75rpx;
}
.list {
margin-top: 9.56rpx;
}
.group_5 {
padding: 18.75rpx 29.46rpx 0 35.63rpx;
height: 180rpx;
}
.list-divider {
background-color: #d6d6d6;
height: 1.88rpx;
}
.pos_3 {
position: absolute;
left: 35.63rpx;
right: 33.81rpx;
top: 178.13rpx;
}
.image_4 {
border-radius: 9.38rpx;
width: 208.13rpx;
height: 133.13rpx;
}
.pos {
position: absolute;
left: 35.63rpx;
top: 50%;
transform: translateY(-50%);
}
.group_6 {
width: 453.49rpx;
}
.pos_2 {
position: absolute;
right: 29.46rpx;
top: 50%;
transform: translateY(-50%);
}
.font_2 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 31.88rpx;
color: #000000;
}
.font_3 {
font-size: 26.25rpx;
font-family: AlibabaPuHuiTi;
line-height: 24.15rpx;
color: #ff5733;
}
.font_4 {
font-size: 22.5rpx;
font-family: AlibabaPuHuiTi;
line-height: 20.34rpx;
color: #a6a6a6;
/* 顶部 */
.top { padding: 30rpx; }
.search-bar {
display: flex; align-items: center; gap: 14rpx;
padding: 18rpx 22rpx; border-radius: 9999rpx;
background: #f5f6f7;
}
.search-icon { width: 36rpx; height: 36rpx; }
.search-text { font-size: 26rpx; color: #a8a8a8; }
.swiper {
border-radius: 9.38rpx;
width: 691.88rpx;
height: 324.38rpx;
margin-top: 22.5rpx;
width: 100%; height: 324rpx; margin-top: 24rpx;
border-radius: 16rpx; overflow: hidden;
}
.swiper-image { width: 100%; height: 100%; }
/* 分类 */
.category-row {
display: flex; gap: 24rpx; padding: 0 30rpx; margin-top: 22rpx;
}
.category-card {
flex: 1; background: #fff; border-radius: 20rpx;
padding: 22rpx 0 18rpx;
display: flex; flex-direction: column; align-items: center; gap: 12rpx;
box-shadow: 0 6rpx 24rpx rgba(0,0,0,0.06);
}
.category-icon { width: 96rpx; height: 96rpx; }
.category-text { font-size: 26rpx; color: #111; }
/* 标题 */
.section-head { padding: 28rpx 30rpx 16rpx; }
.section-title { font-size: 30rpx; font-weight: 600; }
/* 列表(滚动) */
.list {
flex: 1;
padding: 0 30rpx;
-webkit-overflow-scrolling: touch;
overflow: auto;
}
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { scrollbar-width: none; }
/* 宫格布局 */
.grid {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 20rpx;
padding-bottom: 30rpx;
}
.grid-item {
width: 335rpx;
background: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.05);
display: flex;
flex-direction: column;
}
.grid-cover {
width: 100%; height: 200rpx;
object-fit: cover;
}
.grid-info {
padding: 14rpx;
display: flex;
flex-direction: column;
gap: 6rpx;
}
.grid-title {
font-size: 26rpx;
color: #111;
line-height: 36rpx;
min-height: 72rpx;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.grid-meta {
display: flex; justify-content: space-between; align-items: center;
}
.grid-price {
font-size: 26rpx;
font-weight: 600;
color: #ff6a00;
}
.grid-people {
font-size: 22rpx;
color: #9aa0a6;
}
/* 空状态 */
.empty {
padding: 80rpx 0 60rpx;
display: flex; flex-direction: column; align-items: center; gap: 18rpx;
color: #9aa0a6;
}
.empty-icon { width: 220rpx; height: 220rpx; opacity: 0.7; }
.empty-text { font-size: 24rpx; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,239 @@
import { baseUrl, globalImgUrl } from "../../../request";
Page({
data: {
countdown: "",
orderId: 0,
orderObj: {}, // 订单详情对象
_secondsRemaining: 0, // 内部倒计时秒数
_hasShownTimeout: false, // 是否已弹过“超时未支付”弹窗(本次页面停留期内)
globalImgUrl,
isMaskVisible: false,
_isActive: false // 页面是否处于可见状态
},
// —— 非 data 状态,避免无谓 setData
_timer: null,
onLoad(options) {
this.setData({ orderId: options.id || 0 });
this.getOrderDetail();
},
onShow() {
this.setData({ _isActive: true });
},
onHide() {
this.setData({ _isActive: false });
this._clearTimer();
},
onUnload() {
this.setData({ _isActive: false });
this._clearTimer();
},
onPullDownRefresh() {
this.getOrderDetail(); // stopPullDownRefresh 放到 complete 里,更稳
},
// ====== 工具函数 ======
_clearTimer() {
if (this._timer) {
clearInterval(this._timer);
this._timer = null;
}
},
_pad2(n) {
return String(n).padStart(2, "0");
},
_format(sec) {
const m = Math.floor(sec / 60);
const s = sec % 60;
return `${this._pad2(m)}${this._pad2(s)}`;
},
// ====== 拉取订单详情并初始化倒计时 ======
getOrderDetail() {
wx.request({
url: baseUrl + "/courseOrder/query/detail",
method: "POST",
data: { id: this.data.orderId },
header: { Authorization: wx.getStorageSync("token") },
success: (res) => {
if (res.data.code !== 1) {
wx.showToast({ title: res.data.message || "获取失败", icon: "none" });
return;
}
const order = res.data.data || {};
this.setData({ orderObj: order });
// 只有“待支付”才需要倒计时;其它状态关掉计时器并清空文案
if (order.orderStatus === "待支付") {
this._initFromCreateTime(order.createTime);
} else {
this._clearTimer();
this.setData({ countdown: "" });
}
},
fail: () => wx.showToast({ title: "网络错误", icon: "none" }),
complete: () => wx.stopPullDownRefresh(),
});
},
// 计算剩余秒数并启动定时器
_initFromCreateTime(createTime) {
const ts = new Date(String(createTime).replace(/-/g, "/")).getTime();
const createMs = Number.isFinite(ts) ? ts : Date.now();
const ttlMs = 15 * 60 * 1000; // 15分钟有效
const now = Date.now();
let diff = Math.floor((createMs + ttlMs - now) / 1000);
diff = Math.max(0, diff);
// 初始化阶段:如果已过期,静默转“交易关闭”(不弹窗,避免干扰)
if (diff === 0) {
const o = { ...this.data.orderObj, orderStatus: "交易关闭" };
this._clearTimer();
this.setData({ orderObj: o, countdown: "" });
return;
}
// 未过期:初始化倒计时并启动
this._clearTimer();
this.setData({
_secondsRemaining: diff,
countdown: this._format(diff),
_hasShownTimeout: false, // 重置本页弹窗标记
});
this._startTimer();
},
// 每秒递减
_startTimer() {
this._clearTimer();
this._timer = setInterval(() => {
const sec = this.data._secondsRemaining - 1;
if (sec <= 0) {
this._clearTimer();
this._handleTimeout(); // 到点且在当前页,才弹窗
return;
}
this.setData({
_secondsRemaining: sec,
countdown: this._format(sec),
});
}, 1000);
},
// 超时处理:仅在当前页可见时弹一次,并把状态改为“交易关闭”
_handleTimeout() {
const { _isActive, _hasShownTimeout } = this.data;
// 更新状态并隐藏倒计时
const o = { ...this.data.orderObj, orderStatus: "交易关闭" };
this.setData({ orderObj: o, countdown: "" });
// 只在当前页面 & 未弹过 时弹一次
if (_isActive && !_hasShownTimeout) {
wx.showModal({
title: "提示",
content: "订单超时未支付,已关闭",
showCancel: false,
complete: () => {
// 标记已弹
this.setData({ _hasShownTimeout: true });
},
});
} else {
this.setData({ _hasShownTimeout: true });
}
},
// ====== 支付相关 ======
showIsPayModal() {
const { orderId } = this.data;
wx.showModal({
title: "确认支付",
content: "是否立即支付该订单?",
cancelText: "取消",
confirmText: "去支付",
success: (res) => {
if (res.confirm) {
this.payOrder(orderId);
} else if (res.cancel) {
this.setData({ isMaskVisible: false });
}
},
fail: () => {
wx.hideLoading();
wx.showToast({ title: "网络错误", icon: "none" });
},
});
},
payOrder(orderId) {
this.setData({ isMaskVisible: true });
wx.showLoading({ title: "支付中..." });
wx.request({
url: baseUrl + "/courseOrder/payment",
method: "POST",
header: { Authorization: wx.getStorageSync("token") },
data: { id: orderId }, // 若后端用 orderId则把键名改为 orderId
success: (res) => {
wx.hideLoading();
if (res.data.code === 1) {
wx.redirectTo({
url: `/pages/course/orderDetail/orderDetail?id=${orderId}`,
complete: () => this.setData({ isMaskVisible: false }),
});
} else {
this.setData({ isMaskVisible: false });
wx.showToast({ title: res.data.message || "支付失败", icon: "none" });
}
},
fail: () => {
wx.hideLoading();
this.setData({ isMaskVisible: false });
wx.showToast({ title: "网络错误,支付失败", icon: "none" });
},
});
},
// ====== 取消、退款(示例) ======
cancelOrder() {
wx.showModal({
title: "取消订单",
content: "是否要取消订单?",
success: (res) => {
if (res.confirm) {
wx.request({
url: baseUrl + "/courseOrder/cancel",
method: "POST",
header: { Authorization: wx.getStorageSync("token") },
data: { id: this.data.orderId }, // 后端如果需要 { orderId },改键名
success: (r) => {
if (!r.data || r.data.code !== 1) {
wx.showToast({ title: (r.data && r.data.message) || "取消失败", icon: "none" });
}
this.getOrderDetail();
},
fail: () => wx.showToast({ title: "网络错误", icon: "none" }),
});
}
},
});
},
goPay() {
wx.showToast({ title: "支付功能稍后开放", icon: "none" });
},
refundOrder() {
wx.showToast({ title: "退款功能稍后开放", icon: "none" });
},
});

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -0,0 +1,101 @@
<!-- pages/order/orderDetail.wxml -->
<view class="page">
<!-- 中间内容滚动,底部按钮固定,所以这里预留底部内边距 -->
<scroll-view scroll-y class="content no-scrollbar">
<!-- 订单状态 + 倒计时 + 课程信息 -->
<view class="card header-card">
<!-- 状态与倒计时 -->
<view class="status-line">
<view class="status-badge {{ orderObj.orderStatus === '待支付' ? 'status-pending' : (orderObj.orderStatus === '已支付' || orderObj.orderStatus === '交易成功' ? 'status-success' : 'status-default') }}">
<text class="status-text">{{ orderObj.orderStatus }}</text>
</view>
<view wx:if="{{ orderObj.orderStatus === '待支付' }}" class="countdown-pill">
<text class="countdown-text">请在 {{ countdown }} 内完成支付</text>
</view>
</view>
<!-- 课程信息 -->
<view class="course-line">
<image class="cover" src="{{ globalImgUrl + orderObj.image }}" mode="aspectFill" lazy-load="true" />
<view class="course-info">
<text class="course-title ellipsis-2">{{ orderObj.name }}</text>
<view class="price-line">
<text class="price-origin">¥{{ orderObj.originPrice }}</text>
<text class="price-amount">应付:¥{{ orderObj.totalAmount }}</text>
</view>
</view>
</view>
</view>
<!-- 订单详情 -->
<view class="card">
<view class="kv">
<text class="kv-key">订单编号</text>
<text class="kv-val selectable">{{ orderObj.orderNumber }}</text>
</view>
<view class="kv">
<text class="kv-key">下单时间</text>
<text class="kv-val">{{ orderObj.createTime }}</text>
</view>
<view class="divider"></view>
<view class="kv">
<text class="kv-key">支付方式</text>
<text class="kv-val">微信支付</text>
</view>
<view class="kv">
<text class="kv-key">交易号</text>
<!-- 这里可替换为真实字段 -->
<text class="kv-val selectable">4002506191307440406460485418</text>
</view>
<view wx:if="{{ orderObj.orderStatus === '交易成功' }}" class="kv">
<text class="kv-key">交付时间</text>
<text class="kv-val">{{ orderObj.updateTime }}</text>
</view>
</view>
<!-- 价格明细 -->
<view class="card">
<view class="kv">
<text class="kv-key">课程价格</text>
<text class="kv-val">¥{{ orderObj.originPrice }}</text>
</view>
<view class="kv">
<text class="kv-key">价格折扣</text>
<text class="kv-val discount">-¥{{ (orderObj.originPrice - orderObj.totalAmount) >= 0 ? (orderObj.originPrice - orderObj.totalAmount) : 0 }}
</text>
</view>
<view class="kv total">
<text class="kv-key total-key">订单金额</text>
<text class="kv-val total-val">¥{{ orderObj.totalAmount }}</text>
</view>
</view>
</scroll-view>
<!-- 底部按钮:待支付 -->
<view class="footer" wx:if="{{ orderObj.orderStatus === '待支付' }}">
<view class="footer-inner two-btns">
<view class="btn btn-ghost" bindtap="cancelOrder">取消</view>
<view class="btn btn-primary" bindtap="showIsPayModal">立即支付</view>
</view>
</view>
<!-- 底部按钮:已支付 -->
<view class="footer" wx:if="{{ orderObj.orderStatus === '已支付' }}">
<view class="footer-inner one-btn">
<view class="btn btn-primary" bindtap="refundOrder">退款</view>
</view>
</view>
<!-- 遮罩 -->
<view wx:if="{{ isMaskVisible }}" class="page-mask"></view>
</view>

View File

@ -0,0 +1,255 @@
/* ===== 页面框架 ===== */
.page {
background: #f7f7f7;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
padding: 24rpx 24rpx 200rpx; /* 为底部固定按钮预留空间 */
box-sizing: border-box;
}
.no-scrollbar::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
/* 遮罩 */
.page-mask {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.35);
z-index: 9999;
}
/* ===== 卡片通用 ===== */
.card {
background: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.05);
}
.card + .card {
margin-top: 20rpx;
}
/* ===== 顶部卡片:状态 + 倒计时 + 课程 ===== */
.header-card .status-line {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
margin-bottom: 16rpx;
}
.status-badge {
height: 48rpx;
padding: 0 20rpx;
border-radius: 999rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.status-text {
font-size: 26rpx;
font-weight: 600;
}
.status-pending {
background: #fff6e6;
color: #ff8d1a;
}
.status-success {
background: #e9fbef;
color: #12b05b;
}
.status-default {
background: #f0f0f0;
color: #666666;
}
.countdown-pill {
background: #fff4f2;
border: 1rpx solid #ffd6cc;
padding: 0 18rpx;
height: 48rpx;
border-radius: 999rpx;
display: inline-flex;
align-items: center;
}
.countdown-text {
font-size: 24rpx;
color: #ff5a1a;
}
/* 课程行 */
.course-line {
display: flex;
gap: 20rpx;
align-items: stretch;
}
.cover {
width: 240rpx;
height: 160rpx;
border-radius: 12rpx;
background: #f2f2f2;
flex-shrink: 0;
}
.course-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.course-title {
font-size: 32rpx;
font-weight: 600;
color: #1f1f1f;
line-height: 44rpx;
}
.ellipsis-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.price-line {
display: flex;
align-items: baseline;
gap: 16rpx;
margin-top: 8rpx;
}
.price-origin {
font-size: 28rpx;
color: #9f9f9f;
text-decoration: line-through;
}
.price-amount {
font-size: 30rpx;
color: #ff5a1a;
font-weight: 700;
}
/* ===== 键值对(订单详情 / 价格明细) ===== */
.kv {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12rpx 0;
}
.kv + .kv {
border-top: 1rpx dashed #f0f0f0;
}
.kv-key {
font-size: 28rpx;
color: #666666;
}
.kv-val {
font-size: 28rpx;
color: #1f1f1f;
max-width: 70%;
text-align: right;
word-break: break-all;
}
.selectable {
user-select: text;
}
.divider {
height: 1rpx;
background: #f2f2f2;
margin: 8rpx 0 12rpx;
}
.discount {
color: #12b05b;
font-weight: 600;
}
.total {
border-top: 1rpx solid #f2f2f2;
margin-top: 8rpx;
padding-top: 16rpx;
}
.total-key {
font-size: 30rpx;
color: #333333;
font-weight: 600;
}
.total-val {
font-size: 34rpx;
color: #ff5a1a;
font-weight: 700;
}
/* ===== 底部操作栏 ===== */
.footer {
position: fixed;
left: 0; right: 0; bottom: 0;
background: #ffffff;
box-shadow: 0 -6rpx 20rpx rgba(0,0,0,0.06);
padding-bottom: env(safe-area-inset-bottom);
padding-bottom: constant(safe-area-inset-bottom);
}
.footer-inner {
height: 120rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 24rpx;
padding: 0 24rpx;
box-sizing: border-box;
}
.footer-inner.two-btns { justify-content: space-between; }
.footer-inner.one-btn { justify-content: flex-end; }
.btn {
height: 88rpx;
min-width: 260rpx;
border-radius: 999rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
font-weight: 600;
}
.btn-ghost {
background: #ffffff;
color: #333333;
border: 2rpx solid #e6e6e6;
}
.btn-primary {
background: linear-gradient(180deg, #ffa64a 0%, #ff8d1a 100%);
color: #ffffff;
box-shadow: 0 6rpx 14rpx rgba(255, 141, 26, 0.35);
}
/* ===== 迁移提示:以下旧的散装类建议删除(如无外部依赖) ===== */
/* .ml-37, .ml-7, .mt-15, .ml-3, .ml-23, .mt-17, .mt-11, .mt-389 等 */

View File

@ -1,13 +1,45 @@
// pages/course/searchCourses/searchCourses.js
import { baseUrl, globalImgUrl } from "../../../request";
Page({
/**
* 页面的初始数据
*/
data: {
courseList: [],
searchKeyword: '',
globalImgUrl,
},
// 每次用户输入都会进这里
onSearchInput(e) {
this.setData({
searchKeyword: e.detail.value
});
},
gotoCourseDetail(e) {
const courseId = e.currentTarget.dataset.id;
wx.navigateTo({
url: `/pages/course/courseDetail/courseDetail?id=${courseId}`,
});
},
onSearch() {
const token = wx.getStorageSync('token')
const { searchKeyword } = this.data
wx.request({
url: baseUrl + '/course/query/keyword',
header: {
Authorization: token
},
method: 'POST',
data: {
templateString: searchKeyword
},
success: res => {
let result = res.data.data
this.setData({courseList: result})
}
})
},
/**
* 生命周期函数--监听页面加载
*/

View File

@ -1,26 +1,42 @@
<!-- pages/course/searchCourses/searchCourses.wxml -->
<view class="flex-col page">
<view class="flex-row items-center section">
<image
class="image"
src="https://ide.code.fun/api/image?token=6854f3c94ae84d0012332367&name=f2d91149603a9b9bbd30ffd5a77c2043.png"
<view class="page">
<!-- 顶部搜索条(固定) -->
<view class="search-bar" hover-class="hover">
<image class="search-icon" src="./images/sousuo.png" mode="aspectFit"/>
<input
class="search-input"
placeholder="搜索更多好课"
placeholder-class="search-ph"
bindinput="onSearchInput"
confirm-type="search"
bindconfirm="onSearch"
/>
<input class="text ml-3" placeholder="搜索更多好课" />
</view>
<view class="flex-col list mt-17">
<view class="flex-row relative list-item" wx:for="{{items}}" wx:for-item="item" wx:for-index="index" wx:key="index">
<view class="list-divider pos_3"></view>
<image
class="image_2 pos"
src="https://ide.code.fun/api/image?token=6854f3c94ae84d0012332367&name=9c2a22f14e2bd768cbd40d939693e4a8.png"
/>
<view class="flex-col group_2 pos_2">
<text class="font">区块链和加密数字货币(随报随学认证班)</text>
<view class="flex-row justify-between items-baseline mt-17">
<text class="font_2">券后99元起</text>
<text class="font_3">18523人学习</text>
<!-- 搜索结果(独立滚动,隐藏滚动条) -->
<scroll-view scroll-y class="list no-scrollbar">
<block wx:for="{{courseList}}" wx:key="item.id" wx:for-item="item">
<view class="course-card" bindtap="gotoCourseDetail" data-id="{{item.id}}" hover-class="hover">
<!-- 封面 -->
<image class="cover" src="{{globalImgUrl + item.image}}" mode="aspectFill" lazy-load="true"/>
<!-- 文案 -->
<view class="info">
<text class="title">{{item.name}}</text>
<view class="meta">
<text class="price-pill">券后{{item.discountPrice}}元起</text>
<text class="people">{{item.orderCount}}人学习</text>
</view>
</view>
</view>
</block>
<!-- 空状态(可选) -->
<view wx:if="{{!courseList || courseList.length === 0}}" class="empty">
<image class="empty-icon" src="/static/empty.png" mode="aspectFit"/>
<text class="empty-text">没找到相关课程,换个关键词试试~</text>
</view>
</scroll-view>
</view>

View File

@ -1,89 +1,138 @@
/* pages/course/searchCourses/searchCourses.wxss */
.ml-3 {
margin-left: 5.63rpx;
}
.mt-17 {
margin-top: 31.88rpx;
}
/* ===== 页面骨架:整页固定,仅列表滚动 ===== */
.page {
padding: 26.25rpx 0 918.73rpx;
background-color: #ffffff;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
height: 100vh;
display: flex;
flex-direction: column;
background: #ffffff;
overflow: hidden; /* 禁止整页滚动 */
box-sizing: border-box;
font-family: SourceHanSansCN, PingFang SC, Microsoft YaHei, system-ui, -apple-system, sans-serif;
}
.section {
margin-left: 28.13rpx;
margin-right: 26.27rpx;
padding: 11.25rpx 24.38rpx;
background-color: #f2f2f2;
border-radius: 93.75rpx;
/* 触摸反馈 */
.hover { opacity: .86; transition: opacity .18s ease; }
/* ===== 顶部搜索条(固定) ===== */
.search-bar {
padding: 24rpx 28rpx;
box-sizing: border-box;
display: flex;
align-items: center;
gap: 16rpx;
background: #fff;
}
.image {
width: 35.63rpx;
height: 35.63rpx;
}
.text {
color: #a8a8a8;
font-size: 22.5rpx;
font-family: SourceHanSerifCN;
line-height: 20.83rpx;
.search-icon { width: 36rpx; height: 36rpx; opacity: .9; }
/* 胶囊输入框 */
.search-input {
flex: 1;
height: 72rpx;
padding: 0 26rpx;
border-radius: 9999rpx;
background: #f5f6f7;
font-size: 26rpx;
color: #111;
line-height: 72rpx;
box-shadow: inset 0 0 0 1rpx rgba(0,0,0,.04);
}
.search-ph { color: #a8a8a8; font-size: 26rpx; }
/* ===== 列表:占满剩余高度,独立滚动,隐藏滚动条 ===== */
.list {
padding-top: 11.25rpx;
border-top: solid 1.88rpx #d1d1d1;
flex: 1;
padding: 0 24rpx 28rpx;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
background: #fff;
}
.list-item {
padding: 28.13rpx 29.46rpx 0 35.63rpx;
height: 189.39rpx;
.no-scrollbar::-webkit-scrollbar { display: none; width: 0; height: 0; background: transparent; }
.no-scrollbar { scrollbar-width: none; }
/* ===== 课程卡片(左图右文,更工整) ===== */
.course-card {
display: flex;
gap: 22rpx;
padding: 20rpx;
margin-top: 20rpx;
background: #ffffff;
border-radius: 20rpx;
border: 1rpx solid #f1f1f1;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,.05);
}
.list-divider {
background-color: #d6d6d6;
height: 1.88rpx;
/* 封面3:2 比例,圆角 */
.cover {
width: 280rpx;
height: 186rpx;
flex: 0 0 280rpx;
border-radius: 14rpx;
object-fit: cover;
}
.pos_3 {
position: absolute;
left: 35.63rpx;
right: 33.81rpx;
top: 187.52rpx;
/* 信息区 */
.info {
flex: 1;
min-width: 0; /* 防文字溢出 */
display: flex;
flex-direction: column;
justify-content: space-between;
}
.image_2 {
border-radius: 9.38rpx;
width: 208.13rpx;
height: 133.13rpx;
/* 标题:两行省略 */
.title {
font-size: 28rpx;
line-height: 40rpx;
color: #111;
font-weight: 600;
display: -webkit-box;
-webkit-line-clamp: 2; /* 两行省略 */
-webkit-box-orient: vertical;
overflow: hidden;
word-break: break-word;
}
.pos {
position: absolute;
left: 35.63rpx;
top: 50%;
transform: translateY(-50%);
/* 元信息:价格胶囊 + 学习人数 */
.meta {
margin-top: 12rpx;
display: flex;
align-items: baseline;
justify-content: space-between;
}
.group_2 {
width: 453.49rpx;
.price-pill {
padding: 6rpx 14rpx;
font-size: 24rpx;
color: #fff;
border-radius: 9999rpx;
background: linear-gradient(90deg, #ff6a00, #ff8a2a);
box-shadow: 0 6rpx 16rpx rgba(255,106,0,.22);
white-space: nowrap;
}
.pos_2 {
position: absolute;
right: 29.46rpx;
top: 50%;
transform: translateY(-50%);
.people {
font-size: 22rpx;
color: #9aa0a6;
white-space: nowrap;
}
.font {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 31.88rpx;
color: #000000;
/* ===== 空状态 ===== */
.empty {
padding: 120rpx 0 80rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 18rpx;
color: #9aa0a6;
}
.font_2 {
font-size: 26.25rpx;
font-family: AlibabaPuHuiTi;
line-height: 24.15rpx;
color: #ff5733;
}
.font_3 {
font-size: 22.5rpx;
font-family: AlibabaPuHuiTi;
line-height: 20.34rpx;
color: #a6a6a6;
.empty-icon { width: 240rpx; height: 240rpx; opacity: .7; }
.empty-text { font-size: 24rpx; line-height: 34rpx; }
/* ===== 如你项目里已有的工具类,可保留或删除 ===== */
.ml-3 { margin-left: 6rpx; }
.mt-17 { margin-top: 12rpx; }
::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}

View File

@ -1,38 +1,66 @@
// pages/course/waitPayOrder/waitPayOrder.js
Page({
/**
* 页面的初始数据
*/
data: {
// 初始倒计时字符串
countdown: '30分00秒'
},
onLoad(options) {
// 启动倒计时(总秒数 = 29*60 + 17
this.initCountdown(30 * 60 );
},
/**
* 初始化倒计时
* @param {number} totalSeconds 初始总秒数
* 生命周期函数--监听页面加载
*/
initCountdown(totalSeconds) {
this.countdownTimer = setInterval(() => {
if (totalSeconds <= 0) {
clearInterval(this.countdownTimer);
this.setData({ countdown: '00分00秒' });
return;
}
totalSeconds--;
const m = Math.floor(totalSeconds / 60);
const s = totalSeconds % 60;
const mm = m < 10 ? '0' + m : '' + m;
const ss = s < 10 ? '0' + s : '' + s;
this.setData({ countdown: `${mm}${ss}` });
}, 1000);
onLoad(options) {
},
onUnload() {
// 页面卸载时清除定时器
clearInterval(this.countdownTimer);
}
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
});
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

View File

@ -1,79 +1,2 @@
<view class="flex-col page">
<view class="flex-col group">
<view class="flex-col section">
<!-- 订单状态 + 倒计时 -->
<view class="flex-row justify-between self-stretch group_2">
<text class="font">订单状态</text>
<view class="flex-row group_3">
<text class="font_2 text">请在{{countdown}}内完成支付</text>
<text class="font_2 text_2 ml-37">待支付</text>
</view>
</view>
<!-- 课程信息 -->
<view class="flex-row self-stretch group_4 mt-15">
<image
class="shrink-0 image"
src="https://ide.code.fun/api/image?token=6859f7a14ae84d0012334fa9&name=9c2a22f14e2bd768cbd40d939693e4a8.png"
/>
<text class="flex-1 self-start font_3 text_3 ml-7">
区块链和加密数字货币(随报随学认证班)(随报随学认证班)
</text>
</view>
<!-- 课程价格 -->
<text class="self-end font_3 text_4 mt-15">¥999.00</text>
</view>
<!-- 订单详情 -->
<view class="mt-16 flex-col section_2">
<view class="self-start group_5">
<text class="font text_5">订单编号:</text>
<text class="font_4">202506191307440406460485418</text>
</view>
<view class="flex-row items-baseline self-start group_6">
<text class="shrink-0 font text_6">下单时间:</text>
<text class="flex-1 font_5 ml-3">2025-06-19 16:08:15</text>
</view>
<view class="flex-col justify-start self-stretch relative group_7">
<view class="flex-col section_3">
<view class="self-stretch divider"></view>
<view class="flex-row self-stretch group_8 mt-17">
<text class="font text_7">支付方式:</text>
<text class="ml-8 font text_8">微信支付</text>
</view>
<view class="flex-row items-center self-stretch mt-17">
<text class="font text_9">交易号:</text>
<text class="font_4 ml-23">4002506191307440406460485418</text>
</view>
<text class="self-start font text_10 mt-17">交付时间:</text>
</view>
<text class="font_5 text_11 pos">2025-06-19 08:48:35</text>
</view>
</view>
<!-- 价格明细 -->
<view class="mt-16 flex-col section_4">
<view class="flex-row justify-between items-center">
<text class="font text_12">课程价格</text>
<text class="font_4">¥1999.9</text>
</view>
<view class="flex-row justify-between items-center mt-11">
<text class="font text_13">价格折扣</text>
<text class="font_4 text_14">-¥10</text>
</view>
<view class="flex-row justify-between items-center group_9 mt-11">
<text class="font_2 text_15">订单金额</text>
<text class="font_4 text_16">¥999</text>
</view>
</view>
</view>
<!-- 底部按钮 -->
<view class="flex-row mt-389">
<view class="flex-col justify-start items-center text-wrapper">
<text class="font_3 text_17">取消</text>
</view>
<view class="flex-col justify-start items-center text-wrapper_2">
<text class="font_3 text_18">立即支付</text>
</view>
</view>
</view>
<!--pages/course/waitPayOrder/waitPayOrder.wxml-->
<text>pages/course/waitPayOrder/waitPayOrder.wxml</text>

View File

@ -1,208 +0,0 @@
.ml-37 {
margin-left: 69.38rpx;
}
.ml-7 {
margin-left: 13.13rpx;
}
.mt-15 {
margin-top: 28.13rpx;
}
.ml-3 {
margin-left: 5.63rpx;
}
.ml-23 {
margin-left: 40.13rpx;
}
.mt-17 {
margin-top: 31.88rpx;
}
.mt-11 {
margin-top: 20.63rpx;
}
.mt-389 {
margin-top: 729.38rpx;
}
/* 整体布局 */
.page {
padding-top: 26.25rpx;
background-color: #f8f8f8;
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
.group {
padding: 0 18.75rpx;
}
/* 调整首屏 section 右边内边距,不让价格太贴边 */
.section {
padding: 0 22.5rpx 33.75rpx 22.5rpx;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
background-color: #ffffff;
border-radius: 7.22rpx;
}
/* 订单详情区 */
.group_2 {
padding: 33.75rpx 0 26.25rpx;
border-bottom: solid 1.88rpx #e3e3e3;
}
.group_3 {
margin-right: 18.75rpx;
}
.font_2 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.23rpx;
color: #f84947;
}
.text {
line-height: 24.56rpx;
}
.text_2 {
line-height: 24.17rpx;
}
.group_4 {
margin-right: 33.75rpx;
}
.image {
border-radius: 9.38rpx;
width: 208.13rpx;
height: 133.13rpx;
}
.font_3 {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.64rpx;
}
.text_3 {
color: #000000;
line-height: 35.63rpx;
}
.text_4 {
color: #3d3d3d;
line-height: 22.76rpx;
}
/* 订单详情二级区 */
.section_2 {
padding: 33.75rpx 22.5rpx 0;
background-color: #ffffff;
border-radius: 7.39rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.group_5 {
line-height: 24.28rpx;
}
.font_4 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 19.93rpx;
color: #323232;
}
.group_6 {
margin-top: 30rpx;
width: 369.94rpx;
}
.font_5 {
font-size: 26.25rpx;
line-height: 31.88rpx;
color: #323232;
}
.group_7 {
margin-top: 11.25rpx;
padding-bottom: 26.25rpx;
}
.section_3 {
padding-top: 9.38rpx;
background-color: #ffffff;
}
.divider {
background-color: #cccccc;
height: 1.88rpx;
}
.group_8 {
padding: 0 3.75rpx;
}
.font {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.23rpx;
color: #696969;
}
.text_7 {
line-height: 24.36rpx;
}
.text_6 {
line-height: 31.88rpx;
}
.text_5 {
line-height: 24.28rpx;
}
.text_8 {
color: #323232;
}
.text_9 {
line-height: 24.52rpx;
}
.text_10 {
line-height: 24.43rpx;
}
.text_11 {
width: 270rpx;
}
.pos {
position: absolute;
left: 141.05rpx;
top: 142.92rpx;
}
/* 调整价格明细区右边内边距 */
.section_4 {
padding: 22.5rpx 22.5rpx 0 22.5rpx;
background-color: #ffffff;
border-radius: 4.01rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.text_12 {
line-height: 24.41rpx;
}
.text_13 {
line-height: 24.41rpx;
}
.text_14 {
margin-right: 15rpx;
}
.group_9 {
padding: 22.5rpx 0 18.75rpx;
border-top: solid 1.88rpx #e3e3e3;
}
.text_15 {
line-height: 24.49rpx;
}
.text_16 {
color: #f84947;
}
/* 底部按钮 */
.text-wrapper {
padding: 37.5rpx 0;
flex: 1 1 375rpx;
background-color: #ffffff;
height: 105rpx;
}
.text-wrapper_2 {
padding: 37.5rpx 0;
flex: 1 1 375rpx;
background-color: #ff8d1a;
height: 105rpx;
}
.text_17 {
color: #323232;
}
.text_18 {
color: #ffffff;
line-height: 27.81rpx;
}

View File

@ -0,0 +1,88 @@
import { baseUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
// pages/dashboardModule/overviewPerformance/overviewPerformance.js
Page({
data: {
totalAmount: 0, // 订单总金额
netAmount: 0, // 净成交
promoCount: 0, // 客户数量
superCount: 0, // 主管数量
empCount: 0, // 员工数量
orderCount: 0, // 下单数量
toRelease: 0, // 待释放
toSettle: 0, // 可结算
settled: 0, // 已结算
refunded: 0, // 已退回
todayOrderCount: 0, // 今日下单数量
todayOrderAmount: 0, // 今日下单总金额
todayRefundCount: 0, // 今日退款数量
todayRefundAmount: 0, // 今日退款总金额
todayPromotionCount: 0, // 今日推广数量
monthOrderCount: 0, // 本月下单数量
monthOrderAmount: 0, // 本月下单总金额
monthRefundCount: 0, // 本月退款数量
monthRefundAmount: 0, // 本月退款总金额
monthPromotionCount: 0, // 本月推广数量
userRole: '', // 用户角色
isShowArr: [],
widthRate: '30%'
},
onLoad(options) {
console.log('--->',options);
this.fetchPerformance();
this.setData({
userRole: options.role
})
let showRole = '';
switch (options.role) {
case 'manager':
showRole = '经理';
break;
case 'supervisor':
showRole = '主管';
break;
case 'staff':
showRole = '员工';
break;
}
this.setData({ showRole });
if (options.role === 'manager') this.setData({isShowArr: [true, true, true]})
else if (options.role === 'supervisor') this.setData({isShowArr: [false, true, true]})
else if (options.role === 'staff') this.setData({isShowArr: [false, false, true]})
const trueCount = this.data.isShowArr.filter(v => v === true).length;
if (trueCount === 3) this.setData({widthRate: '30%'})
else if (trueCount === 2) this.setData({widthRate: '47.5%'})
else if (trueCount === 1) this.setData({widthRate: '100%'})
},
onPullDownRefresh() {
this.fetchPerformance()
wx.stopPullDownRefresh();
},
fetchPerformance() {
wx.request({
url: baseUrl + '/perform/mini/query/dashboard',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
success: (res) => {
if (res.data.code === 1) {
// 直接把后端 data 对象铺平到页面 data
this.setData(res.data.data);
} else {
notLogin(res.data.message)
}
},
fail: () => {
wx.showToast({
title: '请求失败',
icon: 'none'
});
}
});
}
});

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -0,0 +1,96 @@
<view class="flex-col page">
<text class="self-center text">{{ showRole }}端绩效总览</text>
<view class="flex-col justify-start self-stretch relative group mt-41">
<view class="flex-col group_2">
<!-- 今日数据 -->
<view class="flex-row equal-division">
<view class="flex-col items-start equal-division-item section">
<text class="font_3 text_8">今日数据</text>
<text class="font text_10">今日下单数量</text>
<text class="font_2 text_12">{{todayOrderCount}}</text>
<text class="font text_14">今日订单总金额</text>
<text class="font_2 text_16">¥{{todayOrderAmount}}</text>
<text class="font text_18">今日退单数量</text>
<text class="font_2 text_20">{{todayRefundCount}}</text>
<text class="font text_22">今日退款总金额</text>
<text class="font_2 text_24">¥{{todayRefundAmount}}</text>
<text class="font_4 text_26">今日推广数量</text>
<text class="font_2 text_28">{{todayPromotionCount}}</text>
</view>
<!-- 本月数据 -->
<view class="flex-col items-start equal-division-item section_2 ml-19">
<text class="font_3 text_9">本月数据</text>
<text class="font text_11">本月下单数量</text>
<text class="font_2 text_13">{{monthOrderCount}}</text>
<text class="font text_15">本月订单总金额</text>
<text class="font_2 text_17">¥{{monthOrderAmount}}</text>
<text class="font text_19">本月退单数量</text>
<text class="font_2 text_21">{{monthRefundCount}}</text>
<text class="font text_23">本月退款总金额</text>
<text class="font_2 text_25">¥{{monthRefundAmount}}</text>
<text class="font_4 text_27">本月推广数量</text>
<text class="font_2 text_29">{{monthPromotionCount}}</text>
</view>
</view>
<!-- 财务状态 -->
<view class="mt-30 flex-col section_3">
<text class="self-start font_3">财务状态</text>
<view class="mt-26 flex-col self-stretch">
<view class="flex-row justify-between items-baseline">
<text class="font text_30">待释放</text>
<text class="font_2 text_31">{{toRelease}}</text>
</view>
<view class="flex-row justify-between items-baseline mt-19">
<text class="font text_32">可结算</text>
<text class="font_2 text_33">{{toSettle}}</text>
</view>
<view class="flex-row justify-between items-baseline mt-19">
<text class="font text_34">已结算</text>
<text class="font_2 text_35">{{settled}}</text>
</view>
<view class="flex-row justify-between items-baseline mt-19">
<text class="font text_36">已退回</text>
<text class="font_2 text_37">{{refunded}}</text>
</view>
</view>
</view>
</view>
<!-- 底部网格 -->
<view class="pos">
<view class="flex-row" style="justify-content: space-between;">
<view style="width: {{widthRate}};" class="flex-col items-center grid-item" wx:if="{{isShowArr[0]}}">
<text class="font text_2">主管数量</text>
<text class="mt-20 font_2">{{superCount}}</text>
</view>
<view style="width: {{widthRate}};" class="flex-col items-center grid-item" wx:if="{{isShowArr[1]}}">
<text class="font text_3">员工数量</text>
<text class="mt-20 font_2">{{empCount}}</text>
</view>
<view style="width: {{widthRate}};" class="flex-col items-center grid-item" wx:if="{{isShowArr[2]}}">
<text class="font text_4">客户数量</text>
<text class="mt-20 font_2">{{promoCount}}</text>
</view>
</view>
<view class="flex-row" style="justify-content: space-between;">
<view class="flex-col items-center grid-item_2" style="margin-right: 10rpx">
<text class="font text_5">订单总金额</text>
<text class="mt-20 font_2">¥{{totalAmount}}</text>
</view>
<view class="flex-col items-center grid-item_2" style="margin: 40rpx 10rpx 0">
<text class="font text_6">订单净成交</text>
<text class="mt-20 font_2">¥{{netAmount}}</text>
</view>
<view class="flex-col items-center grid-item_2" style="margin-left: 10rpx">
<text class="font text_7">下单数量</text>
<text class="mt-20 font_2">{{orderCount}}</text>
</view>
</view>
</view>
</view>
</view>

View File

@ -0,0 +1,254 @@
.mt-41 {
margin-top: 76.88rpx;
}
.ml-19 {
margin-left: 35.63rpx;
}
.mt-19 {
margin-top: 35.63rpx;
}
.page {
padding-top: 71.25rpx;
background-color: #fefbf6;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.text {
color: #e67e22;
font-size: 45rpx;
font-family: SourceHanSansCN;
font-weight: 700;
line-height: 42.71rpx;
}
.group {
padding-top: 168.75rpx;
}
.group_2 {
margin-right: 33.75rpx;
padding: 138.75rpx 0 120rpx 41.25rpx;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
}
.equal-division {
padding-top: 48.75rpx;
}
.equal-division-item {
flex: 1 1 320.63rpx;
}
.section {
padding: 41.25rpx 33.75rpx 33.75rpx;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
background-color: #ffffff;
border-radius: 9.38rpx;
height: 684.38rpx;
border-left: solid 5.88rpx #e67e22;
/* border-right: solid 1.88rpx #e67e22; */
border-top: solid 5.88rpx #e67e22;
/* border-bottom: solid 1.88rpx #e67e22; */
}
.font_3 {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 28.01rpx;
color: #e67e22;
}
.text_8 {
line-height: 28.24rpx;
}
.font {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 22.91rpx;
color: #666666;
}
.text_10 {
margin-top: 33.75rpx;
line-height: 24.69rpx;
}
.text_14 {
margin-top: 41.25rpx;
line-height: 24.75rpx;
}
.text_18 {
margin-top: 41.25rpx;
line-height: 24.69rpx;
}
.text_22 {
margin-top: 41.25rpx;
line-height: 24.75rpx;
}
.font_4 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.92rpx;
color: #666666;
}
.text_26 {
margin-top: 41.25rpx;
}
.section_2 {
padding: 41.25rpx 33.75rpx 33.75rpx;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
background-color: #ffffff;
border-radius: 9.38rpx;
height: 684.38rpx;
border-left: solid 5.88rpx #f1c40f;
/* border-right: solid 1.88rpx #f1c40f; */
border-top: solid 5.88rpx #f1c40f;
/* border-bottom: solid 1.88rpx #f1c40f; */
}
.text_9 {
color: #f1c40f;
line-height: 27.99rpx;
}
.text_11 {
margin-top: 33.75rpx;
line-height: 24.69rpx;
}
.text_15 {
margin-top: 41.25rpx;
line-height: 24.75rpx;
}
.text_19 {
margin-top: 41.25rpx;
line-height: 24.69rpx;
}
.text_23 {
margin-top: 41.25rpx;
line-height: 24.75rpx;
}
.text_27 {
margin-top: 41.25rpx;
}
.section_3 {
padding: 37.5rpx 20rpx 37.5rpx 33.75rpx;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
background-color: #ffffff;
border-radius: 9.38rpx;
border-left: solid 5.88rpx #e67e22;
/* border-right: solid 1.88rpx #e67e22; */
border-top: solid 5.88rpx #e67e22;
/* border-bottom: solid 1.88rpx #e67e22; */
}
.text_30 {
line-height: 24.3rpx;
}
.text_32 {
line-height: 24.3rpx;
}
.text_34 {
line-height: 24.3rpx;
}
.text_36 {
line-height: 24.3rpx;
}
.grid {
height: 306.56rpx;
display: grid;
grid-template-rows: repeat(2, minmax(0, 1fr));
grid-template-columns: repeat(3, minmax(0, 1fr));
row-gap: 32.94rpx;
column-gap: 50.19rpx;
}
.pos {
position: absolute;
left: 39.38rpx;
right: 33rpx;
top: 0;
}
.grid-item {
padding: 22.5rpx 0;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
background-color: #ffffff;
border-radius: 9.38rpx;
border-left: solid 5.88rpx #e67e22;
/* border-right: solid 1.88rpx #e67e22; */
border-top: solid 5.88rpx #e67e22;
/* border-bottom: solid 1.88rpx #e67e22; */
}
.text_2 {
line-height: 24.34rpx;
}
.font_2 {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 22.91rpx;
color: #e67e22;
}
.text_37 {
margin-right: 7.5rpx;
}
.text_35 {
margin-right: 3.75rpx;
}
.text_33 {
margin-right: 3.75rpx;
}
.text_31 {
margin-right: 3.75rpx;
}
.text_29 {
margin-top: 26.25rpx;
}
.text_25 {
margin-left: 3.75rpx;
margin-top: 26.25rpx;
}
.text_21 {
margin-top: 26.25rpx;
line-height: 22.54rpx;
}
.text_17 {
margin-left: 3.75rpx;
margin-top: 26.25rpx;
}
.text_13 {
margin-top: 26.25rpx;
}
.text_28 {
margin-top: 26.25rpx;
}
.text_24 {
margin-left: 3.75rpx;
margin-top: 26.25rpx;
}
.text_20 {
margin-top: 26.25rpx;
line-height: 22.54rpx;
}
.text_16 {
margin-left: 3.75rpx;
margin-top: 26.25rpx;
}
.text_12 {
margin-top: 26.25rpx;
}
.text_3 {
line-height: 24.28rpx;
}
.text_4 {
line-height: 24.54rpx;
}
.grid-item_2 {
width: 30%;
margin-top: 40rpx;
padding: 22.5rpx 0;
filter: drop-shadow(0rpx 3.75rpx 3.75rpx #00000040);
background-color: #ffffff;
border-radius: 9.38rpx;
border-left: solid 5.88rpx #f1c40f;
/* border-right: solid 1.88rpx #f1c40f; */
border-top: solid 5.88rpx #f1c40f;
/* border-bottom: solid 1.88rpx #f1c40f; */
}
.text_5 {
line-height: 24.49rpx;
}
.text_6 {
line-height: 24.56rpx;
}
.text_7 {
line-height: 24.26rpx;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

View File

@ -0,0 +1,209 @@
import { baseUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
Page({
data: {
// 用于存储输入框数据
nickName: '',
phoneNumber: '',
selectedSortField: '员工数量', // 默认选择"员工数量"
selectedSortOrder: '降序', // 默认选择升序
sortFieldsByManager: ['员工数量', '推广人数', '下单数量', '总订单金额', '净成交金额'],
sortFieldsBySupervisor: ['推广人数', '下单数量', '总订单金额', '净成交金额'],
sortField: 'empCount',
sortOrder: 'descend',
sortOrders: ['升序', '降序'],
items: [], // 用于存储查询结果
role: '', // 假设初始为主管角色,可以根据实际情况动态设置
k: 1,
showRole: ''
},
// 主管名称输入
onNameInput(e) {
this.setData({
nickName: e.detail.value
});
},
// 手机号输入
onPhoneInput(e) {
this.setData({
phoneNumber: e.detail.value
});
},
// 选择排序字段
onSortFieldChange(e) {
const sortFieldsMap = {
'员工数量': 'empCount',
'推广人数': 'promoCount',
'下单数量': 'orderCount',
'总订单金额': 'totalAmount',
'净成交金额': 'netAmount'
};
const { showRole, sortFieldsByManager, sortFieldsBySupervisor } = this.data
let selectedField = showRole === '主管' ? sortFieldsByManager[e.detail.value] : sortFieldsBySupervisor[e.detail.value];
this.setData({
selectedSortField: selectedField,
sortField: sortFieldsMap[selectedField], // 默认是 id
});
this.onSearch()
},
// 选择排序顺序
onSortOrderChange(e) {
const selectedOrder = e.detail.value === '0' ? 'ascend' : 'descend';
this.setData({
selectedSortOrder: selectedOrder === 'ascend' ? '升序' : '降序',
sortOrder: selectedOrder,
});
this.onSearch()
},
// 搜索按钮点击
onSearch() {
const { showRole, role } = this.data;
// // —— 新增:校验主管名称 ——
// const nameRegex = /^[\u4e00-\u9fa5]+$/;
// if (!this.data.nickName) {
// wx.showToast({ title: '主管名称不能为空', icon: 'none' });
// return;
// }
// if (!nameRegex.test(this.data.nickName)) {
// wx.showToast({ title: '主管名称只能为汉字', icon: 'none' });
// return;
// }
// // —— 新增:校验手机号 ——
// if (!this.data.phoneNumber) {
// wx.showToast({ title: '手机号不能为空', icon: 'none' });
// return;
// }
// if (this.data.phoneNumber.length < 11) {
// wx.showToast({ title: '手机号不够11位', icon: 'none' });
// return;
// }
// 原排序条件校验,保持不变
// if (this.data.selectedSortField === '待选择') {
// wx.showToast({
// title: '排序条件不能为空',
// icon: 'none'
// });
// return;
// }
// 显示加载中
wx.showLoading({
title: '加载中...',
mask: true // 显示遮罩层
});
if (showRole === '员工') {
this.setData({ sortField: 'promoCount' })
}
const requestData = {
nickName: this.data.nickName,
phoneNumber: this.data.phoneNumber,
sortField: this.data.sortField || '',
sortOrder: this.data.sortOrder || 'ascend'
};
console.log('requestData====>', requestData)
if(role === 'manager') {
wx.request({
url: baseUrl + '/perform/rank/supervisor', // 替换为实际API地址
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: requestData,
success: (res) => {
console.log('看看后端--->', res.data);
// 请求成功后隐藏loading
wx.hideLoading();
if (res.data.code === 1) {
this.setData({
items: res.data.data
});
} else {
notLogin(res.data.message)
}
},
fail: () => {
// 请求失败后隐藏loading
wx.hideLoading();
wx.showToast({
title: '请求失败',
icon: 'none'
});
}
});
} else if( role === 'supervisor' || role === 'staff') {
wx.request({
url: baseUrl + '/perform/rank/staff', // 替换为实际API地址
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: requestData,
success: (res) => {
console.log('看看后端--->', res.data);
// 请求成功后隐藏loading
wx.hideLoading();
if (res.data.code === 1) {
this.setData({
items: res.data.data
});
} else {
wx.showToast({
title: '没有数据',
icon: 'none'
});
}
},
fail: () => {
// 请求失败后隐藏loading
wx.hideLoading();
wx.showToast({
title: '请求失败',
icon: 'none'
});
}
});
}
},
onLoad(options) {
// 根据身份确定角色
const role = options.role;
this.setData({k: options.k})
if (role === 'staff') this.setData({selectedSortField: '推广人数'})
console.log('角色---->',options.role);
this.setData({ role });
let showRole = '';
switch (options.role) {
case 'manager':
showRole = '主管';
break;
case 'supervisor':
showRole = '员工';
break;
case 'staff':
showRole = '员工'
}
this.setData({ showRole });
this.onSearch()
},
onPullDownRefresh() {
this.onSearch()
wx.stopPullDownRefresh();
},
});

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -0,0 +1,127 @@
<!-- pages/dashboardModule/ranking/ranking.wxml按你的实际路径命名 -->
<view class="page">
<!-- 页面标题 -->
<view class="page-title">
<text class="title">{{ showRole }}绩效排名</text>
</view>
<scroll-view scroll-y class="content no-scrollbar">
<!-- 表单卡片 -->
<view class="card form-card">
<!-- 名称 -->
<view class="field">
<text class="field-label">{{ showRole }}名称</text>
<view class="input-box">
<input
class="input"
placeholder="请输入{{ showRole }}名称"
bindinput="onNameInput"
/>
</view>
</view>
<!-- 手机号 -->
<view class="field">
<text class="field-label">手机号</text>
<view class="input-box">
<input
class="input"
placeholder="请输入手机号"
bindinput="onPhoneInput"
maxlength="11"
type="number"
/>
</view>
</view>
<!-- 排序条件 -->
<view class="field">
<text class="field-label">排序条件</text>
<view class="picker-row">
<!-- 排序字段 -->
<view class="picker-box">
<picker wx:if="{{ role === 'manager' }}"
mode="selector"
range="{{ sortFieldsByManager }}"
bindchange="onSortFieldChange">
<view class="picker-inner">
<text class="picker-text">{{ selectedSortField }}</text>
<image class="arrow" src="./images/bottom.png"/>
</view>
</picker>
<picker wx:if="{{ role === 'supervisor' || role === 'staff' }}"
mode="selector"
range="{{ sortFieldsBySupervisor }}"
bindchange="onSortFieldChange">
<view class="picker-inner">
<text class="picker-text">{{ selectedSortField }}</text>
<image class="arrow" src="./images/bottom.png" />
</view>
</picker>
</view>
<!-- 排序顺序 -->
<view class="picker-box">
<picker mode="selector"
range="{{ sortOrders }}"
bindchange="onSortOrderChange">
<view class="picker-inner">
<text class="picker-text">{{ selectedSortOrder }}</text>
<image class="arrow" src="./images/bottom.png" />
</view>
</picker>
</view>
</view>
</view>
<!-- 搜索按钮 -->
<view class="btn btn-primary" bindtap="onSearch">搜索</view>
</view>
<!-- 结果列表 -->
<view class="result-wrap">
<view class="card item-card"
wx:for="{{ items }}"
wx:for-item="item"
wx:for-index="index"
wx:key="index">
<!-- 头部:排名 + 基本信息 -->
<view class="item-head">
<view class="rank-badge {{ index < 3 ? 'rank-top' : '' }}">
<text class="rank-text">{{ index + 1 }}</text>
</view>
<view class="person-line">
<text class="name">{{ item.nickName }}</text>
<text class="phone">{{ item.phoneNumber }}</text>
</view>
</view>
<!-- 指标 chips -->
<view class="chips">
<view wx:if="{{ k === '1' }}" class="chip">员工:{{ item.empCount }}</view>
<view class="chip">推广:{{ item.promoCount }}</view>
<view class="chip">下单:{{ item.orderCount }}</view>
</view>
<!-- 金额类键值行 -->
<view class="kv">
<text class="kv-key">总额</text>
<text class="kv-val money">¥{{ item.totalAmount }}</text>
</view>
<view class="kv">
<text class="kv-key">净成交</text>
<text class="kv-val money">¥{{ item.netAmount }}</text>
</view>
</view>
<!-- 空状态 -->
<view wx:if="{{ !items || !items.length }}" class="empty">
<image class="empty-img" src="/assets/empty-list.png" mode="aspectFit" />
<text class="empty-text">暂无数据</text>
</view>
</view>
</scroll-view>
</view>

View File

@ -0,0 +1,189 @@
/* ===== 页面框架 ===== */
.page {
background: #fefbf6;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.page-title {
padding: 24rpx 24rpx 0;
}
.title {
font-size: 40rpx;
font-weight: 700;
color: #ff8a00; /* 主色:亮橙 */
}
.content {
flex: 1;
padding: 24rpx;
box-sizing: border-box;
}
/* 隐藏滚动条 */
.no-scrollbar::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
/* ===== 卡片通用 ===== */
.card {
background: #ffffff;
border-radius: 18rpx;
padding: 24rpx;
border: 2rpx solid #ffeaa7; /* 与你项目的浅橙描边一致 */
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.05);
}
.card + .card { margin-top: 20rpx; }
/* ===== 表单区 ===== */
.form-card .field + .field { margin-top: 20rpx; }
.field-label {
font-size: 28rpx;
color: #555555;
margin-bottom: 12rpx;
display: block;
}
/* 输入框 */
.input-box {
height: 84rpx;
border-radius: 12rpx;
border: 2rpx solid #ffeaa7;
background: #ffffff;
padding: 0 20rpx;
display: flex;
align-items: center;
}
.input {
flex: 1;
font-size: 28rpx;
color: #1f1f1f;
}
/* 选择器行 */
.picker-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16rpx;
}
.picker-box {
height: 84rpx;
border-radius: 12rpx;
border: 2rpx solid #ffeaa7;
background: #ffffff;
display: flex;
align-items: center;
position: relative;
}
.picker-inner {
padding: 0 20rpx;
width: 270rpx;
height: 84rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.picker-text { font-size: 28rpx; color: #1f1f1f;}
.arrow { width: 28rpx; height: 28rpx; position: absolute; right: 20rpx;}
/* 搜索按钮 */
.btn {
height: 88rpx;
border-radius: 999rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
font-weight: 600;
margin-top: 24rpx;
}
.btn-primary {
background: linear-gradient(180deg, #ffa400 0%, #ff8a00 100%);
color: #ffffff;
box-shadow: 0 6rpx 14rpx rgba(255,138,0,0.30);
}
/* ===== 列表与条目 ===== */
.result-wrap { margin-top: 20rpx; }
.item-card { padding-top: 20rpx; }
/* 顶部信息 */
.item-head {
display: flex;
align-items: center;
gap: 16rpx;
margin-bottom: 8rpx;
}
.rank-badge {
width: 64rpx;
height: 64rpx;
border-radius: 999rpx;
background: #f0f0f0;
border: 2rpx solid #e6e6e6;
display: flex;
align-items: center;
justify-content: center;
}
.rank-top {
background: #fff6e6;
border-color: #ffd6b3;
}
.rank-text {
font-size: 28rpx;
font-weight: 700;
color: #ff8a00; /* 改为亮橙 */
}
.person-line {
display: flex;
align-items: baseline;
gap: 12rpx;
flex-wrap: wrap;
}
.name { font-size: 30rpx; font-weight: 600; color: #1f1f1f; }
.phone { font-size: 26rpx; color: #666666; }
/* 指标 Chips */
.chips {
display: flex;
gap: 12rpx;
flex-wrap: wrap;
margin: 8rpx 0 4rpx;
}
.chip {
padding: 10rpx 16rpx;
background: #f7f9fc;
color: #3d4f6e;
border: 1rpx solid #e6edf7;
border-radius: 12rpx;
font-size: 24rpx;
}
/* 金额类键值行 */
.kv {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12rpx 0;
border-top: 1rpx dashed #f0f0f0;
}
.kv:first-of-type { border-top: 0; }
.kv-key { font-size: 26rpx; color: #666666; }
.kv-val { font-size: 28rpx; color: #1f1f1f; }
.money { color: #ff8a00; font-weight: 700; }
/* ===== 空状态 ===== */
.empty {
padding: 120rpx 0 40rpx;
display: flex;
flex-direction: column;
align-items: center;
color: #999999;
}
.empty-img { width: 300rpx; height: 300rpx; margin-bottom: 16rpx; }
.empty-text { font-size: 26rpx; }

View File

@ -0,0 +1,122 @@
import { baseUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
// pages/dashboardModule/supervisorPerformance/supervisorPerformance.js
Page({
data: {
nickName: '', // 主管名称
phoneNumber: '', // 手机号
showList: false, // 是否显示绩效列表
performanceList: [], // 绩效列表数据,含 ratePercent 字段
supervisorUserId: 0, // 上级主管id
},
onNameInput(e) {
this.setData({ nickName: e.detail.value });
},
onPhoneInput(e) {
this.setData({ phoneNumber: e.detail.value });
},
onSearch() {
const nickName = this.data.nickName.trim();
const phoneNumber = this.data.phoneNumber.trim();
const { supervisorUserId } = this.data;
wx.request({
url: baseUrl + '/perform/query/staff',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: {
nickName: nickName,
phoneNumber: phoneNumber,
supervisorUserId: supervisorUserId,
},
success: (res) => {
console.log('--->后端返回记录',res.data);
if (res.data.code === 1) {
// 预处理:给每条记录加一个 ratePercent 字段
const listWithRate = res.data.data.map(item => {
const ratePercent = (item.rakeRewardsRate * 100).toFixed(2);
return Object.assign({}, item, { ratePercent });
});
// 分两次 setData不链
this.setData({ performanceList: listWithRate });
this.setData({ showList: true });
} else {
notLogin(res.data.message)
}
},
fail: () => {
wx.showToast({ title: '网络错误', icon: 'none' });
}
});
},
// 全查
onSearchSupId() {
const { supervisorUserId } = this.data;
wx.request({
url: baseUrl + '/perform/query/staff',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: { supervisorUserId },
success: (res) => {
console.log('--->后端返回记录',res.data);
if (res.data.code === 1) {
// 预处理:给每条记录加一个 ratePercent 字段
const listWithRate = res.data.data.map(item => {
const ratePercent = (item.rakeRewardsRate * 100).toFixed(2);
return Object.assign({}, item, { ratePercent });
});
// 分两次 setData不链
this.setData({ performanceList: listWithRate });
this.setData({ showList: true });
} else {
wx.showToast({ title: res.data.message || '查询失败', icon: 'none' });
}
},
fail: () => {
wx.showToast({ title: '网络错误', icon: 'none' });
}
});
},
onCopyPhone(e) {
const phone = e.currentTarget.dataset.phone;
wx.setClipboardData({
data: phone,
success() {
wx.showToast({ title: '手机号已复制', icon: 'success' });
}
});
},
onLoad(options) {
console.log('========>', options)
this.setData({
supervisorUserId: options.supId,
})
this.onSearchSupId();
},
onPullDownRefresh() {
this.onSearchSupId()
wx.stopPullDownRefresh();
},
// 跳转用户订单
gotoUser(e) {
const { id } = e.currentTarget.dataset;
wx.navigateTo({
url: `/pages/dashboardModule/userOrderPerformance/userOrderPerformance?userId=${id}`,
})
},
});

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -0,0 +1,128 @@
<!-- pages/dashboardModule/supervisorPerformance/supervisorPerformance.wxml -->
<view class="page">
<!-- 标题 -->
<view class="page-title">
<text class="title">员工业绩报表</text>
</view>
<scroll-view scroll-y class="content no-scrollbar">
<!-- 搜索表单 -->
<view class="card form-card">
<!-- 员工名称 -->
<view class="field">
<text class="field-label">员工名称</text>
<view class="input-box">
<input
class="input"
placeholder="请输入员工名称"
placeholder-class="ph"
bindinput="onNameInput"
value="{{ nickName }}"
/>
</view>
</view>
<!-- 手机号 -->
<view class="field">
<text class="field-label">手机号</text>
<view class="input-box">
<input
class="input"
placeholder="请输入手机号"
placeholder-class="ph"
bindinput="onPhoneInput"
value="{{ phoneNumber }}"
type="number"
maxlength="11"
/>
</view>
</view>
<!-- 搜索 -->
<view class="btn btn-primary" bindtap="onSearch">搜索</view>
</view>
<!-- 业绩列表 -->
<block wx:if="{{ showList }}">
<!-- 空状态(可选) -->
<view wx:if="{{ !performanceList || performanceList.length === 0 }}" class="empty">
<image class="empty-img" src="/assets/empty-list.png" mode="aspectFit" />
<text class="empty-text">暂无数据</text>
</view>
<!-- 列表卡片 -->
<view wx:for="{{ performanceList }}"
wx:key="item.id"
wx:for-item="item"
wx:for-index="index"
class="card perf-card">
<!-- 顶部:编号 + 员工 + 跳转 -->
<view class="topline">
<view class="id-and-name">
<text class="no">编号:{{ index + 1 }}</text>
<text class="name">员工:{{ item.nickName }}</text>
</view>
<view class="link-btn" bind:tap="gotoUser" data-id="{{ item.userId }}">
<text class="link-text">客户订单明细 >></text>
</view>
</view>
<!-- 手机号 + 复制 -->
<view class="row">
<text class="row-key">手机号</text>
<view class="row-val">
<text class="mono">{{ item.phoneNumber }}</text>
<text class="copy" bindtap="onCopyPhone" data-phone="{{ item.phoneNumber }}">复制</text>
</view>
</view>
<!-- 客户数 + 抽成比例(徽章) -->
<view class="chips">
<view class="chip">客户数:{{ item.empCount }}</view>
<view class="chip">比例:{{ item.ratePercent }}%</view>
</view>
<!-- 业绩九宫格 -->
<view class="grid">
<view class="grid-item">
<text class="gi-label">下单量</text>
<text class="gi-value">{{ item.orderCount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">总订单</text>
<text class="gi-value money">¥{{ item.totalAmount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">净成交</text>
<text class="gi-value money">¥{{ item.netAmount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">待释放</text>
<text class="gi-value money">¥{{ item.toRelease }}</text>
</view>
<view class="grid-item">
<text class="gi-label">可结算</text>
<text class="gi-value">{{ item.toSettle }}</text>
</view>
<view class="grid-item">
<text class="gi-label">已结算</text>
<text class="gi-value money">¥{{ item.settled }}</text>
</view>
<view class="grid-item">
<text class="gi-label">推广数</text>
<text class="gi-value">{{ item.promoCount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">退款</text>
<text class="gi-value money">¥{{ item.refunded }}</text>
</view>
<view class="grid-item">
<text class="gi-label">已回退</text>
<text class="gi-value money">¥0</text>
</view>
</view>
</view>
</block>
</scroll-view>
</view>

View File

@ -0,0 +1,176 @@
/* 基础 */
.page {
background: #fefbf6; /* 暖米黄背景 */
min-height: 100vh;
display: flex;
flex-direction: column;
}
.page-title { padding: 24rpx 24rpx 0; }
.title {
color: #ff8a00; /* 主标题亮橙 */
font-size: 40rpx;
font-weight: 700;
}
.content {
flex: 1;
padding: 24rpx;
box-sizing: border-box;
}
/* 隐藏滚动条 */
.no-scrollbar::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* 卡片 */
.card {
background: #ffffff;
border-radius: 18rpx;
padding: 24rpx;
border: 2rpx solid #ffeaa7; /* 浅橙描边 */
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.05);
}
.card + .card { margin-top: 20rpx; }
/* 表单 */
.form-card .field + .field { margin-top: 20rpx; }
.field-label {
font-size: 28rpx;
color: #555555;
margin-bottom: 12rpx;
display: block;
}
.input-box {
background: #ffffff;
border: 2rpx solid #ffeaa7;
border-radius: 12rpx;
padding: 0 20rpx;
height: 84rpx;
display: flex;
align-items: center;
}
.input {
flex: 1;
font-size: 28rpx;
color: #1f1f1f;
}
.ph { color: #b8b8b8; }
/* 按钮 */
.btn {
height: 88rpx;
border-radius: 999rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
font-weight: 600;
margin-top: 24rpx;
}
.btn-primary {
background: linear-gradient(180deg, #ffa400 0%, #ff8a00 100%);
color: #ffffff;
box-shadow: 0 6rpx 14rpx rgba(255,138,0,0.30);
}
/* 空状态 */
.empty {
padding: 120rpx 0 40rpx;
display: flex;
flex-direction: column;
align-items: center;
color: #999999;
}
.empty-img { width: 300rpx; height: 300rpx; margin-bottom: 16rpx; }
.empty-text { font-size: 26rpx; }
/* 列表头部行 */
.topline {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
margin-bottom: 8rpx;
}
.id-and-name {
display: flex;
align-items: baseline;
gap: 16rpx;
flex-wrap: wrap;
}
.no { font-size: 24rpx; color: #666666; }
.name { font-size: 28rpx; color: #1f1f1f; font-weight: 600; }
.link-btn {
height: 56rpx;
padding: 0 18rpx;
border-radius: 999rpx;
background: #fff6e6;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1rpx solid #ffd6b3;
}
.link-text { font-size: 24rpx; color: #ff8a00; font-weight: 600; }
/* 键值行 */
.row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12rpx 0;
border-top: 1rpx dashed #f0f0f0;
}
.row-key { font-size: 26rpx; color: #666666; }
.row-val { display: flex; align-items: center; gap: 16rpx; }
.mono { font-size: 28rpx; color: #1f1f1f; }
.copy {
font-size: 24rpx;
color: #ff8a00;
padding: 8rpx 14rpx;
border-radius: 12rpx;
background: #fff4f2;
border: 1rpx solid #ffd6cc;
}
/* 徽章 Chips */
.chips { display: flex; gap: 12rpx; flex-wrap: wrap; margin: 12rpx 0 4rpx; }
.chip {
padding: 10rpx 16rpx;
background: #f7f9fc;
color: #3d4f6e;
border: 1rpx solid #e6edf7;
border-radius: 12rpx;
font-size: 24rpx;
}
/* 九宫格 */
.grid {
margin-top: 8rpx;
margin-left: -10rpx;
margin-right: -10rpx;
display: flex;
flex-wrap: wrap;
}
.grid-item {
width: 33.3333%;
padding: 14rpx 10rpx;
box-sizing: border-box;
}
.gi-label { font-size: 24rpx; color: #666666; }
.gi-value {
display: block;
margin-top: 10rpx;
font-size: 30rpx;
font-weight: 700;
color: #1f1f1f;
}
.gi-value.money { color: #ff8a00; }
/* 小屏两列适配 */
@media (max-width: 360px) {
.grid-item { width: 50%; }
}

View File

@ -0,0 +1,100 @@
import { baseUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
// pages/dashboardModule/supervisorPerformance/supervisorPerformance.js
Page({
data: {
nickName: '', // 主管名称
phoneNumber: '', // 手机号
showList: false, // 是否显示绩效列表
performanceList: [], // 绩效列表数据,含 ratePercent 字段
userRole: '', // 用户角色
id: 0,
},
onNameInput(e) {
this.setData({ nickName: e.detail.value });
},
onPhoneInput(e) {
this.setData({ phoneNumber: e.detail.value });
},
onSearch() {
const nickName = this.data.nickName.trim();
const phoneNumber = this.data.phoneNumber.trim();
wx.request({
url: baseUrl + '/perform/query/supervisor',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: {
nickName: nickName,
phoneNumber: phoneNumber,
},
success: (res) => {
console.log('--->后端返回记录',res.data);
if (res.data.code === 1) {
// 预处理:给每条记录加一个 ratePercent 字段
const listWithRate = res.data.data.map(item => {
const ratePercent = (item.rakeRewardsRate * 100).toFixed(2);
return Object.assign({}, item, { ratePercent });
});
// 分两次 setData不链
this.setData({ performanceList: listWithRate });
this.setData({ showList: true });
} else {
notLogin(res.data.message)
}
},
fail: () => {
wx.showToast({ title: '网络错误', icon: 'none' });
}
});
},
onCopyPhone(e) {
const phone = e.currentTarget.dataset.phone;
wx.setClipboardData({
data: phone,
success() {
wx.showToast({ title: '手机号已复制', icon: 'success' });
}
});
},
onLoad(options) {
console.log('--->',options);
this.setData({
userRole: options.role,
id: options.id,
})
let showRole = '';
switch (options.role) {
case 'manager':
showRole = '主管';
break;
case 'supervisor':
showRole = '员工';
break;
}
this.setData({ showRole });
this.onSearch()
},
onPullDownRefresh() {
this.onSearch()
wx.stopPullDownRefresh();
},
changeStaff(e) {
const { id } = e.currentTarget.dataset;
console.log(id)
wx.navigateTo({
url: `/pages/dashboardModule/staffPerformance/staffPerformance?supId=${id}`,
})
},
});

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -0,0 +1,128 @@
<!-- pages/dashboardModule/supervisorPerformance/supervisorPerformance.wxml -->
<view class="page">
<!-- 标题 -->
<view class="page-title">
<text class="title">{{ showRole }}业绩报表</text>
</view>
<scroll-view scroll-y class="content no-scrollbar">
<!-- 搜索表单 -->
<view class="card form-card">
<!-- 主管名称 -->
<view class="field">
<text class="field-label">{{ showRole }}名称</text>
<view class="input-box">
<input
class="input"
placeholder="请输入{{ showRole }}名称"
placeholder-class="ph"
bindinput="onNameInput"
value="{{ nickName }}"
/>
</view>
</view>
<!-- 手机号 -->
<view class="field">
<text class="field-label">手机号</text>
<view class="input-box">
<input
class="input"
placeholder="请输入手机号"
placeholder-class="ph"
bindinput="onPhoneInput"
value="{{ phoneNumber }}"
type="number"
maxlength="11"
/>
</view>
</view>
<!-- 搜索按钮 -->
<view class="btn btn-primary" bindtap="onSearch">搜索</view>
</view>
<!-- 业绩列表(按需显示) -->
<block wx:if="{{ showList }}">
<!-- 空状态(可选) -->
<view wx:if="{{ !performanceList || performanceList.length === 0 }}" class="empty">
<image class="empty-img" src="/assets/empty-list.png" mode="aspectFit" />
<text class="empty-text">暂无数据</text>
</view>
<!-- 列表卡片 -->
<view wx:for="{{ performanceList }}"
wx:for-item="item"
wx:for-index="index"
wx:key="item.id"
class="card perf-card">
<!-- 顶部:编号 + 主管 + 跳转员工绩效 -->
<view class="topline">
<view class="id-and-name">
<text class="no">编号:{{ index + 1 }}</text>
<text class="name">主管:{{ item.nickName }}</text>
</view>
<view class="link-btn" bind:tap="changeStaff" data-id="{{ item.userId }}">
<text class="link-text">员工绩效排名 >></text>
</view>
</view>
<!-- 手机号 + 复制 -->
<view class="row">
<text class="row-key">手机号</text>
<view class="row-val">
<text class="mono">{{ item.phoneNumber }}</text>
<text class="copy" bindtap="onCopyPhone" data-phone="{{ item.phoneNumber }}">复制</text>
</view>
</view>
<!-- 员工数 + 抽成比例(徽标 chip -->
<view class="chips">
<view class="chip">员工数:{{ item.empCount }}</view>
<view class="chip">比例:{{ item.ratePercent }}%</view>
</view>
<!-- 业绩九宫格 -->
<view class="grid">
<view class="grid-item">
<text class="gi-label">下单量</text>
<text class="gi-value">{{ item.orderCount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">总订单</text>
<text class="gi-value">¥{{ item.totalAmount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">净成交</text>
<text class="gi-value">¥{{ item.netAmount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">待释放</text>
<text class="gi-value">¥{{ item.toRelease }}</text>
</view>
<view class="grid-item">
<text class="gi-label">可结算</text>
<text class="gi-value">{{ item.toSettle }}</text>
</view>
<view class="grid-item">
<text class="gi-label">已结算</text>
<text class="gi-value">¥{{ item.settled }}</text>
</view>
<view class="grid-item">
<text class="gi-label">推广数</text>
<text class="gi-value">{{ item.promoCount }}</text>
</view>
<view class="grid-item">
<text class="gi-label">退款</text>
<text class="gi-value">¥{{ item.refunded }}</text>
</view>
<view class="grid-item">
<text class="gi-label">已回退</text>
<text class="gi-value">¥0</text>
</view>
</view>
</view>
</block>
</scroll-view>
</view>

View File

@ -0,0 +1,235 @@
/* ===== 页面与滚动 ===== */
.page {
background: #fefbf6;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.page-title {
padding: 24rpx 24rpx 0;
}
.title {
color: #ff8a00; /* 主标题亮橙 */
font-size: 40rpx;
font-weight: 700;
}
.content {
flex: 1;
padding: 24rpx;
box-sizing: border-box;
}
.no-scrollbar::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
/* ===== 卡片通用 ===== */
.card {
background: #ffffff;
border-radius: 18rpx;
padding: 24rpx;
border: 2rpx solid #ffeaa7; /* 浅橙描边 */
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.05);
}
.card + .card { margin-top: 20rpx; }
/* ===== 表单 ===== */
.form-card .field + .field { margin-top: 20rpx; }
.field-label {
font-size: 28rpx;
color: #555555;
margin-bottom: 12rpx;
display: block;
}
.input-box {
background: #ffffff;
border: 2rpx solid #ffeaa7;
border-radius: 12rpx;
padding: 0 20rpx;
height: 84rpx;
display: flex;
align-items: center;
}
.input {
flex: 1;
font-size: 28rpx;
color: #1f1f1f;
}
.ph {
color: #b8b8b8;
}
/* 按钮 */
.btn {
height: 88rpx;
border-radius: 999rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
font-weight: 600;
margin-top: 24rpx;
}
.btn-primary {
background: linear-gradient(180deg, #ffa400 0%, #ff8a00 100%);
color: #ffffff;
box-shadow: 0 6rpx 14rpx rgba(255, 138, 0, 0.30);
}
/* ===== 空状态 ===== */
.empty {
padding: 120rpx 0 40rpx;
display: flex;
flex-direction: column;
align-items: center;
color: #999999;
}
.empty-img { width: 300rpx; height: 300rpx; margin-bottom: 16rpx; }
.empty-text { font-size: 26rpx; }
/* ===== 业绩卡片 ===== */
.topline {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
margin-bottom: 8rpx;
}
.id-and-name {
display: flex;
align-items: baseline;
gap: 16rpx;
flex-wrap: wrap;
}
.no {
font-size: 24rpx;
color: #666666;
}
.name {
font-size: 28rpx;
color: #1f1f1f;
font-weight: 600;
}
.link-btn {
height: 56rpx;
padding: 0 18rpx;
border-radius: 999rpx;
background: #fff6e6;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1rpx solid #ffd6b3;
}
.link-text {
font-size: 24rpx;
color: #ff8a00;
font-weight: 600;
}
/* 行:键值对 */
.row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12rpx 0;
border-top: 1rpx dashed #f0f0f0;
}
.row-key {
font-size: 26rpx;
color: #666666;
}
.row-val {
display: flex;
align-items: center;
gap: 16rpx;
}
.mono {
font-size: 28rpx;
color: #1f1f1f;
}
.copy {
font-size: 24rpx;
color: #ff8a00;
padding: 8rpx 14rpx;
border-radius: 12rpx;
background: #fff4f2;
border: 1rpx solid #ffd6cc;
}
/* 徽标 chips */
.chips {
display: flex;
gap: 12rpx;
flex-wrap: wrap;
margin: 12rpx 0 4rpx;
}
.chip {
padding: 10rpx 16rpx;
background: #f7f9fc;
color: #3d4f6e;
border: 1rpx solid #e6edf7;
border-radius: 12rpx;
font-size: 24rpx;
}
/* 九宫格3 列自适应 */
.grid {
margin-top: 8rpx;
margin-left: -10rpx;
margin-right: -10rpx;
display: flex;
flex-wrap: wrap;
}
.grid-item {
width: 33.3333%;
padding: 14rpx 10rpx;
box-sizing: border-box;
}
.gi-label {
font-size: 24rpx;
color: #666666;
}
.gi-value {
display: block;
margin-top: 10rpx;
font-size: 30rpx;
font-weight: 700;
color: #1f1f1f;
}
/* 金额类,用主题橙强调 */
.grid-item:nth-child(2) .gi-value,
.grid-item:nth-child(3) .gi-value,
.grid-item:nth-child(4) .gi-value,
.grid-item:nth-child(6) .gi-value,
.grid-item:nth-child(8) .gi-value,
.grid-item:nth-child(9) .gi-value {
color: #ff8a00;
}
/* 小屏两列适配 */
@media (max-width: 360px) {
.grid-item { width: 50%; }
}

View File

@ -0,0 +1,111 @@
import { baseUrl } from "../../../request";
const { notLogin } = require('../../../utils/util')
// pages/dashboardModule/userOrderPerformance/userOrderPerformance.js
Page({
data: {
orderNumber: '', // 双向绑定的输入框内容
staffUserId: 0, // 后期改为动态注入
OrderItems: [] // 接口返回的订单列表
},
onLoad(options) {
console.log('options-->',options);
this.setData({
staffUserId: options.userId
})
this.searchOrderByStaffId()
},
onPullDownRefresh() {
this.searchOrderByStaffId()
wx.stopPullDownRefresh();
},
// 输入框内容变化
onOrderNumberInput(e) {
this.setData({
orderNumber: e.detail.value.trim()
});
},
// 点击搜索按钮
searchOrder() {
const { orderNumber, staffUserId } = this.data;
// 简单校验:非空
// if (!orderNumber) {
// return wx.showToast({
// title: '请输入订单号',
// icon: 'none'
// });
// }
// 发起 POST 请求
wx.request({
url: baseUrl + '/perform/query/user',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: {
orderNumber,
staffUserId
},
success: (res) => {
if (res.data.code === 1) {
// 更新列表
this.setData({
OrderItems: res.data.data
});
} else {
wx.showToast({
title: res.data.message || '未找到订单',
icon: 'none'
});
this.setData({ OrderItems: [] });
}
},
fail: () => {
wx.showToast({
title: '请求失败,请稍后重试',
icon: 'none'
});
}
});
},
// 根据上级订单搜索
searchOrderByStaffId() {
const { staffUserId } = this.data;
// 发起 POST 请求
wx.request({
url: baseUrl + '/perform/query/user',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: {
staffUserId
},
success: (res) => {
if (res.data.code === 1) {
// 更新列表
this.setData({
OrderItems: res.data.data
});
} else {
this.setData({ OrderItems: [] });
notLogin(res.data.message)
}
},
fail: () => {
wx.showToast({
title: '请求失败,请稍后重试',
icon: 'none'
});
}
});
}
});

View File

@ -0,0 +1,4 @@
{
"usingComponents": {},
"enablePullDownRefresh": true
}

View File

@ -0,0 +1,92 @@
<!-- pages/dashboardModule/userOrderPerformance/userOrderPerformance.wxml -->
<view class="page">
<!-- 标题 -->
<view class="page-title">
<text class="title">客户订单明细</text>
</view>
<scroll-view scroll-y class="content no-scrollbar">
<!-- 搜索表单 -->
<view class="card form-card">
<view class="field">
<text class="field-label">订单号</text>
<view class="input-box">
<input
class="input"
placeholder="请输入订单号"
placeholder-class="ph"
value="{{ orderNumber }}"
type="number"
bindinput="onOrderNumberInput"
/>
</view>
</view>
<view class="btn btn-primary" bindtap="searchOrder">搜索</view>
</view>
<!-- 结果列表 -->
<view class="result-wrap">
<!-- 有数据 -->
<block wx:if="{{ OrderItems.length }}">
<view
wx:for="{{ OrderItems }}"
wx:for-item="item"
wx:for-index="index"
wx:key="id"
class="card order-card"
>
<!-- 顶部:订单号 + 状态徽标 -->
<view class="topline">
<view class="row-left">
<text class="label">订单号</text>
<text class="mono">{{ item.orderNumber }}</text>
</view>
<view class="badge {{ item.orderStatus === '待支付' ? 'badge-pending' : (item.orderStatus === '已支付' || item.orderStatus === '交易成功' ? 'badge-success' : 'badge-default') }}">
<text class="badge-text">{{ item.orderStatus }}</text>
</view>
</view>
<!-- 键值对信息 -->
<view class="kv">
<text class="kv-key">用户</text>
<text class="kv-val">{{ item.nickName }}</text>
</view>
<view class="kv">
<text class="kv-key">手机号</text>
<text class="kv-val">{{ item.phoneNumber }}</text>
</view>
<view class="kv">
<text class="kv-key">金额</text>
<text class="kv-val money">¥{{ item.totalAmount }}</text>
</view>
<view class="kv">
<text class="kv-key">抽成</text>
<text class="kv-val">主管:{{ item.firstRate * 100 }}%,员工:{{ item.secondRate * 100 }}%</text>
</view>
<view class="kv">
<text class="kv-key">奖励</text>
<text class="kv-val">主管:¥{{ item.firstReward }},员工:¥{{ item.secondReward }}</text>
</view>
<view class="kv">
<text class="kv-key">提成状态</text>
<text class="kv-val">{{ item.commissionStatus }}</text>
</view>
</view>
</block>
<!-- 无数据 -->
<block wx:else>
<view class="empty">
<image class="empty-img" src="/assets/empty-list.png" mode="aspectFit" />
<text class="empty-text">暂无数据</text>
</view>
</block>
</view>
</scroll-view>
</view>

View File

@ -0,0 +1,133 @@
/* ===== 页面与滚动 ===== */
.page {
background: #fefbf6; /* 与你项目的暖米黄保持一致 */
min-height: 100vh;
display: flex;
flex-direction: column;
}
.page-title { padding: 24rpx 24rpx 0; }
.title {
color: #ff8a00; /* 亮橙主色 */
font-size: 40rpx;
font-weight: 700;
}
.content {
flex: 1;
padding: 24rpx;
box-sizing: border-box;
}
.no-scrollbar::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* ===== 卡片 ===== */
.card {
background: #ffffff;
border-radius: 18rpx;
padding: 24rpx;
border: 2rpx solid #ffeaa7; /* 浅橙描边,延续你原风格 */
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.05);
}
.card + .card { margin-top: 20rpx; }
/* ===== 表单 ===== */
.form-card .field + .field { margin-top: 20rpx; }
.field-label {
font-size: 28rpx;
color: #555555;
margin-bottom: 12rpx;
display: block;
}
.input-box {
height: 84rpx;
border-radius: 12rpx;
border: 2rpx solid #ffeaa7;
background: #ffffff;
padding: 0 20rpx;
display: flex;
align-items: center;
}
.input {
flex: 1;
font-size: 28rpx;
color: #1f1f1f;
}
.ph { color: #b8b8b8; }
.btn {
height: 88rpx;
border-radius: 999rpx;
margin-top: 24rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
font-weight: 600;
}
.btn-primary {
background: linear-gradient(180deg, #ffa400 0%, #ff8a00 100%);
color: #ffffff;
box-shadow: 0 6rpx 14rpx rgba(255,138,0,0.30);
}
/* ===== 列表容器 ===== */
.result-wrap { margin-top: 20rpx; }
/* 顶部行:订单号 + 状态徽标 */
.topline {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
margin-bottom: 6rpx;
}
.row-left {
display: flex;
align-items: baseline;
gap: 12rpx;
flex-wrap: wrap;
}
.label { font-size: 26rpx; color: #666666; }
.mono { font-size: 28rpx; color: #1f1f1f; }
.badge {
height: 40rpx;
padding: 0 16rpx;
border-radius: 999rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.badge-text { font-size: 22rpx; font-weight: 600; }
.badge-pending{ background: #fff6e6; color: #ff8d1a; border: 1rpx solid #ffd6b3; }
.badge-success{ background: #e9fbef; color: #12b05b; border: 1rpx solid #b9f0cf; }
.badge-default{ background: #f0f0f0; color: #666666; border: 1rpx solid #e6e6e6; }
/* 键值行 */
.kv {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12rpx 0;
border-top: 1rpx dashed #f0f0f0;
}
.kv:first-of-type { border-top: 0; }
.kv-key { font-size: 26rpx; color: #666666; }
.kv-val {
font-size: 28rpx;
color: #1f1f1f;
text-align: right;
max-width: 70%;
word-break: break-all;
}
.money { color: #ff8a00; font-weight: 700; }
/* 空状态 */
.empty {
padding: 120rpx 0 40rpx;
display: flex;
flex-direction: column;
align-items: center;
color: #999999;
}
.empty-img { width: 300rpx; height: 300rpx; margin-bottom: 16rpx; }
.empty-text { font-size: 26rpx; }

View File

@ -0,0 +1,224 @@
const { baseUrl } = require('../../../request');
const { validate } = require('../../../utils/validate');
Page({
data: {
name: '',
phone: '',
code: '', // 验证码
idcard: '', // 身份证号
codeSent: false,
countdown: 0, // 剩余秒数
codeButtonText: '获取验证码',
_timer: null,
isUploading: false,
resumeUploaded: false,
resumeFilePath: '',
fileCode: '', // 上传文件后端返回的码
credential: '', // 用户申请后的唯一凭证,用于查询用户是否审核通过
},
onInput(e) {
const field = e.currentTarget.dataset.field;
this.setData({
[field]: e.detail.value
});
},
// 获取验证码(仅校验手机号)
getSmsCode() {
const { phone } = this.data;
// 1. 非空校验
if (!validate(this.data, { phone: '请输入手机号' })) {
return;
}
// 2. 格式校验
if (!/^1\d{10}$/.test(phone)) {
return wx.showToast({ title: '手机号格式不正确', icon: 'none' });
}
// 3. 发送验证码请求
wx.request({
url: baseUrl + '/userInfo/code/register',
method: 'POST',
data: {
phoneNumber: phone,
userRole: 'staff'
},
success: (res) => {
console.log('验证码发送--->',res.data);
if (res.data.code === 1) {
wx.showToast({ title: '验证码已发送', icon: 'none' });
this._startCountdown(60);
} else {
wx.showToast({ title: res.data.message, icon: 'none' });
}
},
fail: () => {
wx.showToast({ title: '发送失败,请重试', icon: 'none' });
}
});
},
// 开始倒计时
_startCountdown(seconds) {
this.setData({
countdown: seconds,
codeButtonText: `${seconds}s后重试`
});
// 如果已有定时器,不重复创建
if (this.data._timer) return;
this.data._timer = setInterval(() => {
const cd = this.data.countdown - 1;
if (cd <= 0) {
this._clearTimer();
this.setData({
countdown: 0,
codeButtonText: '获取验证码'
});
} else {
this.setData({
countdown: cd,
codeButtonText: `${cd}s后重试`
});
}
}, 1000);
},
// 清除倒计时定时器
_clearTimer() {
if (this.data._timer) {
clearInterval(this.data._timer);
this.data._timer = null;
}
},
// 选择并上传简历
chooseResume() {
if (this.data.resumeUploaded) return;
wx.chooseMessageFile({
count: 1,
type: 'file',
success: res => {
const file = res.tempFiles[0];
this.uploadResume(file);
}
});
},
// 上传简历
uploadResume(file) {
this.setData({ isUploading: true });
wx.uploadFile({
url: baseUrl + '/file/upload',
method: 'POST',
name: 'file',
header : {
Authorization: wx.getStorageSync('token'),
},
formData: {
biz: 'default', // 传 biz 文本字段
},
filePath: file.path,
success: res => {
console.log('简历上传后端返回--->',JSON.parse(res.data));
const data = JSON.parse(res.data);
console.log('后端返回文件码--->',data.data);
if (data.code === 1) {
wx.showToast({ title: '上传成功', icon: 'success' });
this.setData({
isUploading: false,
resumeUploaded: true,
resumeFilePath: file.path,
fileCode: data.data
});
} else {
wx.showToast({ title: data.message || '上传失败', icon: 'none' });
this.setData({ isUploading: false });
}
},
fail: () => {
wx.showToast({ title: '上传失败,请重试', icon: 'none' });
this.setData({ isUploading: false });
}
});
},
// 提交表单
handleSubmit() {
const { name, phone, code, idcard, fileCode } = this.data;
// 校验用户是否填写所有必要信息
if (!name || !phone || !code || !idcard || !fileCode) {
wx.showToast({ title: '请填写所有信息', icon: 'none' });
return;
}
// 姓名只能中文或英文
if (!/^[\u4e00-\u9fa5A-Za-z]+$/.test(name)) {
wx.showToast({ title: '姓名只能为中英文', icon: 'none' });
return;
}
// 校验身份证号
const idCardReg = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
if (!idCardReg.test(idcard)) {
wx.showToast({
title: '身份证号格式不正确',
icon: 'none'
})
return ;
}
// 提交表单数据到后端
wx.request({
url: baseUrl + '/advancementApply/add',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: {
name: name,
phone: phone,
verificationCode: code,
idCard: idcard,
resume: fileCode
},
success: res => {
console.log('后端返回的申请---->', res);
if (res.data.code === 1) {
wx.showToast({ title: '提交成功', icon: 'success' });
// 清空表单内容
this.setData({
name: '',
phone: '',
code: '',
idcard: '',
fileCode: '',
resumeUploaded: false, // 重置简历上传状态
resumeFilePath: '', // 清空简历文件路径
credential: '' // 清空凭证
});
} else {
wx.showToast({ title: res.data.message, icon: 'none' });
}
}
});
},
// 跳转申请须知
gotoNotice() {
wx.navigateTo({
url: '/pages/loginModule/employeeAccountNotice/employeeAccountNotice',
})
},
// 跳转我的申请记录
gotoQuery() {
wx.navigateTo({
url: '/pages/loginModule/employeeApplyQuery/employeeApplyQuery',
})
},
});

View File

@ -0,0 +1,108 @@
<view class="page">
<!-- 遮罩层(上传时显示) -->
<view wx:if="{{isUploading}}" class="mask">
<text class="loading-text">上传中...</text>
</view>
<!-- 顶部 Logo / 标题 -->
<image class="logo" src="/static/logo.jpg" mode="aspectFit" />
<text class="page-title">员工申请 - 丁香校园</text>
<!-- 主卡片 -->
<view class="card">
<!-- 标题 + 须知入口 -->
<view class="card-head">
<text class="card-title">员工账号申请</text>
<view class="head-link" bind:tap="gotoNotice">
<text class="head-link-text">员工账号申请须知</text>
<image class="head-link-icon" src="./images/right.png" mode="aspectFit" />
</view>
</view>
<!-- 表单 -->
<view class="form">
<!-- 姓名 -->
<view class="field">
<input
class="field-input"
placeholder="请输入姓名"
placeholder-class="ph"
maxlength="8"
bindinput="onInput"
data-field="name"
value="{{name}}"
/>
</view>
<!-- 手机号 -->
<view class="field">
<input
class="field-input"
placeholder="请输入手机号"
placeholder-class="ph"
maxlength="11"
type="number"
bindinput="onInput"
data-field="phone"
value="{{phone}}"
/>
</view>
<!-- 验证码 + 发送 -->
<view class="field field-row">
<input
class="field-input flex-1"
placeholder="请输入验证码"
placeholder-class="ph"
type="number"
maxlength="6"
bindinput="onInput"
data-field="code"
value="{{code}}"
/>
<view
class="code-btn"
bindtap="getSmsCode"
>
<text class="code-btn-text">{{ codeButtonText }}</text>
</view>
</view>
<!-- 身份证号 -->
<view class="field">
<input
class="field-input"
placeholder="请输入身份证号"
placeholder-class="ph"
type="idcard"
maxlength="18"
bindinput="onInput"
data-field="idcard"
value="{{idcard}}"
/>
</view>
<!-- 上传简历 -->
<view class="upload-box" bindtap="chooseResume">
<image class="upload-icon" src="./images/resume.png" mode="aspectFit" />
<text class="{{ resumeUploaded ? 'upload-success-text' : 'upload-tip' }}">{{ resumeUploaded ? '简历上传成功!' : '点击上传简历' }}
</text>
</view>
<!-- 提交按钮 -->
<view class="btn-primary" bindtap="handleSubmit">
<text class="btn-primary-text">提交申请</text>
</view>
</view>
<!-- 我的申请记录 -->
<view class="record" bind:tap="gotoQuery">
<text class="record-text">我的申请记录</text>
<image class="record-icon" src="./images/right.png" mode="aspectFit" />
</view>
</view>
</view>

View File

@ -0,0 +1,208 @@
/* ===== 页面与顶区 ===== */
.page {
box-sizing: border-box;
min-height: 100vh;
padding: 56rpx 32rpx 40rpx;
background-image: linear-gradient(180deg, #ffe3c4 0%, #fff 38%);
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.logo {
width: 180rpx;
height: 180rpx;
border-radius: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06);
}
.page-title {
margin-top: 12rpx;
font-size: 34rpx;
color: #1c2023;
font-weight: 700;
}
/* ===== 遮罩(上传中) ===== */
.mask {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.35);
backdrop-filter: blur(2rpx);
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
}
.loading-text {
padding: 20rpx 28rpx;
background: #000000cc;
color: #fff;
border-radius: 16rpx;
font-size: 28rpx;
}
/* ===== 主卡片 ===== */
.card {
width: 100%;
margin-top: 24rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 12rpx 36rpx rgba(0,0,0,0.08);
padding: 24rpx 24rpx 16rpx;
}
.card-head {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 12rpx;
border-bottom: 1rpx solid #f1f1f1;
}
.card-title {
font-size: 30rpx;
font-weight: 700;
color: #1c2023;
}
/* 须知入口 */
.head-link {
display: flex;
align-items: center;
gap: 8rpx;
}
.head-link-icon {
width: 28rpx;
height: 28rpx;
}
.head-link-text {
font-size: 26rpx;
color: #ff8d1a;
}
/* ===== 表单 ===== */
.form { padding-top: 16rpx; }
.field {
background: #fff;
border: 1rpx solid #e9e9ec;
border-radius: 16rpx;
padding: 18rpx 22rpx;
box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.04);
margin-top: 18rpx;
}
.field:focus-within {
border-color: #ff8d1a;
box-shadow: 0 10rpx 24rpx rgba(255,141,26,0.14);
}
.field-input {
width: 100%;
font-size: 30rpx;
color: #1c2023;
line-height: 44rpx;
}
.ph { color: #9aa0a6; }
/* 验证码行 */
.field-row {
display: flex;
align-items: center;
gap: 16rpx;
padding-right: 16rpx;
}
.flex-1 { flex: 1; }
.code-btn {
height: 44rpx;
padding: 0 22rpx;
background: #ff8d1a;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap;
box-shadow: 0 8rpx 18rpx rgba(255,141,26,0.25);
transition: transform .08s ease-in-out, opacity .2s;
}
.code-btn:active { transform: scale(0.98); }
.code-btn-text {
color: #fff;
font-size: 24rpx;
font-weight: 600;
}
/* ===== 上传简历 ===== */
.upload-box {
margin-top: 18rpx;
border: 1rpx dashed #ffb66a;
background: #fffaf4;
border-radius: 16rpx;
padding: 28rpx 22rpx;
display: flex;
align-items: center;
gap: 16rpx;
transition: transform .06s ease-in-out, background .2s;
}
.upload-box:active { transform: scale(0.992); }
.upload-icon {
width: 56rpx;
height: 56rpx;
}
.upload-tip {
font-size: 26rpx;
color: #666a73;
}
.upload-success-text {
font-size: 26rpx;
color: #13b26b;
font-weight: 600;
}
/* ===== 提交按钮 ===== */
.btn-primary {
margin-top: 22rpx;
height: 96rpx;
border-radius: 48rpx; /* 胶囊 */
background: linear-gradient(180deg, #ff9a2d 0%, #ff8d1a 100%);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 14rpx 28rpx rgba(255,141,26,0.28);
transition: transform .06s ease-in-out;
}
.btn-primary:active { transform: scale(0.985); }
.btn-primary-text {
color: #ffffff;
font-size: 32rpx;
font-weight: 700;
}
/* ===== 记录入口 ===== */
.record {
margin-top: 12rpx;
padding: 16rpx 8rpx 4rpx;
display: flex;
align-items: center;
gap: 10rpx;
justify-content: center;
}
.record-icon { width: 28rpx; height: 28rpx; }
.record-text { font-size: 26rpx; color: #1c2023; }
/* ===== 复用的工具类(与原项目兼容) ===== */
.flex-col { display: flex; flex-direction: column; }
.flex-row { display: flex; flex-direction: row; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.justify-center { justify-content: center; }
.self-center { align-self: center; }
.self-stretch { align-self: stretch; }
.relative { position: relative; }
.shrink-0 { flex-shrink: 0; }
.mt-15 { margin-top: 30rpx; }
.mt-21 { margin-top: 42rpx; }
.mt-28 { margin-top: 56rpx; }
.ml-16 { margin-left: 32rpx; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

View File

@ -0,0 +1,84 @@
import { baseUrl } from "../../../request";
import { decodeBase64 } from "../../../utils/decodebase64";
Page({
/**
* 页面的初始数据
*/
data: {
applyDesc: '',
},
/**
* 生命周期函数--监听页面加载
*/
getApplyDesc() {
wx.request({
url: baseUrl + '/userInfo/query/applyNotice',
method: 'POST',
success: res => {
if (res.data.code === 1) {
this.setData({ applyDesc: decodeBase64(res.data.data) })
} else {
wx.showToast({ title: res.data.message, icon: 'none' });
}
},
fail: () => {
wx.showToast({ title: '网络错误', icon: 'none' });
}
})
},
onLoad() {
this.getApplyDesc()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

View File

@ -0,0 +1,5 @@
<!--pages/loginModule/employeeAccountNotice/employeeAccountNotice.wxml-->
<view class="flex-col page">
<text class="self-center text">员工账号申请须知</text>
<rich-text nodes="{{ applyDesc }}" class="section view mt-20"></rich-text>
</view>

View File

@ -0,0 +1,27 @@
/* pages/loginModule/employeeAccountNotice/employeeAccountNotice.wxss */
.page {
padding: 65.08rpx 42.19rpx 150rpx 44.06rpx;
background-color: #ffffff;
width: 100%;
overflow: auto;
height: 100%;
}
.text {
color: #000000;
font-size: 33.75rpx;
font-weight: bold;
font-family: SourceHanSansCN;
line-height: 31.26rpx;
}
.section {
align-self: stretch;
}
.view {
background-color: #ffffff;
}
::-webkit-scrollbar {
width: 0;
height: 0;
background: transparent;
}

View File

@ -0,0 +1,146 @@
import { baseUrl } from "../../../request";
Page({
data: {
status: '', // 审核状态: 审核中、审核通过、审核失败
result: {} // 查询结果数据
},
// 输入框事件
onInput(e) {
this.setData({
inputIdCard: e.detail.value // 获取身份证输入
});
},
// 查询操作
onSearch() {
const inputIdCard = this.data.inputIdCard;
if (!inputIdCard) {
wx.showToast({
title: '请输入身份证',
icon: 'none'
});
return;
}
// 查询的接口
wx.request({
url: baseUrl + '/advancementApply/query/credential', // 替换为你的后端查询接口
method: 'POST',
data: { templateString: inputIdCard },
success: (res) => {
console.log('后端返回---->',res.data);
if (res.data.code === 1) {
// 假设返回的查询结果是以下格式
const result = res.data.data; // 获取返回的数据
// 更新审核状态和查询结果
this.setData({
status: result.reviewStatus, // 审核状态
result: {
name: result.name, // 姓名
phone: result.phone, // 手机号
idCard: result.idCard, // 身份证号
failureReason: result.rejectReason, // 失败原因
password: result.userPassword, // 密码(如果有的话)
userRole: result.userRole, // 用户级别
id: result.id
}
});
} else {
wx.showToast({
title: res.data.message,
icon: 'none'
});
}
},
fail: () => {
wx.showToast({
title: '请求失败,请重试',
icon: 'none'
});
}
});
},
// 重新申请操作
onReapply() {
wx.showToast({
title: '重新申请中...',
icon: 'none'
});
},
// 用户撤销申请
revokeApplication() {
const { id } = this.data.result
console.log('id--->',id);
wx.showModal({
title: '确认',
content: '是否撤销申请',
complete: (res) => {
if (res.cancel) {
}
if (res.confirm) {
wx.request({
url: baseUrl + '/advancementApply/modify/status',
method: 'POST',
header: {
Authorization: wx.getStorageSync('token')
},
data: {
id: id
},
success: res => {
console.log('后端返回11---->',res.data);
if (res.data.code === 1 ) {
this.setData({
status: ''
})
} else {
wx.showToast({
title: '系统错误',
})
}
}
})
}
}
})
},
// 用户去登录
gotoLogin() {
wx.navigateBack({
delta: 2
})
},
// 用户重新申请
reapply() {
wx.navigateBack({
delta: 1
})
},
copyPassword() {
const { password } = this.data.result
wx.setClipboardData({
data: password, // 要复制的内容
success(res) {
wx.showToast({
title: '已复制到剪贴板',
icon: 'success'
});
},
fail() {
wx.showToast({
title: '复制失败',
icon: 'none'
});
}
});
}
});

View File

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@ -0,0 +1,98 @@
<view class="flex-col page">
<!-- 身份证输入框 -->
<view class="flex-row items-center section">
<image class="image" src="./images/find.png" />
<input class="font text ml-5" maxlength="18" placeholder="请输入身份证查询凭证" bindinput="onInput" bindconfirm="onSearch" />
</view>
<!-- 显示查询结果 -->
<view class="flex-col mt-18">
<!-- 审核失败 -->
<view wx:if="{{status === '已拒绝'}}" class="flex-col section_2">
<view class="flex-row justify-center self-start section_3">
<image class="image_2" src="./images/flase.png" />
<text class="font text_2 ml-8">审核失败</text>
</view>
<text class="self-start font_2 text_3">姓名</text>
<text class="self-start font_3 text_4">{{result.name}}</text>
<text class="self-start font_2 text_5">手机号</text>
<text class="self-start font_4 text_6">{{result.phone}}</text>
<view class="flex-col self-stretch relative group">
<view class="self-start section_4"></view>
<view class="flex-col justify-start items-center self-stretch text-wrapper" bind:tap="reapply">
<text class="font text_9">重新申请</text>
</view>
<view class="flex-col items-start section_5 pos">
<text class="font_5 text_7">原因:</text>
<text class="font_5 text_8 mt-11">{{result.failureReason}}</text>
</view>
</view>
</view>
<!-- 审核通过 -->
<view wx:if="{{status === '已通过'}}" class="flex-col section_6 mt-18">
<view class="flex-col group_2">
<view class="flex-row justify-between group_3">
<view class="flex-row items-center section_7">
<image class="shrink-0 image_3" src="./images/current.png" />
<text class="font text_11 ml-6">审核通过</text>
</view>
<view class="flex-col justify-start items-center self-start text-wrapper_2">
<text class="text_10">员工</text>
</view>
</view>
<view class="flex-col relative mt-21">
<view class="flex-row self-stretch section_8">
<text class="font_2 text_12">姓名</text>
<text class="font_3 ml-39">{{result.name}}</text>
</view>
<view class="flex-row self-stretch section_9">
<text class="font_2">手机号</text>
<text class="font_4 text_13 ml-23">{{result.phone}}</text>
</view>
<view class="self-start section_10"></view>
<view class="flex-row justify-between items-center section_11 pos_2">
<view class="flex-row items-center">
<text class="font_2 text_14">密码</text>
<text class="font_3 text_15 ml-37">{{result.password}}</text>
</view>
<text class="font_2 text_16" bind:tap="copyPassword">复制</text>
</view>
</view>
<view class="group_4 mt-21">
<text class="font_6 text_17">温馨提示:</text>
<text class="font_6">恭喜成为本公司的推广员工,请保存以上账号密码,用于登录员工端小程序。</text>
</view>
</view>
<view class="flex-col justify-start items-center text-wrapper_3" bind:tap="gotoLogin"><text class="font text_18">去登录</text></view>
</view>
<!-- 审核中 -->
<view wx:if="{{status === '待审核'}}" class="flex-col section_12 mt-18">
<view class="flex-row justify-center items-center self-start section_13">
<image class="image" src="./images/wait.png" />
<text class="font text_19 ml-6">审核中</text>
</view>
<text class="self-start font_2 text_20">姓名</text>
<text class="self-start font_3 text_21">{{result.name}}</text>
<text class="self-start font_2 text_22">手机号</text>
<text class="self-start font_4 text_23">{{result.phone}}</text>
<!-- <text class="self-start font_2 text_24">身份证号</text>
<view class="flex-row self-stretch group_5">
<view class="shrink-0 section_14"></view>
<view class="flex-col justify-start items-start flex-1 text-wrapper_4">
<text class="text_25">{{result.idCard}}</text>
</view>
</view> -->
<view class="flex-col self-stretch group_6">
<view class="group_7">
<text class="font_6 text_26">注:</text>
<text class="font_6">每次必须通过身份证来查看申请状态。</text>
</view>
<view class="flex-col justify-start items-center text-wrapper_5 mt-14" bind:tap="revokeApplication">
<text class="font text_27">撤销申请</text>
</view>
</view>
</view>
</view>
</view>

View File

@ -0,0 +1,330 @@
.ml-5 {
margin-left: 9.38rpx;
}
.mt-11 {
margin-top: 20.63rpx;
}
.ml-39 {
margin-left: 73.13rpx;
}
.ml-23 {
margin-left: 43.13rpx;
}
.ml-37 {
margin-left: 69.38rpx;
}
.mt-21 {
margin-top: 39.38rpx;
}
.page {
padding: 45.94rpx 38.44rpx 140.91rpx;
background-color: #fafafa;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.section {
padding: 15.81rpx 13.93rpx 14.19rpx;
background-color: #ffffff;
border-radius: 93.75rpx;
border: solid 1.88rpx #e0e0e0;
}
.image {
width: 33.75rpx;
height: 33.75rpx;
}
.font {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.84rpx;
color: #ffffff;
}
.text {
color: #919191;
line-height: 27.75rpx;
width: 90%;
}
.section_2 {
padding: 33.75rpx 28.13rpx 35.63rpx;
background-color: #ffffff;
border-radius: 18.43rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.section_3 {
padding: 15rpx 0 13.13rpx;
background-color: #e53935;
border-radius: 18.75rpx;
width: 211.88rpx;
}
.image_2 {
width: 30rpx;
height: 30rpx;
}
.text_2 {
margin-right: 3.28rpx;
line-height: 28.16rpx;
}
.font_2 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.15rpx;
color: #999999;
}
.text_3 {
margin-left: 2.81rpx;
margin-top: 39rpx;
line-height: 24.21rpx;
}
.font_3 {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.84rpx;
color: #333333;
}
.text_4 {
margin-left: 4.24rpx;
margin-top: 21rpx;
}
.text_5 {
margin-left: 3.19rpx;
margin-top: 41.4rpx;
}
.font_4 {
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 24.15rpx;
color: #333333;
}
.text_6 {
margin-left: 4.52rpx;
margin-top: 24.04rpx;
line-height: 22.76rpx;
}
.group {
margin-top: 43.73rpx;
}
.section_4 {
background-color: #d32f2f;
border-radius: 9.38rpx 0rpx 0rpx 9.38rpx;
width: 13.13rpx;
height: 120rpx;
}
.text-wrapper {
margin-top: 35.63rpx;
padding: 35.57rpx 0 30.49rpx;
background-color: #e53935;
border-radius: 9.38rpx;
}
.text_9 {
line-height: 27.69rpx;
}
.section_5 {
padding: 27.81rpx 21.47rpx 24.26rpx;
background-color: #fdecea;
border-radius: 8.01rpx;
}
.pos {
position: absolute;
left: 7.5rpx;
right: 0;
top: 0;
}
.font_5 {
font-size: 26.25rpx;
font-family: AlibabaPuHuiTi;
line-height: 24.15rpx;
}
.text_7 {
color: #d32f2f;
line-height: 23.25rpx;
}
.text_8 {
color: #555555;
line-height: 24.26rpx;
}
.section_6 {
padding: 0 28.13rpx 56.25rpx;
background-color: #ffffff;
border-radius: 22.24rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.group_2 {
padding: 31.88rpx 0 54.17rpx;
}
.group_3 {
padding-left: 7.5rpx;
}
.section_7 {
padding: 11.25rpx 18.75rpx 9.38rpx;
background-color: #66bb6a;
border-radius: 18.75rpx;
height: 58.13rpx;
}
.image_3 {
width: 37.5rpx;
height: 37.5rpx;
}
.text_11 {
margin-right: 3.28rpx;
line-height: 28.16rpx;
}
.text-wrapper_2 {
padding: 11.47rpx 0 9.73rpx;
background-color: #66bb6a;
border-radius: 29.46rpx;
width: 99.38rpx;
height: 41.25rpx;
}
.text_10 {
color: #ffffff;
font-size: 22.5rpx;
font-family: SourceHanSansCN;
line-height: 20.04rpx;
}
.section_8 {
padding: 33.58rpx 27.19rpx 30.45rpx;
background-color: #f8f9fa;
border-radius: 9.38rpx;
}
.text_12 {
line-height: 24.21rpx;
}
.section_9 {
margin-top: 28.74rpx;
padding: 35.33rpx 27.56rpx 32.4rpx;
background-color: #f8f9fa;
border-radius: 9.38rpx;
}
.text_13 {
line-height: 22.76rpx;
}
.section_10 {
margin-top: 31.26rpx;
background-color: #66bb6a;
border-radius: 9.38rpx 0rpx 0rpx 9.38rpx;
width: 13.13rpx;
height: 91.88rpx;
}
.section_11 {
padding: 34.74rpx 21.62rpx 25.59rpx;
background-color: #e8f5e9;
border-radius: 9.38rpx;
}
.pos_2 {
position: absolute;
left: 5.63rpx;
right: 0;
top: 235.75rpx;
}
.text_14 {
line-height: 24.36rpx;
}
.text_15 {
line-height: 31.54rpx;
}
.text_16 {
margin-right: 7.52rpx;
color: #66bb6a;
}
.group_4 {
line-height: 31.88rpx;
}
.font_6 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 31.88rpx;
color: #999999;
}
.text_17 {
color: #66bb6a;
}
.text-wrapper_3 {
padding: 35.66rpx 0 30.39rpx;
background-color: #66bb6a;
border-radius: 9.38rpx;
}
.text_18 {
line-height: 27.69rpx;
}
.section_12 {
padding: 33.75rpx 28.13rpx 54.38rpx;
background-color: #ffffff;
border-radius: 22.24rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.section_13 {
margin-left: 7.5rpx;
padding: 13.13rpx 0 11.25rpx;
background-color: #ff8d1a;
border-radius: 18.75rpx;
width: 183.75rpx;
}
.text_19 {
line-height: 28.16rpx;
}
.text_20 {
margin-left: 2.81rpx;
margin-top: 39rpx;
line-height: 24.21rpx;
}
.text_21 {
margin-left: 4.24rpx;
margin-top: 21rpx;
}
.text_22 {
margin-left: 3.19rpx;
margin-top: 41.4rpx;
}
.text_23 {
margin-left: 4.52rpx;
margin-top: 24.04rpx;
line-height: 22.76rpx;
}
.text_24 {
margin-left: 2.98rpx;
margin-top: 39.6rpx;
line-height: 24.43rpx;
}
.group_5 {
margin-top: 20.94rpx;
}
.section_14 {
background-color: #ff8d1a;
border-radius: 9.38rpx 0rpx 0rpx 9.38rpx;
width: 13.13rpx;
height: 91.88rpx;
}
.text-wrapper_4 {
margin-left: -7.5rpx;
padding: 38.04rpx 0 32.04rpx;
background-color: #fff4e5;
border-radius: 9.19rpx;
height: 91.88rpx;
}
.text_25 {
margin-left: 25.71rpx;
color: #ff8d1a;
font-size: 30rpx;
font-family: AlimamaShuHeiTi;
line-height: 21.79rpx;
}
.group_6 {
margin-top: 40.97rpx;
}
.group_7 {
margin-left: 2.74rpx;
margin-right: 10.33rpx;
line-height: 31.88rpx;
}
.text_26 {
color: #ff8d1a;
}
.text-wrapper_5 {
padding: 35.48rpx 0 30.41rpx;
background-color: #ff8d1a;
border-radius: 9.38rpx;
}
.text_27 {
line-height: 27.86rpx;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

View File

@ -10,7 +10,15 @@ Page({
confirmPwd: '',
countdown: 0,
codeButtonText: '发送验证码',
_timer: null
_timer: null,
role: '',
},
onLoad(options) {
console.log(options);
this.setData({
role: options.role
})
},
// 手机号输入
@ -32,7 +40,7 @@ Page({
// 发送验证码
getSmsCode() {
const { phone } = this.data;
const { phone, role } = this.data;
// 1. 非空
if (!validate(this.data, { phone: '请输入手机号' })) return;
// 2. 格式
@ -43,7 +51,7 @@ Page({
wx.request({
url: baseUrl + '/userInfo/code/pwd',
method: 'POST',
data: { templateString: phone },
data: { phoneNumber: phone, userRole: role },
success: (res) => {
if (res.data.code === 1) {
wx.showToast({ title: '验证码已发送', icon: 'none' });
@ -92,7 +100,7 @@ Page({
// 重置密码
resetPassword() {
const { phone, code, newPwd, confirmPwd } = this.data;
const { phone, code, newPwd, confirmPwd, role } = this.data;
// 1. 非空校验
if (!validate(this.data, {
phone: '请输入手机号',
@ -117,7 +125,7 @@ Page({
verificationCode: code,
userPassword: newPwd,
userConfirmPassword: confirmPwd,
sourceToken: null
userRole: role
},
success: res => {
if (res.data.code === 1) {
@ -139,7 +147,7 @@ Page({
// 点击“登录账号”回登录页
gotoLogin() {
wx.navigateTo({ url: '/pages/loginModule/pwdLogin/pwdLogin' });
wx.navigateBack();
},
onUnload() {

View File

@ -1,18 +1,21 @@
<view class="flex-col page">
<image
class="self-center image"
src="./images/logo.png"
/>
<text class="self-center text">欢迎登陆—青橙校园</text>
<view class="page">
<view class="flex-col self-stretch group">
<text class="self-start font text_2">忘记密码</text>
<!-- 顶部 Logo 与标题 -->
<image class="logo" src="/static/logo.jpg" mode="aspectFit" />
<text class="page-title">欢迎登录 — 丁香校园</text>
<!-- 重置密码卡片 -->
<view class="card">
<text class="card-title">忘记密码</text>
<view class="form">
<!-- 手机号 -->
<view class="flex-col justify-start self-stretch relative section mt-20">
<view class="field">
<input
class="flex-col justify-start items-start text-wrapper view input"
class="field-input"
placeholder="请输入手机号"
placeholder-class="ph"
maxlength="11"
type="number"
model:value="{{phone}}"
@ -20,28 +23,30 @@
/>
</view>
<view class="flex-col self-stretch group_2 mt-20">
<!-- 验证码 + 发送 -->
<view class="flex-row items-center self-stretch relative section_2">
<view class="field field-row">
<input
class="flex-col justify-start items-start text-wrapper_2 view_2 input_1"
class="field-input flex-1"
placeholder="请输入验证码"
placeholder-class="ph"
maxlength="6"
type="number"
model:value="{{code}}"
bindinput="onCodeInput"
/>
<text
class="flex-col justify-start items-center shrink-0 text-wrapper_3 ml-12 text_6 send-code {{ countdown>0 ? 'disabled' : '' }}"
class="code-btn {{ countdown>0 ? 'disabled' : '' }}"
bindtap="{{ countdown>0 ? '' : 'getSmsCode' }}"
>{{ codeButtonText }}</text>
>{{ codeButtonText }}
</text>
</view>
<!-- 新密码 -->
<view class="flex-col justify-start self-stretch relative section_1 mt-22">
<view class="field">
<input
class="flex-col justify-start items-start text-wrapper text-wrapper_1 input_2"
class="field-input"
placeholder="请输入密码"
placeholder-class="ph"
password="true"
model:value="{{newPwd}}"
bindinput="onNewPwdInput"
@ -49,10 +54,11 @@
</view>
<!-- 确认密码 -->
<view class="flex-col justify-start self-stretch relative section_3 mt-22">
<view class="field field-last">
<input
class="flex-col justify-start items-start text-wrapper text-wrapper_5 input_3"
class="field-input"
placeholder="请再次输入密码"
placeholder-class="ph"
password="true"
model:value="{{confirmPwd}}"
bindinput="onConfirmPwdInput"
@ -60,17 +66,11 @@
</view>
<!-- 登录账号 -->
<text
class="self-end text_9 mt-22 link"
bindtap="gotoLogin"
>登录账号</text>
<text class="link-right" bindtap="gotoLogin">登录账号</text>
<!-- 重置密码 按钮 -->
<view
class="flex-col justify-start items-center self-stretch text-wrapper_4 mt-22 reset-button"
bindtap="resetPassword"
>
<text class="text_10">重置密码</text>
<view class="btn-primary reset-button" bindtap="resetPassword">
<text class="btn-primary-text">重置密码</text>
</view>
</view>
</view>

View File

@ -1,131 +1,141 @@
/* ===== 页面基础 ===== */
.page {
padding: 86.25rpx 46.2rpx 326.25rpx 49.89rpx;
background-color: #ffffff;
box-sizing: border-box;
min-height: 100vh;
padding: 64rpx 32rpx 48rpx;
background: #ffffff;
display: flex;
flex-direction: column;
align-items: center;
}
.logo {
width: 200rpx;
height: 200rpx;
border-radius: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06);
}
.page-title {
margin-top: 16rpx;
font-size: 36rpx;
color: #1c2023;
font-weight: 700;
}
/* ===== 卡片容器 ===== */
.card {
width: 100%;
overflow: hidden;
height: 100%;
margin-top: 28rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 10rpx 28rpx rgba(0,0,0,0.06);
padding: 28rpx;
}
.image {
width: 232.5rpx;
height: 232.5rpx;
}
.text {
margin-top: 37.8rpx;
.card-title {
font-size: 32rpx;
color: #1c2023;
font-size: 37.5rpx;
font-family: SourceHanSansCN;
line-height: 35.18rpx;
font-weight: 700;
padding-bottom: 12rpx;
border-bottom: 1rpx solid #f1f1f1;
}
.group {
margin-top: 86.14rpx;
/* ===== 表单 ===== */
.form { padding-top: 20rpx; }
.field {
background: #fff;
border: 1rpx solid #e9e9ec;
border-radius: 16rpx;
padding: 20rpx 24rpx;
box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.04);
margin-top: 18rpx;
}
.font {
.field:focus-within {
border-color: #ff8d1a;
box-shadow: 0 8rpx 24rpx rgba(255,141,26,0.12);
}
.field-input {
width: 100%;
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.79rpx;
color: #b3b3b3;
}
.text_2 {
color: #1c2023;
line-height: 28.09rpx;
line-height: 44rpx;
}
.section {
margin-left: 2.61rpx;
margin-right: 4.42rpx;
padding: 20.63rpx 0 18.75rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 11.25rpx #00000040;
.ph { color: #9aa0a6; }
/* 输入 + 发送验证码 并排 */
.field-row {
display: flex;
align-items: center;
gap: 16rpx;
padding-right: 16rpx;
}
.text-wrapper {
margin-left: 16.88rpx;
margin-right: 16.88rpx;
.flex-1 { flex: 1; }
.field-last {
margin-bottom: 26rpx;
}
.view {
padding: 15.92rpx 0 12.64rpx;
background-color: #ffffff00;
/* ===== 发送验证码按钮(用 text 作为按钮) ===== */
.code-btn {
height: 44rpx;
padding: 0 24rpx;
background: #ff8d1a;
border-radius: 14rpx;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap;
box-shadow: 0 8rpx 18rpx rgba(255,141,26,0.25);
color: #fff;
font-size: 24rpx;
font-weight: 600;
transition: transform .08s ease-in-out, opacity .2s;
}
.group_2 {
padding-left: 2.61rpx;
.code-btn:active { transform: scale(0.98); }
.code-btn.disabled {
opacity: 0.55;
box-shadow: none;
}
.section_2 {
margin-right: 4.42rpx;
padding: 25.16rpx 16.88rpx 24.22rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
/* ===== 右侧链接 ===== */
.link-right {
margin-top: 14rpx;
font-size: 26rpx;
color: #666a73;
align-self: flex-end;
}
.text-wrapper_2 {
flex: 1 1 0;
/* ===== 主按钮 ===== */
.btn-primary {
margin-top: 28rpx;
height: 96rpx;
border-radius: 18rpx;
background: linear-gradient(180deg, #ff9a2d 0%, #ff8d1a 100%);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 14rpx 28rpx rgba(255,141,26,0.28);
transition: transform .06s ease-in-out;
}
.view_2 {
padding: 12.51rpx 0 15.96rpx;
background-color: #ffffff00;
height: 66.25rpx;
}
.text-wrapper_3 {
margin-right: 18.77rpx;
padding: 13.16rpx 0 10.93rpx;
background-color: #ff8d1a;
border-radius: 9.38rpx;
width: 157.5rpx;
height: 45rpx;
}
.text_6 {
.btn-primary:active { transform: scale(0.985); }
.btn-primary-text {
color: #ffffff;
font-size: 22.5rpx;
font-family: AlibabaPuHuiTi;
line-height: 20.91rpx;
}
.section_1 {
margin-right: 4.42rpx;
padding: 21.56rpx 0 17.81rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.text-wrapper_1 {
padding: 13.84rpx 0 14.55rpx;
background-color: #ffffff00;
}
.section_3 {
margin-right: 4.42rpx;
padding: 19.22rpx 0 20.16rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.text-wrapper_5 {
padding: 13.37rpx 0 14.87rpx;
background-color: #ffffff00;
}
.text_9 {
color: #1c2023;
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.23rpx;
}
.text-wrapper_4 {
margin-right: 4.42rpx;
padding: 36.04rpx 0 34.01rpx;
background-color: #ff8d1a;
border-radius: 9.38rpx;
}
.text_10 {
color: #ffffff;
font-size: 30rpx;
font-family: AlibabaPuHuiTi;
line-height: 27.45rpx;
}
.input {
padding: 15rpx 16.26rpx 13.13rpx 16.26rpx;
}
.input_1 {
padding: 13.13rpx 16.26rpx 16.88rpx 16.26rpx;
}
.input_2 {
padding: 13.13rpx 16.26rpx 15rpx 16.26rpx;
}
.input_3 {
padding: 13.13rpx 16.26rpx 15rpx 16.26rpx;
font-size: 32rpx;
font-weight: 700;
}
/* ===== 可选:保留一些你原先可能依赖的工具类,避免其它页面受影响 ===== */
.flex-col { display: flex; flex-direction: column; }
.flex-row { display: flex; flex-direction: row; }
.items-center { align-items: center; }
.self-center { align-self: center; }
.self-stretch { align-self: stretch; }
.self-start { align-self: flex-start; }
.relative { position: relative; }
.shrink-0 { flex-shrink: 0; }
.mt-20 { margin-top: 40rpx; }
.mt-22 { margin-top: 44rpx; }
.ml-12 { margin-left: 24rpx; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,6 +1,12 @@
// pages/login/login.js
const { baseUrl } = require('../../../request');
const { validate } = require('../../../utils/validate');
const roleMap = new Map([
['manager', '经理'],
['supervisor', '主管'],
['staff', '员工'],
['user', '用户'],
]);
Page({
data: {
@ -12,7 +18,17 @@ Page({
codeButtonText: '获取验证码',
_timer: null,
defaultType: true, //
passwordType: true
passwordType: true,
role: '', // 登录角色
showRole: '',
isShowRegister: true
},
onLoad(options) {
const role = options.role || ''
const showRole = roleMap.get(role) || ''
this.setData({ role, showRole })
if (role === 'manager') this.setData({isShowRegister: false})
},
// 切换到“密码登录”,只清空表单字段
@ -52,7 +68,7 @@ Page({
// 获取验证码(仅校验手机号)
getSmsCode() {
const { phone } = this.data;
const { phone, role } = this.data;
// 1. 非空校验
if (!validate(this.data, { phone: '请输入手机号' })) {
@ -67,8 +83,12 @@ Page({
wx.request({
url: baseUrl + '/userInfo/code/pwd',
method: 'POST',
data: { templateString: phone },
data: {
phoneNumber: phone,
userRole: role
},
success: (res) => {
console.log('验证码发送--->',res.data);
if (res.data.code === 1) {
wx.showToast({ title: '验证码已发送', icon: 'none' });
this._startCountdown(60);
@ -139,13 +159,14 @@ Page({
return;
}
const { role } = this.data
// 组装请求
const url = loginType === 'password'
? baseUrl + '/userInfo/mini/pwd/login'
: baseUrl + '/userInfo/mini/vcd/login';
const payload = loginType === 'password'
? { phoneNumber: phone, userPassword: credential }
: { phoneNumber: phone, verificationCode: credential };
? { phoneNumber: phone, userPassword: credential, userRole: role }
: { phoneNumber: phone, verificationCode: credential, userRole: role };
wx.request({
url,
@ -158,7 +179,7 @@ Page({
const token = res.data.data.token || res.data.data;
// ← 新增:将 token 存到本地缓存
wx.setStorageSync('token', token);
wx.setStorageSync('role', role)
wx.showToast({
title: '登录成功',
icon: 'success',
@ -167,7 +188,7 @@ Page({
setTimeout(() => {
wx.reLaunch({
url: '/pages/projectModule/projectList/projectList',
url: '/pages/course/homepage/homepage',
})
}, 1000); // 1000ms = 1秒
} else {
@ -183,15 +204,22 @@ Page({
});
},
// 跳转忘记密码
gotoForgetPwd() {
const { role } = this.data;
wx.navigateTo({
url: '/pages/loginModule/forgetPwd/forgetPwd',
url: `/pages/loginModule/forgetPwd/forgetPwd?role=${role}`,
})
},
// 去注册
gotoRegister() {
const { role } = this.data;
wx.navigateTo({
url: '/pages/loginModule/register/register',
url: `/pages/loginModule/register/register?role=${ role }`,
})
},
@ -200,15 +228,25 @@ Page({
this._clearTimer();
},
// 跳转用户协议
gotoAgreement() {
wx.navigateTo({
url: '/pages/loginModule/agreement/agreement',
})
},
// 跳转隐私协议
gotoPolicy() {
wx.navigateTo({
url: '/pages/loginModule/privacyPolicy/privacyPolicy',
})
},
// 跳转职工账号页面
joinUs() {
wx.navigateTo({
url: '/pages/loginModule/employeeAccountApply/employeeAccountApply',
})
},
});

View File

@ -1,88 +1,113 @@
<view class="flex-col page">
<image
class="self-center image"
src="./images/logo.png"
/>
<text class="self-center text">欢迎登陆—青橙校园</text>
<view class="flex-col self-stretch group">
<view class="page">
<!-- 切换登录方式 -->
<view class="flex-row">
<!-- 顶部 Logo -->
<image class="logo" src="/static/logo.jpg" mode="aspectFit" />
<!-- 标题与角色 -->
<view class="title-wrap">
<text class="title bold-text">欢迎登录 — 丁香校园</text>
<text class="subtitle">{{ showRole }}端)</text>
</view>
<!-- 登录卡片 -->
<view class="card">
<!-- 登录方式切换 -->
<view class="tabs">
<text
class="font switch {{loginType==='password'?'active':'inactive'}} text_2"
class="tab {{loginType==='password' ? 'active' : ''}}"
bindtap="switchToPassword"
>密码登录</text>
<text
class="font switch {{loginType==='sms'?'active':'inactive'}} text_3 ml-8"
class="tab {{loginType==='sms' ? 'active' : ''}}"
bindtap="switchToSms"
wx:if="{{ role === 'user' }}"
>验证码登录</text>
</view>
<view class="flex-col group_1 mt-20">
<!-- 表单 -->
<view class="form">
<!-- 手机号输入 -->
<view class="flex-col self-stretch">
<view class="flex-col justify-start relative section">
<!-- 手机号 -->
<view class="field">
<input
class="flex-col justify-start items-start text-wrapper view input"
class="field-input"
placeholder="请输入手机号"
placeholder-class="ph"
value="{{phone}}"
bindinput="onPhoneInput"
maxlength="11"
type="number"
model:value="{{phone}}"
bindinput="onPhoneInput"
/>
</view>
<!-- 密码 / 验证码 输入 + 获取验证码按钮 -->
<view class="flex-row items-center section_2 mt-21">
<!-- 密码 / 验证码 -->
<view class="field field-row">
<input
class="flex-col justify-start items-start text-wrapper_2 view_2 input_1"
class="field-input flex-1"
placeholder="{{ loginType==='password' ? '请输入密码' : '请输入验证码' }}"
password="{{ loginType==='password' }}"
model:value="{{credential}}"
placeholder-class="ph"
value="{{credential}}"
bindinput="onCredentialInput"
password="{{ loginType==='password' }}"
type="{{ loginType==='sms' ? 'number' : 'text' }}"
/>
<text
<!-- 验证码按钮(仅验证码登录显示) -->
<view
class="code-btn"
bindtap="getSmsCode"
wx:if="{{ loginType==='sms' }}"
class="text_6 ml-10 get-code {{ countdown>0 ? 'disabled' : '' }}"
bindtap="{{ countdown>0 ? '' : 'getSmsCode' }}"
>{{ codeButtonText }}</text>
>
<text class="code-btn-text">{{ codeButtonText }}</text>
</view>
</view>
<text class="self-end font_3 text_7" bindtap="gotoForgetPwd">忘记密码</text>
<!-- 忘记密码(仅密码登录) -->
<text
class="link-right"
bindtap="gotoForgetPwd"
wx:if="{{ loginType==='password' }}"
>忘记密码</text>
<!-- 登录按钮 -->
<view
class="flex-col justify-start items-center self-stretch text-wrapper_3 login-button"
class="btn-primary"
bindtap="onLogin"
>
<text class="text_8">登录</text>
<text class="btn-primary-text">登录</text>
</view>
<!-- 用户协议勾选 -->
<view class="flex-row items-center self-stretch group_2">
<!-- 协议 -->
<view class="agreements">
<checkbox-group bindchange="onAgreeChange">
<checkbox
class="checkbox"
value="agree"
checked="{{ isAgree }}"
bindchange="onAgreeChange"
color="#FF8D1A"
/>
</checkbox-group>
<view class="group_3 ml-12">
<text class="font_4 text_9">登录代表您已同意</text>
<text class="font_4" bind:tap="gotoAgreement">《用户协议》</text>
<text class="text_10">&</text>
<text class="font_4" bind:tap="gotoPolicy">《隐私协议》</text>
<view class="agreements-text">
<text class="muted">登录代表您已同意</text>
<text class="link" bindtap="gotoAgreement">《用户协议》</text>
<text class="muted">&</text>
<text class="link" bindtap="gotoPolicy">《隐私协议》</text>
</view>
</view>
<view class="self-center group_4">
<text class="font_3 text_11">没有账号?</text>
<text class="font_4 text_12" bindtap="gotoRegister">去注册→</text>
<!-- 去注册 -->
<view class="register" wx:if="{{isShowRegister}}">
<text class="muted">没有账号?</text>
<text class="link-strong" bindtap="gotoRegister">去注册 →</text>
</view>
</view>
</view>
<!-- 加入我们(仅 user 端) -->
<view class="cta-join" bind:tap="joinUs" wx:if="{{ role === 'user' }}">
<text class="cta-join-text">加入我们</text>
<image class="cta-join-img" src="./images/joinus.png" mode="aspectFit" />
</view>
</view>

View File

@ -1,163 +1,241 @@
/* 切换按钮样式 */
.switch {
font-size: 30rpx; /* 基础字体大小 */
font-family: SourceHanSansCN;
}
.switch.active {
font-size: 36rpx; /* 激活时更大 */
font-weight: bold; /* 加粗 */
color: #1c2023;
}
.switch.inactive {
color: #888888; /* 不活跃时灰色 */
/* ========== 基础 ========== */
.page {
box-sizing: border-box;
padding: 72rpx 32rpx 48rpx;
background-color: #ffffff;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
/* 其它原来样式保持不变 */
.mt-21 {
margin-top: 39.38rpx;
.logo {
width: 220rpx;
height: 220rpx;
border-radius: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06);
}
.page {
padding: 105rpx 45.69rpx 381.68rpx 49.76rpx;
background-color: #ffffff;
.title-wrap {
margin-top: 24rpx;
align-items: center;
text-align: center;
}
.title {
font-size: 40rpx;
line-height: 1.2;
color: #1c2023;
}
.subtitle {
margin-top: 12rpx;
font-size: 28rpx;
color: #666a73;
}
.bold-text { font-weight: 700; }
/* ========== 卡片容器 ========== */
.card {
width: 100%;
overflow: hidden;
height: 100%;
margin-top: 32rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 10rpx 28rpx rgba(0,0,0,0.06);
padding: 28rpx;
}
.image {
width: 232.5rpx;
height: 232.5rpx;
/* ========== 标签切换 ========== */
.tabs {
display: flex;
align-items: center;
gap: 32rpx;
padding: 8rpx 4rpx 20rpx;
border-bottom: 1rpx solid #f1f1f1;
}
.text {
margin-top: 35.14rpx;
.tab {
font-size: 28rpx;
color: #666a73;
padding: 8rpx 6rpx;
position: relative;
transition: color .2s, transform .2s;
}
.tab.active {
color: #1c2023;
font-size: 37.5rpx;
font-family: AlibabaPuHuiTi;
line-height: 35.21rpx;
font-weight: 700;
transform: translateY(-1rpx);
}
.group {
margin-top: 145.01rpx;
.tab.active::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -12rpx;
height: 6rpx;
background: #ff8d1a;
border-radius: 6rpx;
}
.font {
/* ========== 表单区 ========== */
.form { padding-top: 24rpx; }
.field {
background: #fff;
border: 1rpx solid #e9e9ec;
border-radius: 16rpx;
padding: 20rpx 24rpx;
box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.04);
margin-top: 20rpx;
}
.field-input {
width: 100%;
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.69rpx;
color: #1c2023;
line-height: 44rpx;
}
.text_2 {
line-height: 28.29rpx;
.field-input:focus {
outline: none;
border: none;
}
.text_3 {
line-height: 28.2rpx;
.field:focus-within {
border-color: #ff8d1a;
box-shadow: 0 8rpx 24rpx rgba(255,141,26,0.12);
}
.group_1 {
padding-left: 2.74rpx;
.ph { color: #9aa0a6; }
/* 输入+验证码并排 */
.field-row {
display: flex;
align-items: center;
gap: 16rpx;
padding-right: 16rpx;
margin-bottom: 26rpx;
}
.section {
margin-right: 4.93rpx;
padding: 20.63rpx 0 18.75rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 11.25rpx #00000040;
.flex-1 { flex: 1; }
/* 验证码按钮 */
.code-btn {
height: 44rpx;
padding: 0 24rpx;
background: #ff8d1a;
border-radius: 14rpx;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap;
box-shadow: 0 8rpx 18rpx rgba(255,141,26,0.25);
active-opacity: 0.85;
}
.text-wrapper {
margin-left: 16.88rpx;
margin-right: 16.88rpx;
.code-btn:active { transform: scale(0.98); }
.code-btn-text {
color: #fff;
font-size: 24rpx;
font-weight: 600;
}
.view {
padding: 15.92rpx 0 12.64rpx;
background-color: #ffffff00;
/* 忘记密码链接 */
.link-right {
margin-top: 16rpx;
font-size: 26rpx;
color: #666a73;
align-self: flex-end;
}
.section_2 {
margin-right: 4.93rpx;
padding: 20.63rpx 16.88rpx 18.75rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
/* 登录按钮 */
.btn-primary {
margin-top: 32rpx;
height: 96rpx;
border-radius: 18rpx;
background: linear-gradient(180deg, #ff9a2d 0%, #ff8d1a 100%);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 14rpx 28rpx rgba(255,141,26,0.28);
transition: transform .06s ease-in-out;
}
.text-wrapper_2 {
flex: 1 1 0;
}
.view_2 {
padding: 11.96rpx 0 16.43rpx;
background-color: #ffffff00;
height: 76.25rpx;
}
.text_6 {
margin-right: 14.72rpx;
color: #f7810a;
font-size: 26.25rpx;
font-family: AlibabaPuHuiTi;
line-height: 23.94rpx;
}
.get-code {
/* 可根据需求再调样式 */
}
.font_3 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.49rpx;
color: #383838;
}
.text_7 {
margin-top: 28.76rpx;
line-height: 24.36rpx;
}
.text-wrapper_3 {
margin-right: 4.93rpx;
margin-top: 46.26rpx;
padding: 36.73rpx 0 34.16rpx;
background-color: #ff8d1a;
border-radius: 9.38rpx;
}
.text_8 {
.btn-primary:active { transform: scale(0.985); }
.btn-primary-text {
color: #ffffff;
font-size: 30rpx;
font-family: AlibabaPuHuiTi;
line-height: 26.61rpx;
font-size: 32rpx;
font-weight: 700;
}
.group_2 {
margin-top: 48.75rpx;
/* 协议区 */
.agreements {
margin-top: 28rpx;
display: flex;
align-items: center;
gap: 16rpx;
}
.group_3 {
line-height: 24.49rpx;
height: 24.56rpx;
.checkbox { transform: scale(0.92); }
.agreements-text {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8rpx;
line-height: 1.4;
}
.font_4 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.49rpx;
color: #ff5e00;
.muted { color: #666a73; font-size: 26rpx; }
.link { color: #ff5e00; font-size: 26rpx; }
.link-strong { color: #ff5e00; font-size: 28rpx; font-weight: 700; }
/* 注册区 */
.register {
margin-top: 24rpx;
text-align: center;
display: flex;
justify-content: center;
gap: 8rpx;
}
.text_9 {
color: #1c2023;
line-height: 24.43rpx;
}
.text_10 {
color: #1c2023;
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 19.93rpx;
}
.group_4 {
margin-top: 43.91rpx;
line-height: 24.41rpx;
}
.text_11 {
line-height: 24.28rpx;
}
.text_12 {
line-height: 24.41rpx;
}
.input {
padding: 15rpx 16.26rpx 13.13rpx 16.26rpx;
}
.input_1 {
padding: 15rpx 16.26rpx 13.13rpx 16.26rpx;
}
.checkbox {
flex-shrink: 0;
}
.checkbox .wx-checkbox-input {
width: 37.5rpx;
height: 37.5rpx;
/* 加入我们 CTA */
.cta-join {
margin-top: 48rpx;
padding: 16rpx 22rpx;
border: 1rpx solid #ff8d1a;
border-radius: 14rpx;
display: flex;
align-items: center;
gap: 12rpx;
}
.cta-join-text { color: #ff8d1a; font-size: 28rpx; }
.cta-join-img { width: 44rpx; height: 44rpx; }
/* ========== 兼容你原先用到的类名(可选保留) ========== */
.font { font-size: 37.5rpx; color: #1c2023; }
.font_2 { font-size: 30rpx; color: #1c2023; }
.font_4 { font-size: 26rpx; color: #383838; }
.font_5 { font-size: 26rpx; color: #ff5e00; }
.toggle-text { font-size: 28rpx; transition: font-size .2s; }
.toggle-text.active { font-size: 36rpx; font-weight: 700; }
/* 简易工具类(若你全局已有可删除) */
.items-center { align-items: center; }
.self-center { align-self: center; }
.self-end { align-self: flex-end; }
.justify-evenly { justify-content: space-evenly; }
.relative { position: relative; }
.shrink-0 { flex-shrink: 0; }
.ml-2 { margin-left: 16rpx; }
.ml-8 { margin-left: 32rpx; }
.ml-12 { margin-left: 48rpx; }
.mt-12 { margin-top: 24rpx; }
.mt-20 { margin-top: 40rpx; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@ -5,13 +5,38 @@ import { validate } from "../../../utils/validate";
// pages/loginModule/register/register.js
Page({
data: {
role: '', // 用户角色
placeholder: '', // 输入框显示文本
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
console.log('options--->',options);
this.setData({
role: options.role
})
const scene = decodeURIComponent(options.scene)
if (scene !== 'undefined') {
let [key, value] = scene.split('=');
this.setData({inviteCode: value})
console.log(key, value)
if (value === 'manager') value = 'supervisor'
else if (value === 'supervisor') value = 'staff'
else if (value === 'staff') value = 'user'
this.setData({inviteCode: key, role: value})
}
if (this.data.role === 'supervisor') {
this.setData({
placeholder: '请输入学校名称'
})
} else {
this.setData({
placeholder : '请输入昵称'
})
}
},
/**
@ -29,7 +54,7 @@ Page({
},
sendSmsCode() {
const { phone } = this.data;
const { phone, role } = this.data;
if (!phone.trim()) {
wx.showToast({ title: '请输入手机号', icon: 'none' });
return;
@ -43,7 +68,8 @@ Page({
method: 'POST',
header: { 'content-type': 'application/json' },
data: {
templateString: phone
phoneNumber: phone,
userRole: role
},
success: res => {
// 假设后端返回 { success: true, ... }
@ -136,6 +162,8 @@ Page({
title: '加载中',
mask: true
})
const { role } = this.data;
const res = await requestAsync({
url: baseUrl + '/userInfo/register',
method: 'POST',
@ -145,7 +173,8 @@ Page({
phoneNumber: phone,
verificationCode: captcha,
invitationCode: inviteCode,
userPassword: password
userPassword: password,
userRole: role
}
});
console.log('注册信息---->',res.data);
@ -155,27 +184,28 @@ Page({
icon: 'success',
duration: 1000,
});
wx.hideLoading()
setTimeout(() => {
wx.navigateTo({
url: '/pages/loginModule/pwdLogin/pwdLogin',
url: `/pages/loginModule/pwdLogin/pwdLogin?role=${role}`,
success: () => {
this.setData({ nickname:'', phone:'', captcha:'', inviteCode:'', password:'', agree:false });
}
});
}, 1000);
} else {
console.log(res.data)
wx.showToast({
title: res.data.message || '注册失败',
icon: 'none'
icon: 'none',
duration: 1000
});
wx.hideLoading()
// wx.hideLoading()
}
},
gotoLogin() {
wx.navigateTo({
url: '/pages/loginModule/pwdLogin/pwdLogin',
wx.navigateBack({
delta: 1
})
},

View File

@ -1,78 +1,107 @@
<view class="flex-col page">
<image
class="self-center image"
src="./images/logo.png"
/>
<text class="self-center text">欢迎登陆—青橙校园</text>
<view class="flex-col self-stretch group">
<view class="flex-col register">
<text class="self-start font text_2">账号注册</text>
<view class="flex-col self-stretch group_6 mt-20">
<view class="flex-col">
<view class="flex-col justify-start relative section">
<input class="flex-col justify-start items-start text-wrapper_5 view input"
placeholder="请输入昵称"
maxlength="6"
<view class="page">
<!-- 顶部 Logo 与标题 -->
<image class="logo" src="/static/logo.jpg" mode="aspectFit" />
<text class="page-title">欢迎登录 — 丁香校园</text>
<!-- 注册卡片 -->
<view class="card">
<view class="card-head">
<text class="card-title">账号注册</text>
</view>
<!-- 表单 -->
<view class="form">
<!-- 昵称 -->
<view class="field">
<input
class="field-input"
placeholder="{{ placeholder }}"
placeholder-class="ph"
maxlength="18"
bindinput="onInput" data-field="nickname" value="{{nickname}}"
/>
</view>
<view class="flex-col justify-start section_1 mt-22">
<!-- 手机号 -->
<view class="field">
<input
class="flex-col justify-start items-start text-wrapper_5 text-wrapper_1 input_1"
class="field-input"
placeholder="请输入手机号"
placeholder-class="ph"
maxlength="11"
type="number"
bindinput="onInput" data-field="phone" value="{{phone}}"
/>
</view>
</view>
<view class="flex-row items-center relative section_3 mt-22">
<!-- 验证码(输入 + 发送) -->
<view class="field field-row">
<input
class="flex-col justify-start items-start text-wrapper_2 view_6 input_2"
class="field-input flex-1"
placeholder="请输入验证码"
placeholder-class="ph"
maxlength="6"
bindinput="onInput" data-field="captcha" value="{{captcha}}"
/>
<view bindtap="{{sending ? '' : 'sendSmsCode'}}" class="flex-col justify-start items-center shrink-0 text-wrapper_3 ml-18">
<text class="text_7">{{ sending ? count + 's后重发' : '发送验证码' }}</text>
<view
bindtap="{{sending ? '' : 'sendSmsCode'}}"
class="code-btn {{sending ? 'disabled' : ''}}"
>
<text class="code-btn-text">{{ sending ? count + 's后重发' : '发送验证码' }}
</text>
</view>
</view>
<view class="flex-col mt-22">
<view class="flex-col justify-start relative section_2">
<!-- 邀请码 -->
<view class="field">
<input
class="flex-col justify-start items-start text-wrapper_5 view_1 input_3"
class="field-input"
placeholder="请输入邀请码"
placeholder-class="ph"
maxlength="6"
bindinput="onInput" data-field="inviteCode" value="{{inviteCode}}"
/>
</view>
<view class="flex-col justify-start section_2 mt-22">
<input class="flex-col justify-start items-start text-wrapper_5 view_3 input_4"
<!-- 密码 -->
<view class="field">
<input
class="field-input"
placeholder="请输入密码"
placeholder-class="ph"
password="true"
maxlength="11"
maxlength="18"
bindinput="onInput" data-field="password" value="{{password}}"
/>
</view>
</view>
</view>
</view>
<view class="flex-row items-center group_1 mt-26">
<!-- 复选框 -->
<!-- 协议勾选 -->
<view class="agreements">
<checkbox-group bindchange="onCheckboxChange">
<checkbox value="agree" checked="{{agree}}" color="#FF8D1A" />
</checkbox-group>
<view class="group_2 ml-13">
<text class="font_2 text_10">我已阅读并同意</text>
<text class="font_2" bind:tap="gotoAgreement">《用户协议》</text>
<text class="text_11">&</text>
<text class="font_2" bind:tap="gotoPolicy">《隐私协议》</text>
<view class="agreements-text">
<text class="muted">我已阅读并同意</text>
<text class="link" bind:tap="gotoAgreement">《用户协议》</text>
<text class="muted">&</text>
<text class="link" bind:tap="gotoPolicy">《隐私协议》</text>
</view>
</view>
<view bindtap="onRegister" class="flex-col justify-start items-center text-wrapper_6 mt-26"><text class="font text_12">注册</text></view>
</view>
<view class="self-center group_3">
<text class="font_2 text_13">已有账号?</text>
<text bindtap="gotoLogin" class="font_2 text_14" >立即登录→</text>
<!-- 注册按钮 -->
<view class="btn-primary" bindtap="onRegister">
<text class="btn-primary-text">注册</text>
</view>
</view>
</view>
<!-- 登录引导 -->
<view class="footer-tip">
<text class="muted">已有账号?</text>
<text class="link-strong" bindtap="gotoLogin">立即登录 →</text>
</view>
</view>

View File

@ -1,172 +1,182 @@
.ml-13 {
margin-left: 24.38rpx;
}
/* ===== 基础布局 ===== */
.page {
padding: 0rpx 49.74rpx 79.82rpx 49.74rpx;
background-color: #ffffff;
box-sizing: border-box;
min-height: 100vh;
padding: 64rpx 32rpx 48rpx;
background: #ffffff;
display: flex;
flex-direction: column;
align-items: center;
}
.logo {
width: 200rpx;
height: 200rpx;
border-radius: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.06);
}
.page-title {
margin-top: 16rpx;
font-size: 36rpx;
color: #1c2023;
font-weight: 700;
}
/* ===== 卡片 ===== */
.card {
width: 100%;
overflow: hidden;
height: 100%;
margin-top: 28rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 10rpx 28rpx rgba(0,0,0,0.06);
padding: 28rpx;
}
.register {
margin-top: -30rpx;
.card-head {
padding-bottom: 12rpx;
border-bottom: 1rpx solid #f1f1f1;
}
.image {
width: 232.5rpx;
height: 232.5rpx;
}
.text {
margin-top: 37.8rpx;
.card-title {
font-size: 32rpx;
color: #1c2023;
font-size: 37.5rpx;
font-family: SourceHanSansCN;
line-height: 35.18rpx;
font-weight: 700;
}
.group {
margin-top: 86.36rpx;
.form {
padding-top: 20rpx;
}
.font {
/* ===== 表单字段 ===== */
.field {
background: #fff;
border: 1rpx solid #e9e9ec;
border-radius: 16rpx;
padding: 20rpx 24rpx;
box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.04);
margin-top: 18rpx;
}
.field:focus-within {
border-color: #ff8d1a;
box-shadow: 0 8rpx 24rpx rgba(255,141,26,0.12);
}
.field-input {
width: 100%;
font-size: 30rpx;
font-family: SourceHanSansCN;
line-height: 27.79rpx;
color: #b3b3b3;
}
.text_2 {
color: #1c2023;
line-height: 28.2rpx;
line-height: 44rpx;
}
.group_6 {
padding-left: 2.76rpx;
.ph { color: #9aa0a6; }
.field-row {
display: flex;
align-items: center;
gap: 16rpx;
padding-right: 16rpx;
}
.section {
padding: 20.63rpx 0 18.75rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 11.25rpx #00000040;
.flex-1 { flex: 1; }
/* ===== 验证码按钮 ===== */
.code-btn {
height: 44rpx;
padding: 0 24rpx;
background: #ff8d1a;
border-radius: 14rpx;
display: flex;
align-items: center;
justify-content: center;
white-space: nowrap;
box-shadow: 0 8rpx 18rpx rgba(255,141,26,0.25);
transition: transform .08s ease-in-out, opacity .2s;
}
.text-wrapper_5 {
margin-left: 16.88rpx;
margin-right: 16.88rpx;
.code-btn:active { transform: scale(0.98); }
.code-btn.disabled {
opacity: 0.55;
box-shadow: none;
}
.view {
padding: 15.92rpx 0 12.62rpx;
background-color: #ffffff00;
.code-btn-text {
color: #fff;
font-size: 24rpx;
font-weight: 600;
}
.section_1 {
padding: 20.16rpx 0 19.22rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
/* ===== 协议区 ===== */
.agreements {
margin-top: 22rpx;
display: flex;
align-items: center;
gap: 14rpx;
}
.text-wrapper_1 {
padding: 12.64rpx 0 15.92rpx;
background-color: #ffffff00;
.agreements-text {
display: flex;
align-items: center;
gap: 8rpx;
flex-wrap: wrap;
}
.section_3 {
padding: 25.63rpx 16.88rpx 28.75rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
.muted { color: #666a73; font-size: 26rpx; }
.link { color: #ff5e00; font-size: 26rpx; }
.link-strong { color: #ff5e00; font-size: 28rpx; font-weight: 700; }
/* ===== 主按钮 ===== */
.btn-primary {
margin-top: 28rpx;
height: 96rpx;
border-radius: 18rpx;
background: linear-gradient(180deg, #ff9a2d 0%, #ff8d1a 100%);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 14rpx 28rpx rgba(255,141,26,0.28);
transition: transform .06s ease-in-out;
}
.text-wrapper_2 {
flex: 1 1 0;
}
.view_6 {
padding: 16.73rpx 0 11.74rpx;
background-color: #ffffff00;
height: 66.25rpx;
}
.text-wrapper_3 {
margin-right: 15rpx;
padding: 13.16rpx 0 10.93rpx;
background-color: #ff8d1a;
border-radius: 9.38rpx;
width: 157.5rpx;
height: 45rpx;
}
.text_7 {
.btn-primary:active { transform: scale(0.985); }
.btn-primary-text {
color: #ffffff;
font-size: 22.5rpx;
font-family: AlibabaPuHuiTi;
line-height: 20.91rpx;
font-size: 32rpx;
font-weight: 700;
}
.section_2 {
padding: 20.63rpx 0 18.75rpx;
background-color: #ffffff;
border-radius: 9.38rpx;
box-shadow: 0rpx 3.75rpx 7.5rpx #00000040;
}
.view_1 {
padding: 11.7rpx 0 16.89rpx;
background-color: #ffffff00;
}
.view_3 {
padding: 11.96rpx 0 16.29rpx;
background-color: #ffffff00;
}
.group_1 {
padding: 0 2.76rpx;
}
.group_2 {
line-height: 24.56rpx;
height: 24.56rpx;
}
.font_2 {
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 24.49rpx;
color: #ff5e00;
}
.text_10 {
color: #1c2023;
line-height: 24.56rpx;
}
.text_11 {
color: #1c2023;
font-size: 26.25rpx;
font-family: SourceHanSansCN;
line-height: 19.93rpx;
}
.text-wrapper_6 {
margin-left: 2.76rpx;
padding: 37.63rpx 0 32.27rpx;
background-color: #ff8d1a;
border-radius: 9.38rpx;
}
.text_12 {
color: #ffffff;
line-height: 27.6rpx;
}
.group_3 {
margin-top: 37rpx;
line-height: 24.36rpx;
}
.text_13 {
color: #383838;
line-height: 24.28rpx;
}
.text_14 {
line-height: 24.36rpx;
}
.input {
padding: 13.13rpx 16.26rpx 15rpx 16.26rpx;
}
.input_1 {
padding: 13.13rpx 16.26rpx 15rpx 16.26rpx;
}
.input_2 {
padding: 13.13rpx 16.26rpx 15rpx 16.26rpx;
}
.input_3 {
padding: 13.13rpx 16.26rpx 15rpx 16.26rpx;
}
.input_4 {
padding: 13.13rpx 16.26rpx 15rpx 16.26rpx;
}
.checkbox {
flex-shrink: 0;
}
.checkbox .wx-checkbox-input {
width: 37.5rpx;
height: 37.5rpx;
/* ===== 底部引导 ===== */
.footer-tip {
margin-top: 28rpx;
display: flex;
align-items: center;
gap: 8rpx;
}
/* ===== 兼容你原先的类名(可选保留,避免影响其他样式) ===== */
.flex-col { display: flex; flex-direction: column; }
.flex-row { display: flex; flex-direction: row; }
.items-center { align-items: center; }
.self-center { align-self: center; }
.self-start { align-self: flex-start; }
.self-stretch { align-self: stretch; }
.relative { position: relative; }
.shrink-0 { flex-shrink: 0; }
.mt-20 { margin-top: 40rpx; }
.mt-22 { margin-top: 44rpx; } /* 你原文件的 mt-22 语义留存 */
.mt-26 { margin-top: 52rpx; }
.ml-13 { margin-left: 26rpx; }
.ml-18 { margin-left: 36rpx; }
/* 旧色彩类(若其他页面使用到,可保留) */
.text { color: #1c2023; }
.font { font-size: 36rpx; }
.font_2 { font-size: 26rpx; color: #1c2023; }
.text_10, .text_11 { font-size: 26rpx; }
/* 你原先的按钮类名占位(防止引用处报错) */
.text-wrapper_6 { }

View File

@ -1,5 +1,7 @@
// pages/personCenter/accountSetting/accountSetting.js
const { baseUrl } = require("../../../request");
const { baseUrl, globalImgUrl } = require("../../../request");
const { notLogin } = require('../../../utils/util')
Page({
@ -9,12 +11,15 @@ Page({
data: {
nickName: "",
userAvatar: "",
phoneNumber: ""
phoneNumber: "",
globalImgUrl,
role: '',
},
gotoResetPwd() {
const { role } = this.data;
wx.navigateTo({
url: '/pages/personCenter/resetPwd/resetPwd',
url: `/pages/personCenter/resetPwd/resetPwd?role=${ role }`,
})
},
@ -31,9 +36,11 @@ Page({
title: '退出成功',
icon: 'success'
})
wx.removeStorageSync('token')
wx.removeStorageSync('role')
setTimeout(() => {
wx.reLaunch({
url: '/pages/loginModule/pwdLogin/pwdLogin',
url: '/pages/welcome/homePage/homePage',
})
}, 1000); // 1000ms = 1秒
} else {
@ -62,14 +69,17 @@ Page({
Authorization: token
},
success: res => {
console.log('用户信息---->',res.data.data);
if (res.data.code === 1) {
this.setData({
nickName: res.data.data.nickName,
// TODO 头像未连接
userAvatar: res.data.data.userAvatar,
phoneNumber: res.data.data.phoneNumber,
userAccount: res.data.data.userAccount
userAccount: res.data.data.userAccount,
role:res.data.data.userRole,
})
} else {
notLogin(res.data.message)
}
},
fail: () => {

View File

@ -3,9 +3,9 @@
<view class="flex-row self-stretch section">
<image
class="self-center image"
src="./images/logo.png"
src="{{globalImgUrl + userAvatar}}"
/>
<view class="flex-col items-start flex-1 self-start group_2 ml-8">
<view class="flex-col items-start flex-1 self-start group_2 ml-16">
<text class="text">{{ nickName }}</text>
<text class="font text_2 mt-28">{{ phoneNumber }}</text>
</view>

View File

@ -20,6 +20,7 @@
.image {
width: 121.88rpx;
height: 121.88rpx;
border-radius: 30rpx;
}
.group_2 {
margin-top: 21.84rpx;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -9,7 +9,7 @@
</view>
<view class="self-start group mt-17">
<text class="font_2 text_4">注意:最高抽成比例</text>
<text class="font_2 text_5">5%</text>
<text class="font_2 text_5">10%</text>
</view>
<view class="flex-col justify-start items-center self-center text-wrapper mt-17" bindtap="submit">
<text class="font_2 text_6">确认设置</text>

Some files were not shown because too many files have changed in this diff Show More