sc
This commit is contained in:
@@ -3,109 +3,169 @@
|
||||
{
|
||||
"path": "pages/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/register",
|
||||
"style": {
|
||||
"navigationBarTitleText": "注册"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "小程序管理后台"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/work/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "工作台"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/avatar/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改头像"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/info/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "个人信息"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/info/edit",
|
||||
"style": {
|
||||
"navigationBarTitleText": "编辑资料"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/pwd/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改密码"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/setting/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "应用设置"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/help/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "常见问题"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/about/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "关于我们"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/common/webview/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "浏览网页"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/common/textview/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "浏览文本"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/distributor/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "分销员管理"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/distributor/add",
|
||||
"style": {
|
||||
"navigationBarTitleText": "新增分销员"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/distributor/edit",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改分销员"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/distributor/rule",
|
||||
"style": {
|
||||
"navigationBarTitleText": "分润规则配置"
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/school-info",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/custom-fields",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/data-logs",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/personal-info",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/password-change",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/help-center",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/about-us",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/exception/profit",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/exception/ai-recharge",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/exception/member-order",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
609
src/pages/exception/ai-recharge.vue
Normal file
609
src/pages/exception/ai-recharge.vue
Normal file
@@ -0,0 +1,609 @@
|
||||
<template>
|
||||
<view class="ai-recharge-exception-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">AI充值订单异常</view>
|
||||
<view class="header-right" @click="refreshData">
|
||||
<view class="refresh-btn">刷新</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常统计 -->
|
||||
<view class="stats-section">
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">🤖</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.total }}</view>
|
||||
<view class="stat-label">总异常数</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">⚠️</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.pending }}</view>
|
||||
<view class="stat-label">待处理</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">✅</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.resolved }}</view>
|
||||
<view class="stat-label">已解决</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常列表 -->
|
||||
<view class="exception-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">异常列表</view>
|
||||
<view class="filter-box">
|
||||
<view class="filter-tabs">
|
||||
<view
|
||||
v-for="tab in filterTabs"
|
||||
:key="tab.value"
|
||||
class="filter-tab"
|
||||
:class="{ active: currentFilter === tab.value }"
|
||||
@click="currentFilter = tab.value"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="exception-list">
|
||||
<view
|
||||
v-for="exception in filteredExceptions"
|
||||
:key="exception.id"
|
||||
class="exception-item"
|
||||
:class="{ 'pending': exception.status === 'pending', 'resolved': exception.status === 'resolved' }"
|
||||
@click="viewExceptionDetail(exception.id)"
|
||||
>
|
||||
<view class="exception-header">
|
||||
<view class="exception-title">{{ exception.title }}</view>
|
||||
<view class="exception-status">{{ getStatusText(exception.status) }}</view>
|
||||
</view>
|
||||
<view class="exception-content">
|
||||
<view class="exception-desc">{{ exception.description }}</view>
|
||||
<view class="exception-info">
|
||||
<view class="info-item">
|
||||
<view class="info-label">订单号:</view>
|
||||
<view class="info-value">{{ exception.orderNo }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">学员信息:</view>
|
||||
<view class="info-value">{{ getMaskedStudentInfo(exception.studentInfo) }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">充值金额:</view>
|
||||
<view class="info-value">{{ exception.amount }}元</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">异常时间:</view>
|
||||
<view class="info-value">{{ exception.createTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="exception-actions">
|
||||
<view
|
||||
v-if="exception.status === 'pending'"
|
||||
class="action-btn primary"
|
||||
@click.stop="resolveException(exception.id)"
|
||||
>
|
||||
处理
|
||||
</view>
|
||||
<view
|
||||
class="action-btn secondary"
|
||||
@click.stop="viewExceptionDetail(exception.id)"
|
||||
>
|
||||
详情
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="filteredExceptions.length === 0" class="empty-state">
|
||||
<view class="empty-icon">🤖</view>
|
||||
<view class="empty-text">暂无相关异常</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作提示 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-title">操作提示</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">• AI充值订单异常可能包括支付失败、系统错误等情况</view>
|
||||
<view class="tip-item">• 处理异常后系统会自动重试订单处理</view>
|
||||
<view class="tip-item">• 如遇持续异常,请联系平台客服</view>
|
||||
<view class="tip-item">• 学员信息已脱敏处理,保护隐私安全</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 异常统计
|
||||
const exceptionStats = ref({
|
||||
total: 3,
|
||||
pending: 1,
|
||||
resolved: 2
|
||||
})
|
||||
|
||||
// 异常列表
|
||||
const exceptions = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '支付失败',
|
||||
description: 'AI充值订单支付失败,请检查支付状态',
|
||||
orderNo: 'AI202601290001',
|
||||
studentInfo: {
|
||||
name: '张**',
|
||||
phone: '138****1234'
|
||||
},
|
||||
amount: 99.00,
|
||||
status: 'pending',
|
||||
createTime: '2026-01-29 10:30:45'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '系统错误',
|
||||
description: 'AI充值订单处理时系统错误,请重试',
|
||||
orderNo: 'AI202601290002',
|
||||
studentInfo: {
|
||||
name: '李**',
|
||||
phone: '139****5678'
|
||||
},
|
||||
amount: 199.00,
|
||||
status: 'resolved',
|
||||
createTime: '2026-01-29 09:15:30'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '支付超时',
|
||||
description: 'AI充值订单支付超时,请重新发起支付',
|
||||
orderNo: 'AI202601290003',
|
||||
studentInfo: {
|
||||
name: '王**',
|
||||
phone: '137****9012'
|
||||
},
|
||||
amount: 49.00,
|
||||
status: 'resolved',
|
||||
createTime: '2026-01-29 08:45:12'
|
||||
}
|
||||
])
|
||||
|
||||
// 过滤标签
|
||||
const filterTabs = ref([
|
||||
{ label: '全部', value: 'all' },
|
||||
{ label: '待处理', value: 'pending' },
|
||||
{ label: '已解决', value: 'resolved' }
|
||||
])
|
||||
|
||||
const currentFilter = ref('all')
|
||||
|
||||
// 过滤后的异常列表
|
||||
const filteredExceptions = computed(() => {
|
||||
if (currentFilter.value === 'all') {
|
||||
return exceptions.value
|
||||
}
|
||||
return exceptions.value.filter(exception => exception.status === currentFilter.value)
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
function refreshData() {
|
||||
uni.showLoading({ title: '刷新中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '刷新成功', icon: 'success' })
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
function getStatusText(status) {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return '待处理'
|
||||
case 'resolved':
|
||||
return '已解决'
|
||||
default:
|
||||
return '未知'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取脱敏学员信息
|
||||
function getMaskedStudentInfo(studentInfo) {
|
||||
return `${studentInfo.name} ${studentInfo.phone}`
|
||||
}
|
||||
|
||||
// 查看异常详情
|
||||
function viewExceptionDetail(exceptionId) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/exception/ai-recharge-detail?id=${exceptionId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 处理异常
|
||||
function resolveException(exceptionId) {
|
||||
uni.showModal({
|
||||
title: '处理异常',
|
||||
content: '是否确认处理该异常?\n\n处理后系统会自动重试订单处理',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: '处理中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '处理成功', icon: 'success' })
|
||||
|
||||
// 更新异常状态
|
||||
const exception = exceptions.value.find(e => e.id === exceptionId)
|
||||
if (exception) {
|
||||
exception.status = 'resolved'
|
||||
// 更新统计数据
|
||||
exceptionStats.value.pending--
|
||||
exceptionStats.value.resolved++
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取异常数据
|
||||
// fetchExceptionData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.ai-recharge-exception-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 异常统计 */
|
||||
.stats-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 48rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 异常列表 */
|
||||
.exception-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
padding: 12rpx 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filter-tab.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.exception-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.exception-item {
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.exception-item.pending {
|
||||
border-left: 8rpx solid #f56c6c;
|
||||
}
|
||||
|
||||
.exception-item.resolved {
|
||||
border-left: 8rpx solid #67c23a;
|
||||
}
|
||||
|
||||
.exception-item:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.exception-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.exception-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.exception-status {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.exception-item.pending .exception-status {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.exception-item.resolved .exception-status {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.exception-content {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.exception-desc {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.exception-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 22rpx;
|
||||
color: #909399;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.exception-actions {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action-btn.primary {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.action-btn.secondary {
|
||||
background-color: #f9f9f9;
|
||||
color: #606266;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
}
|
||||
|
||||
/* 操作提示 */
|
||||
.tips-section {
|
||||
padding: 32rpx;
|
||||
background-color: #ecf5ff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 100rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.ai-recharge-exception-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.stats-section,
|
||||
.exception-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.exception-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.exception-desc {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
644
src/pages/exception/member-order.vue
Normal file
644
src/pages/exception/member-order.vue
Normal file
@@ -0,0 +1,644 @@
|
||||
<template>
|
||||
<view class="member-order-exception-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">会员订单异常</view>
|
||||
<view class="header-right" @click="refreshData">
|
||||
<view class="refresh-btn">刷新</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常统计 -->
|
||||
<view class="stats-section">
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">🛒</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.total }}</view>
|
||||
<view class="stat-label">总异常数</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">⚠️</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.pending }}</view>
|
||||
<view class="stat-label">待处理</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">✅</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.resolved }}</view>
|
||||
<view class="stat-label">已解决</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常列表 -->
|
||||
<view class="exception-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">异常列表</view>
|
||||
<view class="filter-box">
|
||||
<view class="filter-tabs">
|
||||
<view
|
||||
v-for="tab in filterTabs"
|
||||
:key="tab.value"
|
||||
class="filter-tab"
|
||||
:class="{ active: currentFilter === tab.value }"
|
||||
@click="currentFilter = tab.value"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="exception-list">
|
||||
<view
|
||||
v-for="exception in filteredExceptions"
|
||||
:key="exception.id"
|
||||
class="exception-item"
|
||||
:class="{ 'pending': exception.status === 'pending', 'resolved': exception.status === 'resolved' }"
|
||||
@click="viewExceptionDetail(exception.id)"
|
||||
>
|
||||
<view class="exception-header">
|
||||
<view class="exception-title">{{ exception.title }}</view>
|
||||
<view class="exception-status">{{ getStatusText(exception.status) }}</view>
|
||||
</view>
|
||||
<view class="exception-content">
|
||||
<view class="exception-desc">{{ exception.description }}</view>
|
||||
<view class="exception-info">
|
||||
<view class="info-item">
|
||||
<view class="info-label">订单号:</view>
|
||||
<view class="info-value">{{ exception.orderNo }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">学员信息:</view>
|
||||
<view class="info-value">{{ getMaskedStudentInfo(exception.studentInfo) }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">会员类型:</view>
|
||||
<view class="info-value">{{ exception.memberType }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">订单金额:</view>
|
||||
<view class="info-value">{{ exception.amount }}元</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">异常时间:</view>
|
||||
<view class="info-value">{{ exception.createTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="exception-actions">
|
||||
<view
|
||||
v-if="exception.status === 'pending'"
|
||||
class="action-btn primary"
|
||||
@click.stop="resolveException(exception.id)"
|
||||
>
|
||||
处理
|
||||
</view>
|
||||
<view
|
||||
class="action-btn secondary"
|
||||
@click.stop="viewExceptionDetail(exception.id)"
|
||||
>
|
||||
详情
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="filteredExceptions.length === 0" class="empty-state">
|
||||
<view class="empty-icon">🛒</view>
|
||||
<view class="empty-text">暂无相关异常</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作提示 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-title">操作提示</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">• 会员订单异常可能包括支付失败、系统错误等情况</view>
|
||||
<view class="tip-item">• 处理异常后系统会自动重试订单处理</view>
|
||||
<view class="tip-item">• 如遇持续异常,请联系平台客服</view>
|
||||
<view class="tip-item">• 学员信息已脱敏处理,保护隐私安全</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 异常统计
|
||||
const exceptionStats = ref({
|
||||
total: 5,
|
||||
pending: 3,
|
||||
resolved: 2
|
||||
})
|
||||
|
||||
// 异常列表
|
||||
const exceptions = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '支付失败',
|
||||
description: '会员订单支付失败,请检查支付状态',
|
||||
orderNo: 'M202601290001',
|
||||
studentInfo: {
|
||||
name: '张**',
|
||||
phone: '138****1234'
|
||||
},
|
||||
memberType: '年度会员',
|
||||
amount: 299.00,
|
||||
status: 'pending',
|
||||
createTime: '2026-01-29 10:45:30'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '系统错误',
|
||||
description: '会员订单处理时系统错误,请重试',
|
||||
orderNo: 'M202601290002',
|
||||
studentInfo: {
|
||||
name: '李**',
|
||||
phone: '139****5678'
|
||||
},
|
||||
memberType: '季度会员',
|
||||
amount: 99.00,
|
||||
status: 'pending',
|
||||
createTime: '2026-01-29 09:30:15'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '支付超时',
|
||||
description: '会员订单支付超时,请重新发起支付',
|
||||
orderNo: 'M202601290003',
|
||||
studentInfo: {
|
||||
name: '王**',
|
||||
phone: '137****9012'
|
||||
},
|
||||
memberType: '月度会员',
|
||||
amount: 39.00,
|
||||
status: 'pending',
|
||||
createTime: '2026-01-29 08:15:45'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '支付失败',
|
||||
description: '会员订单支付失败,请检查支付状态',
|
||||
orderNo: 'M202601280004',
|
||||
studentInfo: {
|
||||
name: '刘**',
|
||||
phone: '136****3456'
|
||||
},
|
||||
memberType: '年度会员',
|
||||
amount: 299.00,
|
||||
status: 'resolved',
|
||||
createTime: '2026-01-28 16:20:30'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: '系统错误',
|
||||
description: '会员订单处理时系统错误,请重试',
|
||||
orderNo: 'M202601280005',
|
||||
studentInfo: {
|
||||
name: '陈**',
|
||||
phone: '135****7890'
|
||||
},
|
||||
memberType: '季度会员',
|
||||
amount: 99.00,
|
||||
status: 'resolved',
|
||||
createTime: '2026-01-28 14:10:15'
|
||||
}
|
||||
])
|
||||
|
||||
// 过滤标签
|
||||
const filterTabs = ref([
|
||||
{ label: '全部', value: 'all' },
|
||||
{ label: '待处理', value: 'pending' },
|
||||
{ label: '已解决', value: 'resolved' }
|
||||
])
|
||||
|
||||
const currentFilter = ref('all')
|
||||
|
||||
// 过滤后的异常列表
|
||||
const filteredExceptions = computed(() => {
|
||||
if (currentFilter.value === 'all') {
|
||||
return exceptions.value
|
||||
}
|
||||
return exceptions.value.filter(exception => exception.status === currentFilter.value)
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
function refreshData() {
|
||||
uni.showLoading({ title: '刷新中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '刷新成功', icon: 'success' })
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
function getStatusText(status) {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return '待处理'
|
||||
case 'resolved':
|
||||
return '已解决'
|
||||
default:
|
||||
return '未知'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取脱敏学员信息
|
||||
function getMaskedStudentInfo(studentInfo) {
|
||||
return `${studentInfo.name} ${studentInfo.phone}`
|
||||
}
|
||||
|
||||
// 查看异常详情
|
||||
function viewExceptionDetail(exceptionId) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/exception/member-order-detail?id=${exceptionId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 处理异常
|
||||
function resolveException(exceptionId) {
|
||||
uni.showModal({
|
||||
title: '处理异常',
|
||||
content: '是否确认处理该异常?\n\n处理后系统会自动重试订单处理',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: '处理中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '处理成功', icon: 'success' })
|
||||
|
||||
// 更新异常状态
|
||||
const exception = exceptions.value.find(e => e.id === exceptionId)
|
||||
if (exception) {
|
||||
exception.status = 'resolved'
|
||||
// 更新统计数据
|
||||
exceptionStats.value.pending--
|
||||
exceptionStats.value.resolved++
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取异常数据
|
||||
// fetchExceptionData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.member-order-exception-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 异常统计 */
|
||||
.stats-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 48rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 异常列表 */
|
||||
.exception-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
padding: 12rpx 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filter-tab.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.exception-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.exception-item {
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.exception-item.pending {
|
||||
border-left: 8rpx solid #f56c6c;
|
||||
}
|
||||
|
||||
.exception-item.resolved {
|
||||
border-left: 8rpx solid #67c23a;
|
||||
}
|
||||
|
||||
.exception-item:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.exception-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.exception-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.exception-status {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.exception-item.pending .exception-status {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.exception-item.resolved .exception-status {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.exception-content {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.exception-desc {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.exception-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 22rpx;
|
||||
color: #909399;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.exception-actions {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action-btn.primary {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.action-btn.secondary {
|
||||
background-color: #f9f9f9;
|
||||
color: #606266;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
}
|
||||
|
||||
/* 操作提示 */
|
||||
.tips-section {
|
||||
padding: 32rpx;
|
||||
background-color: #ecf5ff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 100rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.member-order-exception-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.stats-section,
|
||||
.exception-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.exception-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.exception-desc {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
606
src/pages/exception/profit.vue
Normal file
606
src/pages/exception/profit.vue
Normal file
@@ -0,0 +1,606 @@
|
||||
<template>
|
||||
<view class="profit-exception-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">分润异常提醒</view>
|
||||
<view class="header-right" @click="refreshData">
|
||||
<view class="refresh-btn">刷新</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常统计 -->
|
||||
<view class="stats-section">
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">💰</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.total }}</view>
|
||||
<view class="stat-label">总异常数</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">⚠️</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.pending }}</view>
|
||||
<view class="stat-label">待处理</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">✅</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ exceptionStats.resolved }}</view>
|
||||
<view class="stat-label">已解决</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常列表 -->
|
||||
<view class="exception-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">异常列表</view>
|
||||
<view class="filter-box">
|
||||
<view class="filter-tabs">
|
||||
<view
|
||||
v-for="tab in filterTabs"
|
||||
:key="tab.value"
|
||||
class="filter-tab"
|
||||
:class="{ active: currentFilter === tab.value }"
|
||||
@click="currentFilter = tab.value"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="exception-list">
|
||||
<view
|
||||
v-for="exception in filteredExceptions"
|
||||
:key="exception.id"
|
||||
class="exception-item"
|
||||
:class="{ 'pending': exception.status === 'pending', 'resolved': exception.status === 'resolved' }"
|
||||
@click="viewExceptionDetail(exception.id)"
|
||||
>
|
||||
<view class="exception-header">
|
||||
<view class="exception-title">{{ exception.title }}</view>
|
||||
<view class="exception-status">{{ getStatusText(exception.status) }}</view>
|
||||
</view>
|
||||
<view class="exception-content">
|
||||
<view class="exception-desc">{{ exception.description }}</view>
|
||||
<view class="exception-info">
|
||||
<view class="info-item">
|
||||
<view class="info-label">关联账户:</view>
|
||||
<view class="info-value">{{ exception.accountName }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">异常金额:</view>
|
||||
<view class="info-value">{{ exception.amount }}元</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">异常时间:</view>
|
||||
<view class="info-value">{{ exception.createTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="exception-actions">
|
||||
<view
|
||||
v-if="exception.status === 'pending'"
|
||||
class="action-btn primary"
|
||||
@click.stop="resolveException(exception.id)"
|
||||
>
|
||||
处理
|
||||
</view>
|
||||
<view
|
||||
class="action-btn secondary"
|
||||
@click.stop="viewExceptionDetail(exception.id)"
|
||||
>
|
||||
详情
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="filteredExceptions.length === 0" class="empty-state">
|
||||
<view class="empty-icon">📭</view>
|
||||
<view class="empty-text">暂无相关异常</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作提示 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-title">操作提示</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">• 账户余额不足时,系统会暂停分润发放</view>
|
||||
<view class="tip-item">• 请及时充值以确保分润正常发放</view>
|
||||
<view class="tip-item">• 处理异常后,系统会自动重试分润发放</view>
|
||||
<view class="tip-item">• 如遇持续异常,请联系平台客服</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 异常统计
|
||||
const exceptionStats = ref({
|
||||
total: 5,
|
||||
pending: 2,
|
||||
resolved: 3
|
||||
})
|
||||
|
||||
// 异常列表
|
||||
const exceptions = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '账户余额不足',
|
||||
description: '驾校账户余额不足,无法发放分销员分润',
|
||||
accountName: '顺达驾校',
|
||||
amount: 1250.00,
|
||||
status: 'pending',
|
||||
createTime: '2026-01-29 10:15:30'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '账户余额不足',
|
||||
description: '驾校账户余额不足,无法发放分销员分润',
|
||||
accountName: '顺达驾校',
|
||||
amount: 890.50,
|
||||
status: 'pending',
|
||||
createTime: '2026-01-29 09:45:12'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '账户余额不足',
|
||||
description: '驾校账户余额不足,无法发放分销员分润',
|
||||
accountName: '顺达驾校',
|
||||
amount: 678.20,
|
||||
status: 'resolved',
|
||||
createTime: '2026-01-28 16:30:45'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '账户余额不足',
|
||||
description: '驾校账户余额不足,无法发放分销员分润',
|
||||
accountName: '顺达驾校',
|
||||
amount: 1560.80,
|
||||
status: 'resolved',
|
||||
createTime: '2026-01-28 14:20:18'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: '账户余额不足',
|
||||
description: '驾校账户余额不足,无法发放分销员分润',
|
||||
accountName: '顺达驾校',
|
||||
amount: 980.00,
|
||||
status: 'resolved',
|
||||
createTime: '2026-01-28 11:05:33'
|
||||
}
|
||||
])
|
||||
|
||||
// 过滤标签
|
||||
const filterTabs = ref([
|
||||
{ label: '全部', value: 'all' },
|
||||
{ label: '待处理', value: 'pending' },
|
||||
{ label: '已解决', value: 'resolved' }
|
||||
])
|
||||
|
||||
const currentFilter = ref('all')
|
||||
|
||||
// 过滤后的异常列表
|
||||
const filteredExceptions = computed(() => {
|
||||
if (currentFilter.value === 'all') {
|
||||
return exceptions.value
|
||||
}
|
||||
return exceptions.value.filter(exception => exception.status === currentFilter.value)
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
function refreshData() {
|
||||
uni.showLoading({ title: '刷新中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '刷新成功', icon: 'success' })
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
function getStatusText(status) {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return '待处理'
|
||||
case 'resolved':
|
||||
return '已解决'
|
||||
default:
|
||||
return '未知'
|
||||
}
|
||||
}
|
||||
|
||||
// 查看异常详情
|
||||
function viewExceptionDetail(exceptionId) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/exception/profit-detail?id=${exceptionId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 处理异常
|
||||
function resolveException(exceptionId) {
|
||||
uni.showModal({
|
||||
title: '处理异常',
|
||||
content: '是否确认处理该异常?\n\n处理后系统会自动重试分润发放',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: '处理中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '处理成功', icon: 'success' })
|
||||
|
||||
// 更新异常状态
|
||||
const exception = exceptions.value.find(e => e.id === exceptionId)
|
||||
if (exception) {
|
||||
exception.status = 'resolved'
|
||||
// 更新统计数据
|
||||
exceptionStats.value.pending--
|
||||
exceptionStats.value.resolved++
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取异常数据
|
||||
// fetchExceptionData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.profit-exception-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 异常统计 */
|
||||
.stats-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 48rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 异常列表 */
|
||||
.exception-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.filter-tabs {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.filter-tab {
|
||||
padding: 12rpx 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filter-tab.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.exception-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.exception-item {
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.exception-item.pending {
|
||||
border-left: 8rpx solid #f56c6c;
|
||||
}
|
||||
|
||||
.exception-item.resolved {
|
||||
border-left: 8rpx solid #67c23a;
|
||||
}
|
||||
|
||||
.exception-item:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.exception-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.exception-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.exception-status {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.exception-item.pending .exception-status {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.exception-item.resolved .exception-status {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.exception-content {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.exception-desc {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.exception-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 22rpx;
|
||||
color: #909399;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.exception-actions {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action-btn.primary {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.action-btn.secondary {
|
||||
background-color: #f9f9f9;
|
||||
color: #606266;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
}
|
||||
|
||||
/* 操作提示 */
|
||||
.tips-section {
|
||||
padding: 32rpx;
|
||||
background-color: #ecf5ff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 100rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.profit-exception-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.stats-section,
|
||||
.exception-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.exception-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.exception-desc {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,36 +1,575 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<image class="logo" src="@/static/logo.png"></image>
|
||||
<view class="text-area">
|
||||
<text class="title">Hello RuoYi</text>
|
||||
<view class="index-container">
|
||||
<!-- 欢迎信息 -->
|
||||
<view class="welcome-section">
|
||||
<view class="welcome-title">欢迎使用小程序管理系统</view>
|
||||
<view class="welcome-desc">
|
||||
<text v-if="userRole === 'admin'">管理员视图</text>
|
||||
<text v-else>分销员视图</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 管理员统计功能 -->
|
||||
<view v-if="userRole === 'admin'" class="stats-section">
|
||||
<!-- 核心数据概览 -->
|
||||
<view class="section">
|
||||
<view class="section-title">核心数据概览</view>
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card" @click="goToDistributionStats">
|
||||
<view class="stat-icon">📊</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ distributionStats.totalProfit }}</view>
|
||||
<view class="stat-label">分润总额</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card" @click="goToMemberStats">
|
||||
<view class="stat-icon">👥</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ memberStats.totalOrders }}</view>
|
||||
<view class="stat-label">会员订单</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card" @click="goToStudentStats">
|
||||
<view class="stat-icon">🎓</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ studentStats.totalStudents }}</view>
|
||||
<view class="stat-label">学员总数</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card" @click="goToDistributionStats">
|
||||
<view class="stat-icon">📈</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ distributionStats.scanCount }}</view>
|
||||
<view class="stat-label">扫码数</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分销业绩统计 -->
|
||||
<view class="section">
|
||||
<view class="section-title">分销业绩统计</view>
|
||||
<view class="feature-card" @click="goToDistributionStats">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">📈</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">分销业绩统计</view>
|
||||
<view class="feature-desc">查看业绩汇总、排行、多维度筛选</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 会员运营统计 -->
|
||||
<view class="section">
|
||||
<view class="section-title">会员运营统计</view>
|
||||
<view class="feature-card" @click="goToMemberStats">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">👥</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">会员运营统计</view>
|
||||
<view class="feature-desc">查看订单总数、金额、各类型占比</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 学员学情统计 -->
|
||||
<view class="section">
|
||||
<view class="section-title">学员学情统计</view>
|
||||
<view class="feature-card" @click="goToStudentStats">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">🎓</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">学员学情统计</view>
|
||||
<view class="feature-desc">查看学员总数、正确率、模考平均分</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分销员统计功能 -->
|
||||
<view v-else-if="userRole === 'distributor'" class="stats-section">
|
||||
<!-- 个人核心数据 -->
|
||||
<view class="section">
|
||||
<view class="section-title">个人核心数据</view>
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">📱</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ personalStats.scanCount }}</view>
|
||||
<view class="stat-label">扫码数</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">👥</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ personalStats.paidCount }}</view>
|
||||
<view class="stat-label">付费人数</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">📈</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ personalStats.conversionRate }}%</view>
|
||||
<view class="stat-label">转化率</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card">
|
||||
<view class="stat-icon">💰</view>
|
||||
<view class="stat-content">
|
||||
<view class="stat-value">{{ personalStats.totalProfit }}</view>
|
||||
<view class="stat-label">提成总额</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 个人业绩统计 -->
|
||||
<view class="section">
|
||||
<view class="section-title">个人业绩统计</view>
|
||||
<view class="feature-card" @click="goToPersonalStats">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">📊</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">个人业绩统计</view>
|
||||
<view class="feature-desc">查看核心数据、近7天趋势</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据分享 -->
|
||||
<view class="section">
|
||||
<view class="section-title">数据分享</view>
|
||||
<view class="feature-card" @click="shareData">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">📱</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">数据分享</view>
|
||||
<view class="feature-desc">生成业绩数据图片,一键分享</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.content {
|
||||
<script setup>
|
||||
import { ref, getCurrentInstance, onMounted } from "vue"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const userRole = ref('admin') // 模拟角色,实际应从登录状态获取
|
||||
|
||||
// 模拟统计数据
|
||||
const distributionStats = ref({
|
||||
totalProfit: '¥12,345.67',
|
||||
scanCount: 1234,
|
||||
paidCount: 456,
|
||||
conversionRate: '36.9%'
|
||||
})
|
||||
|
||||
const memberStats = ref({
|
||||
totalOrders: 789,
|
||||
totalAmount: '¥89,765.43',
|
||||
refundRate: '2.1%'
|
||||
})
|
||||
|
||||
const studentStats = ref({
|
||||
totalStudents: 1234,
|
||||
memberStudents: 890,
|
||||
avgCorrectRate: '78.5%',
|
||||
avgExamScore: '82.3'
|
||||
})
|
||||
|
||||
const personalStats = ref({
|
||||
scanCount: 123,
|
||||
paidCount: 45,
|
||||
conversionRate: 36.9,
|
||||
totalProfit: '¥1,234.56'
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从登录状态或接口获取用户角色和数据
|
||||
// userRole.value = getUserRole()
|
||||
// loadStatsData()
|
||||
})
|
||||
|
||||
// 管理员统计功能跳转
|
||||
function goToDistributionStats() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/distribution'
|
||||
})
|
||||
}
|
||||
|
||||
function goToMemberStats() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/member'
|
||||
})
|
||||
}
|
||||
|
||||
function goToStudentStats() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/student'
|
||||
})
|
||||
}
|
||||
|
||||
// 分销员统计功能跳转
|
||||
function goToPersonalStats() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/personal'
|
||||
})
|
||||
}
|
||||
|
||||
function shareData() {
|
||||
// 生成并分享业绩数据图片
|
||||
uni.showToast({
|
||||
title: '生成分享图片中...',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
// 模拟生成图片并分享
|
||||
setTimeout(() => {
|
||||
uni.showActionSheet({
|
||||
itemList: ['分享到微信', '分享到朋友圈', '保存图片'],
|
||||
success: function(res) {
|
||||
switch(res.tapIndex) {
|
||||
case 0:
|
||||
uni.showToast({ title: '分享到微信', duration: 1000 })
|
||||
break
|
||||
case 1:
|
||||
uni.showToast({ title: '分享到朋友圈', duration: 1000 })
|
||||
break
|
||||
case 2:
|
||||
uni.showToast({ title: '图片已保存', duration: 1000 })
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}, 1500)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.index-container {
|
||||
padding: 20rpx;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 欢迎信息 */
|
||||
.welcome-section {
|
||||
background: linear-gradient(135deg, #409eff 0%, #667eea 100%);
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx;
|
||||
margin-bottom: 30rpx;
|
||||
color: #fff;
|
||||
box-shadow: 0 8rpx 32rpx rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
|
||||
.welcome-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.welcome-desc {
|
||||
font-size: 24rpx;
|
||||
opacity: 0.9;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 统计区域 */
|
||||
.stats-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 30rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 24rpx;
|
||||
padding-left: 12rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* 统计网格 */
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stat-card:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 48rpx;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 4rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 20rpx;
|
||||
color: #909399;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* 功能卡片样式 */
|
||||
.feature-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.feature-card:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 图标容器 */
|
||||
.feature-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 200rpx;
|
||||
width: 200rpx;
|
||||
margin-top: 200rpx;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 50rpx;
|
||||
/* 各模块颜色 */
|
||||
.distributor-icon {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.text-area {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.user-icon {
|
||||
background-color: #f0f9eb;
|
||||
}
|
||||
|
||||
.title {
|
||||
.dept-icon {
|
||||
background-color: #fdf6ec;
|
||||
}
|
||||
|
||||
.notice-icon {
|
||||
background-color: #fef0f0;
|
||||
}
|
||||
|
||||
.log-icon {
|
||||
background-color: #f4f4f5;
|
||||
}
|
||||
|
||||
/* 图标文本样式 */
|
||||
.icon-text {
|
||||
font-size: 40rpx;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 功能信息 */
|
||||
.feature-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 22rpx;
|
||||
color: #909399;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.index-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.welcome-section {
|
||||
padding: 50rpx;
|
||||
}
|
||||
|
||||
.welcome-title {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.welcome-desc {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 36rpx;
|
||||
color: #8f8f94;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 56rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板和大屏响应式 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.index-container {
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
.welcome-section {
|
||||
padding: 60rpx;
|
||||
}
|
||||
|
||||
.welcome-title {
|
||||
font-size: 52rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 36rpx;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
padding: 36rpx;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 64rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 36rpx;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
font-size: 56rpx;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
483
src/pages/mine/about-us.vue
Normal file
483
src/pages/mine/about-us.vue
Normal file
@@ -0,0 +1,483 @@
|
||||
<template>
|
||||
<view class="about-us-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">关于我们</view>
|
||||
<view class="header-right"></view>
|
||||
</view>
|
||||
|
||||
<!-- 公司信息 -->
|
||||
<view class="company-section">
|
||||
<view class="company-logo">
|
||||
<view class="logo-icon">🏢</view>
|
||||
</view>
|
||||
<view class="company-info">
|
||||
<view class="company-name">顺达驾校管理系统</view>
|
||||
<view class="company-slogan">专业的驾校管理解决方案</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 版本信息 -->
|
||||
<view class="version-section">
|
||||
<view class="version-item">
|
||||
<view class="version-label">当前版本</view>
|
||||
<view class="version-value">{{ appVersion }}</view>
|
||||
</view>
|
||||
<view class="version-item">
|
||||
<view class="version-label">更新时间</view>
|
||||
<view class="version-value">{{ updateTime }}</view>
|
||||
</view>
|
||||
<view class="version-item">
|
||||
<view class="version-label">系统状态</view>
|
||||
<view class="version-value">
|
||||
<view class="status-indicator"></view>
|
||||
<view class="status-text">运行中</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能介绍 -->
|
||||
<view class="features-section">
|
||||
<view class="section-title">功能介绍</view>
|
||||
<view class="features-list">
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">📊</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">统计分析</view>
|
||||
<view class="feature-desc">实时查看驾校运营数据,掌握业务动态</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">👥</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">会员管理</view>
|
||||
<view class="feature-desc">管理会员信息,支持会员赠送和续费</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">🎓</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">学员管理</view>
|
||||
<view class="feature-desc">监控学员学习情况,提供个性化学习建议</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">📈</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">分销系统</view>
|
||||
<view class="feature-desc">支持分销员管理,提高驾校招生效率</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="feature-item">
|
||||
<view class="feature-icon">🏢</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">驾校管理</view>
|
||||
<view class="feature-desc">管理驾校信息,配置自定义字段</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系信息 -->
|
||||
<view class="contact-section">
|
||||
<view class="section-title">联系我们</view>
|
||||
<view class="contact-list">
|
||||
<view class="contact-item">
|
||||
<view class="contact-icon">📞</view>
|
||||
<view class="contact-info">
|
||||
<view class="contact-label">客服电话</view>
|
||||
<view class="contact-value">400-123-4567</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<view class="contact-icon">📧</view>
|
||||
<view class="contact-info">
|
||||
<view class="contact-label">客服邮箱</view>
|
||||
<view class="contact-value">support@shunda.com</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<view class="contact-icon">🌐</view>
|
||||
<view class="contact-info">
|
||||
<view class="contact-label">官方网站</view>
|
||||
<view class="contact-value">www.shunda.com</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<view class="contact-icon">📍</view>
|
||||
<view class="contact-info">
|
||||
<view class="contact-label">公司地址</view>
|
||||
<view class="contact-value">北京市朝阳区建国路88号</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 版权信息 -->
|
||||
<view class="copyright-section">
|
||||
<view class="copyright-text">© 2026 顺达驾校管理系统</view>
|
||||
<view class="copyright-desc">All Rights Reserved</view>
|
||||
<view class="copyright-policy">
|
||||
<view class="policy-item" @click="viewPrivacyPolicy">隐私政策</view>
|
||||
<view class="policy-divider">|</view>
|
||||
<view class="policy-item" @click="viewTermsOfService">服务条款</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue"
|
||||
|
||||
// 应用信息
|
||||
const appVersion = ref('v1.0.0')
|
||||
const updateTime = ref('2026-01-29')
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 查看隐私政策
|
||||
function viewPrivacyPolicy() {
|
||||
uni.showModal({
|
||||
title: '隐私政策',
|
||||
content: '隐私政策详情页面正在开发中',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
|
||||
// 查看服务条款
|
||||
function viewTermsOfService() {
|
||||
uni.showModal({
|
||||
title: '服务条款',
|
||||
content: '服务条款详情页面正在开发中',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.about-us-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
/* 公司信息 */
|
||||
.company-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60rpx 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.company-logo {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 80rpx;
|
||||
background-color: #409eff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
font-size: 80rpx;
|
||||
}
|
||||
|
||||
.company-name {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.company-slogan {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 版本信息 */
|
||||
.version-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.version-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #e4e7ed;
|
||||
}
|
||||
|
||||
.version-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.version-label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.version-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 6rpx;
|
||||
background-color: #67c23a;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
/* 功能介绍 */
|
||||
.features-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 32rpx;
|
||||
padding-left: 12rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.features-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300rpx, 1fr));
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.feature-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 40rpx;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.feature-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 联系信息 */
|
||||
.contact-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.contact-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.contact-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
font-size: 40rpx;
|
||||
margin-right: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.contact-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.contact-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 版权信息 */
|
||||
.copyright-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40rpx 32rpx;
|
||||
background-color: #f0f2f5;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.copyright-text {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.copyright-desc {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.copyright-policy {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.policy-item {
|
||||
font-size: 24rpx;
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.policy-divider {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.about-us-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.company-section {
|
||||
padding: 80rpx 40rpx;
|
||||
}
|
||||
|
||||
.company-name {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.company-slogan {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.features-list {
|
||||
grid-template-columns: repeat(auto-fill, minmax(400rpx, 1fr));
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.contact-value {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
620
src/pages/mine/custom-fields.vue
Normal file
620
src/pages/mine/custom-fields.vue
Normal file
@@ -0,0 +1,620 @@
|
||||
<template>
|
||||
<view class="custom-fields-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">自定义字段配置</view>
|
||||
<view class="header-right" @click="saveFields">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 字段列表 -->
|
||||
<view class="fields-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">本驾校专属自定义字段</view>
|
||||
<view class="add-btn" @click="addField">
|
||||
<view class="add-icon">+</view>
|
||||
<view class="add-text">添加字段</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="fields-list">
|
||||
<view v-for="(field, index) in customFields" :key="field.id" class="field-item">
|
||||
<view class="field-header">
|
||||
<view class="field-title">字段 {{ index + 1 }}</view>
|
||||
<view class="field-actions">
|
||||
<view class="action-btn up-btn" @click="moveField(index, 'up')" :class="{ disabled: index === 0 }">
|
||||
↑
|
||||
</view>
|
||||
<view class="action-btn down-btn" @click="moveField(index, 'down')" :class="{ disabled: index === customFields.length - 1 }">
|
||||
↓
|
||||
</view>
|
||||
<view class="action-btn delete-btn" @click="deleteField(index)">
|
||||
×
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="field-form">
|
||||
<view class="form-group">
|
||||
<view class="form-label">字段名称</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="field.name"
|
||||
class="form-input"
|
||||
placeholder="请输入字段名称"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">字段类型</view>
|
||||
<view class="form-control">
|
||||
<picker
|
||||
v-model="field.type"
|
||||
:range="fieldTypes"
|
||||
:range-key="'label'"
|
||||
class="form-picker"
|
||||
>
|
||||
<view class="picker-display">{{ getFieldTypeName(field.type) }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group" v-if="field.type === 'select'">
|
||||
<view class="form-label">选项值</view>
|
||||
<view class="form-control">
|
||||
<textarea
|
||||
v-model="field.options"
|
||||
class="form-textarea"
|
||||
placeholder="请输入选项值,多个选项用逗号分隔"
|
||||
maxlength="200"
|
||||
rows="2"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">是否必填</view>
|
||||
<view class="form-control">
|
||||
<switch
|
||||
v-model="field.required"
|
||||
class="form-switch"
|
||||
active-color="#409eff"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">字段描述</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="field.description"
|
||||
class="form-input"
|
||||
placeholder="请输入字段描述"
|
||||
maxlength="100"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 筛选规则配置 -->
|
||||
<view class="rules-section">
|
||||
<view class="section-title">筛选规则配置</view>
|
||||
<view class="rules-content">
|
||||
<view class="rule-item">
|
||||
<view class="rule-label">启用字段筛选</view>
|
||||
<view class="rule-control">
|
||||
<switch
|
||||
v-model="filterRules.enabled"
|
||||
class="form-switch"
|
||||
active-color="#409eff"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="rule-item">
|
||||
<view class="rule-label">默认显示字段</view>
|
||||
<view class="rule-control">
|
||||
<picker
|
||||
v-model="filterRules.defaultFields"
|
||||
:range="availableFields"
|
||||
:range-key="'name'"
|
||||
mode="multiSelector"
|
||||
class="form-picker"
|
||||
>
|
||||
<view class="picker-display">
|
||||
{{ filterRules.defaultFields.length }} 个字段
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-title">注意事项</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">• 自定义字段仅在本驾校生效</view>
|
||||
<view class="tip-item">• 字段类型包括:文本、数字、日期、下拉选择</view>
|
||||
<view class="tip-item">• 下拉选择类型需要配置选项值</view>
|
||||
<view class="tip-item">• 修改配置后需点击保存按钮生效</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 字段类型选项
|
||||
const fieldTypes = ref([
|
||||
{ value: 'text', label: '文本' },
|
||||
{ value: 'number', label: '数字' },
|
||||
{ value: 'date', label: '日期' },
|
||||
{ value: 'select', label: '下拉选择' }
|
||||
])
|
||||
|
||||
// 自定义字段列表
|
||||
const customFields = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '学员来源渠道',
|
||||
type: 'select',
|
||||
options: '朋友介绍,网络推广,线下广告,其他',
|
||||
required: false,
|
||||
description: '记录学员的来源渠道'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '报名时间',
|
||||
type: 'date',
|
||||
required: true,
|
||||
description: '学员报名的具体时间'
|
||||
}
|
||||
])
|
||||
|
||||
// 筛选规则
|
||||
const filterRules = ref({
|
||||
enabled: true,
|
||||
defaultFields: [0, 1]
|
||||
})
|
||||
|
||||
// 计算可用字段
|
||||
const availableFields = computed(() => {
|
||||
return customFields.value.map((field, index) => ({
|
||||
id: field.id,
|
||||
name: field.name
|
||||
}))
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取自定义字段配置
|
||||
// loadCustomFields()
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 获取字段类型名称
|
||||
function getFieldTypeName(type) {
|
||||
const fieldType = fieldTypes.value.find(item => item.value === type)
|
||||
return fieldType ? fieldType.label : '请选择'
|
||||
}
|
||||
|
||||
// 添加字段
|
||||
function addField() {
|
||||
const newField = {
|
||||
id: Date.now(),
|
||||
name: '',
|
||||
type: 'text',
|
||||
required: false,
|
||||
description: ''
|
||||
}
|
||||
customFields.value.push(newField)
|
||||
}
|
||||
|
||||
// 删除字段
|
||||
function deleteField(index) {
|
||||
uni.showModal({
|
||||
title: '删除字段',
|
||||
content: '确定要删除这个字段吗?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
customFields.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 移动字段
|
||||
function moveField(index, direction) {
|
||||
if (direction === 'up' && index > 0) {
|
||||
const temp = customFields.value[index]
|
||||
customFields.value[index] = customFields.value[index - 1]
|
||||
customFields.value[index - 1] = temp
|
||||
} else if (direction === 'down' && index < customFields.value.length - 1) {
|
||||
const temp = customFields.value[index]
|
||||
customFields.value[index] = customFields.value[index + 1]
|
||||
customFields.value[index + 1] = temp
|
||||
}
|
||||
}
|
||||
|
||||
// 保存字段配置
|
||||
function saveFields() {
|
||||
// 表单验证
|
||||
const emptyFields = customFields.value.filter(field => !field.name)
|
||||
if (emptyFields.length > 0) {
|
||||
uni.showToast({ title: '请填写所有字段名称', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 实际项目中应调用接口保存配置
|
||||
uni.showLoading({ title: '保存中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
goBack()
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.custom-fields-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 字段列表 */
|
||||
.fields-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12rpx 24rpx;
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
border-radius: 8rpx;
|
||||
cursor: pointer;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.add-icon {
|
||||
margin-right: 8rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.fields-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.field-item {
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.field-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.field-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.field-actions {
|
||||
display: flex;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background-color: #e4e7ed;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.action-btn:hover {
|
||||
background-color: #c0c4cc;
|
||||
}
|
||||
|
||||
.action-btn.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
background-color: #fde2e2;
|
||||
}
|
||||
|
||||
/* 字段表单 */
|
||||
.field-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
color: #606266;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 60rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 6rpx;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2rpx rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
min-height: 120rpx;
|
||||
padding: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 6rpx;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2rpx rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.form-picker {
|
||||
width: 100%;
|
||||
height: 60rpx;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 6rpx;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.picker-display {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.form-switch {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
/* 筛选规则 */
|
||||
.rules-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.rules-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.rule-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #e4e7ed;
|
||||
}
|
||||
|
||||
.rule-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.rule-label {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.rule-control {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 提示信息 */
|
||||
.tips-section {
|
||||
padding: 32rpx;
|
||||
background-color: #ecf5ff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.custom-fields-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.fields-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.field-item {
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
min-height: 160rpx;
|
||||
font-size: 28rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.rules-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.tips-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
646
src/pages/mine/data-logs.vue
Normal file
646
src/pages/mine/data-logs.vue
Normal file
@@ -0,0 +1,646 @@
|
||||
<template>
|
||||
<view class="data-logs-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">数据相关</view>
|
||||
<view class="header-right"></view>
|
||||
</view>
|
||||
|
||||
<!-- 标签切换 -->
|
||||
<view class="tab-container">
|
||||
<view class="tab-item" :class="{ active: activeTab === 'logs' }" @click="switchTab('logs')">
|
||||
操作日志
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: activeTab === 'backup' }" @click="switchTab('backup')">
|
||||
数据备份记录
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作日志 -->
|
||||
<view v-if="activeTab === 'logs'" class="logs-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">操作日志记录</view>
|
||||
<view class="search-box">
|
||||
<input
|
||||
v-model="logSearch"
|
||||
class="search-input"
|
||||
placeholder="搜索操作内容或操作人"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="logs-list">
|
||||
<view v-for="log in filteredLogs" :key="log.id" class="log-item">
|
||||
<view class="log-header">
|
||||
<view class="log-actor">{{ log.actor }}</view>
|
||||
<view class="log-time">{{ log.time }}</view>
|
||||
</view>
|
||||
<view class="log-content">{{ log.content }}</view>
|
||||
<view class="log-ip">{{ log.ip }}</view>
|
||||
</view>
|
||||
|
||||
<view v-if="filteredLogs.length === 0" class="empty-state">
|
||||
<view class="empty-icon">📋</view>
|
||||
<view class="empty-text">暂无操作日志</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页 -->
|
||||
<view v-if="filteredLogs.length > 0" class="pagination">
|
||||
<view class="page-info">
|
||||
共 {{ filteredLogs.length }} 条记录
|
||||
</view>
|
||||
<view class="page-controls">
|
||||
<view class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
||||
上一页
|
||||
</view>
|
||||
<view class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
||||
下一页
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据备份记录 -->
|
||||
<view v-else class="backup-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">数据备份记录</view>
|
||||
<view class="backup-info">
|
||||
<view class="info-text">备份操作由平台控制</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="backup-list">
|
||||
<view v-for="backup in backupRecords" :key="backup.id" class="backup-item">
|
||||
<view class="backup-header">
|
||||
<view class="backup-time">{{ backup.time }}</view>
|
||||
<view class="backup-status" :class="backup.status">
|
||||
{{ backup.statusText }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="backup-details">
|
||||
<view class="detail-item">
|
||||
<view class="detail-label">备份类型:</view>
|
||||
<view class="detail-value">{{ backup.type }}</view>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<view class="detail-label">备份大小:</view>
|
||||
<view class="detail-value">{{ backup.size }}</view>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<view class="detail-label">备份文件:</view>
|
||||
<view class="detail-value">{{ backup.fileName }}</view>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<view class="detail-label">操作人:</view>
|
||||
<view class="detail-value">{{ backup.operator }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="backup-actions">
|
||||
<view class="action-btn view-btn" @click="viewBackup(backup.id)">
|
||||
查看详情
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="backupRecords.length === 0" class="empty-state">
|
||||
<view class="empty-icon">💾</view>
|
||||
<view class="empty-text">暂无备份记录</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-title">注意事项</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">• 操作日志仅记录核心操作,保留最近30天记录</view>
|
||||
<view class="tip-item">• 数据备份由平台自动执行,不可手动操作</view>
|
||||
<view class="tip-item">• 备份文件仅可查看详情,不可下载或恢复</view>
|
||||
<view class="tip-item">• 如有特殊备份需求,请联系平台管理员</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 标签切换
|
||||
const activeTab = ref('logs')
|
||||
|
||||
// 操作日志相关
|
||||
const logSearch = ref('')
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
|
||||
// 模拟操作日志数据
|
||||
const logs = ref([
|
||||
{
|
||||
id: 1,
|
||||
actor: '张校长',
|
||||
time: '2026-01-29 10:30:45',
|
||||
content: '修改了驾校信息',
|
||||
ip: '192.168.1.100'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
actor: '系统管理员',
|
||||
time: '2026-01-29 09:15:30',
|
||||
content: '创建了新的分销员账号',
|
||||
ip: '192.168.1.200'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
actor: '张校长',
|
||||
time: '2026-01-28 16:45:12',
|
||||
content: '配置了分润规则',
|
||||
ip: '192.168.1.100'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
actor: '分销员-李教练',
|
||||
time: '2026-01-28 14:20:05',
|
||||
content: '生成了推广二维码',
|
||||
ip: '192.168.1.150'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
actor: '系统',
|
||||
time: '2026-01-28 00:00:00',
|
||||
content: '自动执行数据备份',
|
||||
ip: '127.0.0.1'
|
||||
}
|
||||
])
|
||||
|
||||
// 模拟备份记录数据
|
||||
const backupRecords = ref([
|
||||
{
|
||||
id: 1,
|
||||
time: '2026-01-29 00:00:00',
|
||||
status: 'success',
|
||||
statusText: '备份成功',
|
||||
type: '自动备份',
|
||||
size: '128 MB',
|
||||
fileName: 'backup_20260129000000.sql',
|
||||
operator: '系统自动'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
time: '2026-01-28 00:00:00',
|
||||
status: 'success',
|
||||
statusText: '备份成功',
|
||||
type: '自动备份',
|
||||
size: '125 MB',
|
||||
fileName: 'backup_20260128000000.sql',
|
||||
operator: '系统自动'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
time: '2026-01-27 00:00:00',
|
||||
status: 'success',
|
||||
statusText: '备份成功',
|
||||
type: '自动备份',
|
||||
size: '122 MB',
|
||||
fileName: 'backup_20260127000000.sql',
|
||||
operator: '系统自动'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
time: '2026-01-26 10:00:00',
|
||||
status: 'success',
|
||||
statusText: '备份成功',
|
||||
type: '手动备份',
|
||||
size: '120 MB',
|
||||
fileName: 'backup_20260126100000.sql',
|
||||
operator: '平台管理员'
|
||||
}
|
||||
])
|
||||
|
||||
// 计算过滤后的日志
|
||||
const filteredLogs = computed(() => {
|
||||
if (!logSearch.value) {
|
||||
return logs.value
|
||||
}
|
||||
return logs.value.filter(log => {
|
||||
return log.actor.includes(logSearch.value) || log.content.includes(logSearch.value)
|
||||
})
|
||||
})
|
||||
|
||||
// 计算总页数
|
||||
const totalPages = computed(() => {
|
||||
return Math.ceil(filteredLogs.value.length / pageSize.value)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取操作日志和备份记录
|
||||
// loadOperationLogs()
|
||||
// loadBackupRecords()
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 切换标签
|
||||
function switchTab(tab) {
|
||||
activeTab.value = tab
|
||||
}
|
||||
|
||||
// 上一页
|
||||
function prevPage() {
|
||||
if (currentPage.value > 1) {
|
||||
currentPage.value--
|
||||
}
|
||||
}
|
||||
|
||||
// 下一页
|
||||
function nextPage() {
|
||||
if (currentPage.value < totalPages.value) {
|
||||
currentPage.value++
|
||||
}
|
||||
}
|
||||
|
||||
// 查看备份详情
|
||||
function viewBackup(backupId) {
|
||||
uni.showModal({
|
||||
title: '备份详情',
|
||||
content: '备份详情查看功能正在开发中',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.data-logs-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
/* 标签切换 */
|
||||
.tab-container {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 24rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 日志和备份通用样式 */
|
||||
.logs-section,
|
||||
.backup-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* 搜索框 */
|
||||
.search-box {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 300rpx;
|
||||
height: 60rpx;
|
||||
padding: 0 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 操作日志 */
|
||||
.logs-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.log-actor {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.log-time {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
font-size: 26rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.log-ip {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 数据备份 */
|
||||
.backup-info {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-text {
|
||||
font-size: 24rpx;
|
||||
color: #f56c6c;
|
||||
padding: 8rpx 16rpx;
|
||||
background-color: #fef0f0;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.backup-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.backup-item {
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.backup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.backup-time {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.backup-status {
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.backup-status.success {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.backup-status.failed {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.backup-details {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
margin-bottom: 12rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: #909399;
|
||||
width: 120rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.backup-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.view-btn {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 100rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 分页 */
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 32rpx;
|
||||
padding-top: 24rpx;
|
||||
border-top: 1rpx solid #e4e7ed;
|
||||
}
|
||||
|
||||
.page-info {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.page-controls {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.page-btn {
|
||||
padding: 8rpx 24rpx;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.page-btn:hover {
|
||||
border-color: #409eff;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.page-btn.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* 提示信息 */
|
||||
.tips-section {
|
||||
padding: 32rpx;
|
||||
background-color: #ecf5ff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.data-logs-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.logs-section,
|
||||
.backup-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.log-item,
|
||||
.backup-item {
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 400rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
560
src/pages/mine/help-center.vue
Normal file
560
src/pages/mine/help-center.vue
Normal file
@@ -0,0 +1,560 @@
|
||||
<template>
|
||||
<view class="help-center-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">帮助中心</view>
|
||||
<view class="header-right"></view>
|
||||
</view>
|
||||
|
||||
<!-- 常见问题 -->
|
||||
<view class="faq-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">常见问题</view>
|
||||
<view class="search-box">
|
||||
<input
|
||||
v-model="faqSearch"
|
||||
class="search-input"
|
||||
placeholder="搜索问题"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="faq-list">
|
||||
<view
|
||||
v-for="(faq, index) in filteredFaqs"
|
||||
:key="faq.id"
|
||||
class="faq-item"
|
||||
@click="toggleFaq(index)"
|
||||
>
|
||||
<view class="faq-header">
|
||||
<view class="faq-question">{{ faq.question }}</view>
|
||||
<view class="faq-icon">{{ expandedFaq === index ? '▼' : '▶' }}</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="expandedFaq === index"
|
||||
class="faq-answer"
|
||||
>
|
||||
{{ faq.answer }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="filteredFaqs.length === 0" class="empty-state">
|
||||
<view class="empty-icon">❓</view>
|
||||
<view class="empty-text">暂无相关问题</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用指南 -->
|
||||
<view class="guide-section">
|
||||
<view class="section-title">使用指南</view>
|
||||
<view class="guide-list">
|
||||
<view
|
||||
v-for="guide in guides"
|
||||
:key="guide.id"
|
||||
class="guide-item"
|
||||
@click="viewGuide(guide.id)"
|
||||
>
|
||||
<view class="guide-icon">{{ guide.icon }}</view>
|
||||
<view class="guide-info">
|
||||
<view class="guide-title">{{ guide.title }}</view>
|
||||
<view class="guide-desc">{{ guide.description }}</view>
|
||||
</view>
|
||||
<view class="guide-arrow">→</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系客服 -->
|
||||
<view class="contact-section">
|
||||
<view class="section-title">联系客服</view>
|
||||
<view class="contact-info">
|
||||
<view class="contact-item">
|
||||
<view class="contact-icon">📞</view>
|
||||
<view class="contact-details">
|
||||
<view class="contact-label">客服电话</view>
|
||||
<view class="contact-value">400-123-4567</view>
|
||||
</view>
|
||||
<view class="contact-action" @click="callService">
|
||||
拨打
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="contact-item">
|
||||
<view class="contact-icon">💬</view>
|
||||
<view class="contact-details">
|
||||
<view class="contact-label">在线客服</view>
|
||||
<view class="contact-value">工作时间:9:00-18:00</view>
|
||||
</view>
|
||||
<view class="contact-action" @click="onlineService">
|
||||
咨询
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="contact-item">
|
||||
<view class="contact-icon">📧</view>
|
||||
<view class="contact-details">
|
||||
<view class="contact-label">邮箱</view>
|
||||
<view class="contact-value">support@shunda.com</view>
|
||||
</view>
|
||||
<view class="contact-action" @click="sendEmail">
|
||||
发送
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from "vue"
|
||||
|
||||
// 常见问题
|
||||
const faqs = ref([
|
||||
{
|
||||
id: 1,
|
||||
question: '如何修改个人密码?',
|
||||
answer: '在个人中心页面,点击"个人账号管理",然后选择"密码修改",按照提示输入当前密码和新密码即可完成修改。密码修改后需要重新登录。'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
question: '如何查看分销业绩?',
|
||||
answer: '在工作页面的"统计分析"模块中,点击"分销业绩统计",即可查看您的分销业绩数据,包括总提成、扫码数、付费人数等核心指标。'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
question: '如何生成推广二维码?',
|
||||
answer: '在工作页面的"分销管理"模块中,点击"个人推广管理",即可生成和领取您的专属推广二维码。您可以将二维码分享给学员,学员扫码后将成为您的推广用户。'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
question: '如何给学员赠送会员?',
|
||||
answer: '在工作页面的"会员维护"模块中,点击"赠送会员操作",输入学员信息和赠送时长,即可生成赠送会员的核验码,学员使用核验码即可激活会员。'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
question: '如何查看学员学习情况?',
|
||||
answer: '在工作页面的"学员学情监控"模块中,点击"学员列表管理"查看所有学员,或点击"学情详情查看"输入学员信息查看具体学员的学习数据和进度。'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
question: '如何修改驾校信息?',
|
||||
answer: '在个人中心页面,点击"驾校信息维护",即可查看和编辑驾校的基础信息,包括名称、地址、联系方式等。核心功能开关由平台控制,不可在此修改。'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
question: '如何配置自定义字段?',
|
||||
answer: '在个人中心页面,点击"自定义字段配置",即可添加和管理本驾校专属的自定义字段,用于收集学员的额外信息。您可以设置字段名称、类型、是否必填等属性。'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
question: '如何查看操作日志?',
|
||||
answer: '在个人中心页面,点击"数据相关",然后选择"操作日志"标签,即可查看本驾校的操作日志记录,包括操作人、操作内容、操作时间等信息。'
|
||||
}
|
||||
])
|
||||
|
||||
// 使用指南
|
||||
const guides = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '分销员操作指南',
|
||||
description: '详细了解如何使用分销功能,包括生成二维码、查看业绩等',
|
||||
icon: '📱'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '管理员操作指南',
|
||||
description: '了解管理员的各项功能,包括账号管理、分润配置等',
|
||||
icon: '🏢'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '学员管理指南',
|
||||
description: '学习如何管理学员信息和监控学习情况',
|
||||
icon: '🎓'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '会员管理指南',
|
||||
description: '了解会员系统的使用方法,包括订单处理、赠送会员等',
|
||||
icon: '👥'
|
||||
}
|
||||
])
|
||||
|
||||
// 搜索和展开状态
|
||||
const faqSearch = ref('')
|
||||
const expandedFaq = ref(null)
|
||||
|
||||
// 过滤后的常见问题
|
||||
const filteredFaqs = computed(() => {
|
||||
if (!faqSearch.value) {
|
||||
return faqs.value
|
||||
}
|
||||
return faqs.value.filter(faq => {
|
||||
return faq.question.includes(faqSearch.value) || faq.answer.includes(faqSearch.value)
|
||||
})
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 切换FAQ展开状态
|
||||
function toggleFaq(index) {
|
||||
expandedFaq.value = expandedFaq.value === index ? null : index
|
||||
}
|
||||
|
||||
// 查看使用指南
|
||||
function viewGuide(guideId) {
|
||||
uni.showModal({
|
||||
title: '使用指南',
|
||||
content: '使用指南详情页面正在开发中',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
|
||||
// 联系客服
|
||||
function callService() {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: '4001234567'
|
||||
})
|
||||
}
|
||||
|
||||
function onlineService() {
|
||||
uni.showModal({
|
||||
title: '在线客服',
|
||||
content: '在线客服功能正在开发中,请通过电话联系我们',
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
|
||||
function sendEmail() {
|
||||
uni.showModal({
|
||||
title: '发送邮件',
|
||||
content: '是否打开邮件应用发送邮件?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
uni.setClipboardData({
|
||||
data: 'support@shunda.com',
|
||||
success: function() {
|
||||
uni.showToast({ title: '邮箱已复制,请粘贴到邮件应用', icon: 'success' })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.help-center-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
/* 常见问题 */
|
||||
.faq-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 300rpx;
|
||||
height: 60rpx;
|
||||
padding: 0 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.faq-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.faq-item {
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.faq-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.faq-header:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.faq-question {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.faq-icon {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.faq-answer {
|
||||
padding: 0 24rpx 24rpx;
|
||||
font-size: 26rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 使用指南 */
|
||||
.guide-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.guide-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.guide-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.guide-item:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.guide-icon {
|
||||
font-size: 48rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.guide-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.guide-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.guide-desc {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.guide-arrow {
|
||||
font-size: 32rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 联系客服 */
|
||||
.contact-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.contact-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid #e4e7ed;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
font-size: 48rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.contact-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.contact-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.contact-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.contact-action {
|
||||
padding: 12rpx 24rpx;
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 100rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.help-center-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.faq-section,
|
||||
.guide-section,
|
||||
.contact-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.faq-question {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.faq-answer {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.guide-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.guide-desc {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.contact-value {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,187 +1,577 @@
|
||||
<template>
|
||||
<view class="mine-container" :style="{height: `${windowHeight}px`}">
|
||||
<!--顶部个人信息栏-->
|
||||
<view class="header-section">
|
||||
<view class="flex padding justify-between">
|
||||
<view class="flex align-center">
|
||||
<view v-if="!avatar" class="cu-avatar xl round bg-white">
|
||||
<view class="iconfont icon-people text-gray icon"></view>
|
||||
<view class="mine-container">
|
||||
<!-- 欢迎信息 -->
|
||||
<view class="welcome-section">
|
||||
<view class="user-info">
|
||||
<view class="avatar">
|
||||
<view class="avatar-icon">{{ userInitial }}</view>
|
||||
</view>
|
||||
<image v-if="avatar" @click="handleToAvatar" :src="avatar" class="cu-avatar xl round" mode="widthFix">
|
||||
</image>
|
||||
<view v-if="!name" @click="handleToLogin" class="login-tip">
|
||||
点击登录
|
||||
</view>
|
||||
<view v-if="name" @click="handleToInfo" class="user-info">
|
||||
<view class="u_title">
|
||||
用户名:{{ name }}
|
||||
<view class="user-details">
|
||||
<view class="user-name">{{ name }}</view>
|
||||
<view class="user-role">
|
||||
<text v-if="userRole === 'admin'">驾校管理员</text>
|
||||
<text v-else>分销员</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view @click="handleToInfo" class="flex align-center">
|
||||
<text>个人信息</text>
|
||||
<view class="iconfont icon-right"></view>
|
||||
<view class="user-stats">
|
||||
<view class="stat-item">
|
||||
<view class="stat-value">{{ stats.scanCount }}</view>
|
||||
<view class="stat-label">扫码数</view>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<view class="stat-value">{{ stats.paidCount }}</view>
|
||||
<view class="stat-label">付费人数</view>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<view class="stat-value">{{ stats.totalProfit }}</view>
|
||||
<view class="stat-label">提成总额</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content-section">
|
||||
<view class="mine-actions grid col-4 text-center">
|
||||
<view class="action-item" @click="handleJiaoLiuQun">
|
||||
<view class="iconfont icon-friendfill text-pink icon"></view>
|
||||
<text class="text">交流群</text>
|
||||
<!-- 角色切换 -->
|
||||
<view v-if="userRole === 'admin'" class="role-switch">
|
||||
<view class="role-tab" :class="{ active: currentView === 'admin' }" @click="switchView('admin')">
|
||||
管理员功能
|
||||
</view>
|
||||
<view class="action-item" @click="handleBuilding">
|
||||
<view class="iconfont icon-service text-blue icon"></view>
|
||||
<text class="text">在线客服</text>
|
||||
</view>
|
||||
<view class="action-item" @click="handleBuilding">
|
||||
<view class="iconfont icon-community text-mauve icon"></view>
|
||||
<text class="text">反馈社区</text>
|
||||
</view>
|
||||
<view class="action-item" @click="handleBuilding">
|
||||
<view class="iconfont icon-dianzan text-green icon"></view>
|
||||
<text class="text">点赞我们</text>
|
||||
<view class="role-tab" :class="{ active: currentView === 'distributor' }" @click="switchView('distributor')">
|
||||
分销员功能
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="menu-list">
|
||||
<view class="list-cell list-cell-arrow" @click="handleToEditInfo">
|
||||
<view class="menu-item-box">
|
||||
<view class="iconfont icon-user menu-icon"></view>
|
||||
<view>编辑资料</view>
|
||||
<!-- 管理员功能 -->
|
||||
<view v-if="currentView === 'admin'" class="feature-section">
|
||||
<view class="section-title">驾校管理</view>
|
||||
<view class="feature-grid">
|
||||
<!-- 驾校信息维护 -->
|
||||
<view class="feature-card" @click="goToSchoolInfo">
|
||||
<view class="feature-icon school-icon">
|
||||
<view class="icon-text">🏢</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">驾校信息维护</view>
|
||||
<view class="feature-desc">查看、编辑本驾校基础信息</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list-cell list-cell-arrow" @click="handleHelp">
|
||||
<view class="menu-item-box">
|
||||
<view class="iconfont icon-help menu-icon"></view>
|
||||
<view>常见问题</view>
|
||||
|
||||
<!-- 自定义字段配置 -->
|
||||
<view class="feature-card" @click="goToCustomFields">
|
||||
<view class="feature-icon field-icon">
|
||||
<view class="icon-text">📝</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">自定义字段配置</view>
|
||||
<view class="feature-desc">配置本驾校专属自定义字段</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list-cell list-cell-arrow" @click="handleAbout">
|
||||
<view class="menu-item-box">
|
||||
<view class="iconfont icon-aixin menu-icon"></view>
|
||||
<view>关于我们</view>
|
||||
|
||||
<!-- 数据相关 -->
|
||||
<view class="feature-card" @click="goToDataLogs">
|
||||
<view class="feature-icon data-icon">
|
||||
<view class="icon-text">📋</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">数据相关</view>
|
||||
<view class="feature-desc">查看操作日志和数据备份记录</view>
|
||||
</view>
|
||||
<view class="list-cell list-cell-arrow" @click="handleToSetting">
|
||||
<view class="menu-item-box">
|
||||
<view class="iconfont icon-setting menu-icon"></view>
|
||||
<view>应用设置</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分销员功能 -->
|
||||
<view v-else class="feature-section">
|
||||
<view class="section-title">个人设置</view>
|
||||
<view class="feature-grid">
|
||||
<!-- 个人资料修改 -->
|
||||
<view class="feature-card" @click="goToPersonalInfo">
|
||||
<view class="feature-icon profile-icon">
|
||||
<view class="icon-text">👤</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">个人资料修改</view>
|
||||
<view class="feature-desc">修改个人基本信息</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 密码修改 -->
|
||||
<view class="feature-card" @click="goToPasswordChange">
|
||||
<view class="feature-icon password-icon">
|
||||
<view class="icon-text">🔒</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">密码修改</view>
|
||||
<view class="feature-desc">修改登录密码</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 驾校信息查看 -->
|
||||
<view class="feature-card" @click="goToSchoolInfo">
|
||||
<view class="feature-icon school-icon">
|
||||
<view class="icon-text">🏢</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">驾校信息查看</view>
|
||||
<view class="feature-desc">查看本驾校基础信息</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 通用功能 -->
|
||||
<view class="feature-section">
|
||||
<view class="section-title">通用功能</view>
|
||||
<view class="feature-grid">
|
||||
<!-- 帮助中心 -->
|
||||
<view class="feature-card" @click="goToHelpCenter">
|
||||
<view class="feature-icon help-icon">
|
||||
<view class="icon-text">❓</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">帮助中心</view>
|
||||
<view class="feature-desc">常见问题和使用指南</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 关于我们 -->
|
||||
<view class="feature-card" @click="goToAboutUs">
|
||||
<view class="feature-icon about-icon">
|
||||
<view class="icon-text">ℹ️</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">关于我们</view>
|
||||
<view class="feature-desc">系统版本和公司信息</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 退出登录 -->
|
||||
<view class="feature-card logout-card" @click="logout">
|
||||
<view class="feature-icon logout-icon">
|
||||
<view class="icon-text">🚪</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">退出登录</view>
|
||||
<view class="feature-desc">退出当前账号</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useUserStore } from '@/store'
|
||||
import { computed , getCurrentInstance } from "vue"
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const name = useUserStore().name
|
||||
const avatar = computed(() => useUserStore().avatar)
|
||||
const windowHeight = computed(() => uni.getSystemInfoSync().windowHeight - 50)
|
||||
// 用户信息
|
||||
const name = ref('张教练')
|
||||
const userRole = ref('admin') // 模拟角色,实际应从登录状态获取
|
||||
const currentView = ref('admin')
|
||||
|
||||
function handleToInfo() {
|
||||
proxy.$tab.navigateTo('/pages/mine/info/index')
|
||||
// 模拟统计数据
|
||||
const stats = ref({
|
||||
scanCount: 1234,
|
||||
paidCount: 456,
|
||||
totalProfit: '¥12,345.67'
|
||||
})
|
||||
|
||||
// 计算用户名首字母
|
||||
const userInitial = computed(() => {
|
||||
return name.value ? name.value.charAt(0).toUpperCase() : 'U'
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从登录状态或接口获取用户信息
|
||||
// loadUserData()
|
||||
})
|
||||
|
||||
// 切换视图
|
||||
function switchView(view) {
|
||||
currentView.value = view
|
||||
}
|
||||
|
||||
function handleToEditInfo() {
|
||||
proxy.$tab.navigateTo('/pages/mine/info/edit')
|
||||
// 管理员功能跳转
|
||||
function goToSchoolInfo() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/school-info'
|
||||
})
|
||||
}
|
||||
|
||||
function handleToSetting() {
|
||||
proxy.$tab.navigateTo('/pages/mine/setting/index')
|
||||
function goToCustomFields() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/custom-fields'
|
||||
})
|
||||
}
|
||||
|
||||
function handleToLogin() {
|
||||
proxy.$tab.reLaunch('/pages/login')
|
||||
function goToDataLogs() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/data-logs'
|
||||
})
|
||||
}
|
||||
|
||||
function handleToAvatar() {
|
||||
proxy.$tab.navigateTo('/pages/mine/avatar/index')
|
||||
// 分销员功能跳转
|
||||
function goToPersonalInfo() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/personal-info'
|
||||
})
|
||||
}
|
||||
|
||||
function handleHelp() {
|
||||
proxy.$tab.navigateTo('/pages/mine/help/index')
|
||||
function goToPasswordChange() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/password-change'
|
||||
})
|
||||
}
|
||||
|
||||
function handleAbout() {
|
||||
proxy.$tab.navigateTo('/pages/mine/about/index')
|
||||
// 通用功能跳转
|
||||
function goToHelpCenter() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/help-center'
|
||||
})
|
||||
}
|
||||
|
||||
function handleJiaoLiuQun() {
|
||||
proxy.$modal.showToast('QQ群:①133713780(满)、②146013835(满)、③189091635')
|
||||
function goToAboutUs() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/about-us'
|
||||
})
|
||||
}
|
||||
|
||||
function handleBuilding() {
|
||||
proxy.$modal.showToast('模块建设中~')
|
||||
// 退出登录
|
||||
function logout() {
|
||||
uni.showModal({
|
||||
title: '退出登录',
|
||||
content: '确定要退出当前账号吗?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
// 实际项目中应清除登录状态
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
background-color: #f5f6f7;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.mine-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
|
||||
.header-section {
|
||||
padding: 15px 15px 45px 15px;
|
||||
background-color: #3c96f3;
|
||||
color: white;
|
||||
|
||||
.login-tip {
|
||||
font-size: 18px;
|
||||
margin-left: 10px;
|
||||
padding: 20rpx;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.cu-avatar {
|
||||
border: 2px solid #eaeaea;
|
||||
|
||||
.icon {
|
||||
font-size: 40px;
|
||||
}
|
||||
/* 欢迎信息区域 */
|
||||
.welcome-section {
|
||||
background: linear-gradient(135deg, #409eff 0%, #667eea 100%);
|
||||
border-radius: 20rpx;
|
||||
padding: 40rpx;
|
||||
margin-bottom: 30rpx;
|
||||
color: #fff;
|
||||
box-shadow: 0 8rpx 32rpx rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
margin-left: 15px;
|
||||
|
||||
.u_title {
|
||||
font-size: 18px;
|
||||
line-height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.avatar-icon {
|
||||
font-size: 64rpx;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.user-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.user-role {
|
||||
font-size: 24rpx;
|
||||
opacity: 0.9;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.user-stats {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding-top: 24rpx;
|
||||
border-top: 1rpx solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 20rpx;
|
||||
opacity: 0.8;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* 角色切换 */
|
||||
.role-switch {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 30rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.role-tab {
|
||||
flex: 1;
|
||||
padding: 24rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.role-tab.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* 功能区域 */
|
||||
.feature-section {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 24rpx;
|
||||
padding-left: 12rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
/* 功能卡片 */
|
||||
.feature-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.feature-card:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logout-card {
|
||||
border: 1rpx solid #f56c6c;
|
||||
}
|
||||
|
||||
/* 图标容器 */
|
||||
.feature-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 图标文本样式 */
|
||||
.icon-text {
|
||||
font-size: 36rpx;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 各模块颜色 */
|
||||
.school-icon {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.field-icon {
|
||||
background-color: #f0f9eb;
|
||||
}
|
||||
|
||||
.data-icon {
|
||||
background-color: #fdf6ec;
|
||||
}
|
||||
|
||||
.profile-icon {
|
||||
background-color: #fef0f0;
|
||||
}
|
||||
|
||||
.password-icon {
|
||||
background-color: #f4f4f5;
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
background-color: #f0f5ff;
|
||||
}
|
||||
|
||||
.about-icon {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.logout-icon {
|
||||
background-color: #fef0f0;
|
||||
}
|
||||
|
||||
/* 功能信息 */
|
||||
.feature-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 22rpx;
|
||||
color: #909399;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.mine-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.welcome-section {
|
||||
padding: 50rpx;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.user-role {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 36rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content-section {
|
||||
position: relative;
|
||||
top: -50px;
|
||||
|
||||
.mine-actions {
|
||||
margin: 15px 15px;
|
||||
padding: 20px 0px;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
|
||||
.action-item {
|
||||
.icon {
|
||||
font-size: 28px;
|
||||
/* 平板和大屏响应式 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.mine-container {
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
.text {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
margin: 8px 0px;
|
||||
.welcome-section {
|
||||
padding: 60rpx;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 36rpx;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
font-size: 52rpx;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
501
src/pages/mine/password-change.vue
Normal file
501
src/pages/mine/password-change.vue
Normal file
@@ -0,0 +1,501 @@
|
||||
<template>
|
||||
<view class="password-change-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">密码修改</view>
|
||||
<view class="header-right" @click="savePassword">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 密码修改表单 -->
|
||||
<view class="form-section">
|
||||
<view class="form-group">
|
||||
<view class="form-label">当前密码</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="passwordForm.oldPassword"
|
||||
class="form-input"
|
||||
placeholder="请输入当前密码"
|
||||
maxlength="20"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
/>
|
||||
<view class="password-toggle" @click="togglePassword">
|
||||
{{ showPassword ? '🙈' : '👁️' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">新密码</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="passwordForm.newPassword"
|
||||
class="form-input"
|
||||
placeholder="请输入新密码"
|
||||
maxlength="20"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
/>
|
||||
<view class="password-toggle" @click="togglePassword">
|
||||
{{ showPassword ? '🙈' : '👁️' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">确认新密码</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="passwordForm.confirmPassword"
|
||||
class="form-input"
|
||||
placeholder="请再次输入新密码"
|
||||
maxlength="20"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
/>
|
||||
<view class="password-toggle" @click="togglePassword">
|
||||
{{ showPassword ? '🙈' : '👁️' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 密码强度提示 -->
|
||||
<view class="strength-section">
|
||||
<view class="section-title">密码强度要求</view>
|
||||
<view class="strength-tips">
|
||||
<view class="tip-item" :class="{ active: passwordForm.newPassword.length >= 8 }">
|
||||
• 密码长度至少8位
|
||||
</view>
|
||||
<view class="tip-item" :class="{ active: /[A-Z]/.test(passwordForm.newPassword) }">
|
||||
• 包含大写字母
|
||||
</view>
|
||||
<view class="tip-item" :class="{ active: /[a-z]/.test(passwordForm.newPassword) }">
|
||||
• 包含小写字母
|
||||
</view>
|
||||
<view class="tip-item" :class="{ active: /[0-9]/.test(passwordForm.newPassword) }">
|
||||
• 包含数字
|
||||
</view>
|
||||
<view class="tip-item" :class="{ active: /[!@#$%^&*(),.?":{}|<>]/.test(passwordForm.newPassword) }">
|
||||
• 包含特殊字符
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 密码强度指示器 -->
|
||||
<view class="strength-indicator">
|
||||
<view class="strength-label">密码强度:</view>
|
||||
<view class="strength-bars">
|
||||
<view
|
||||
class="strength-bar"
|
||||
:class="getStrengthClass()"
|
||||
></view>
|
||||
<view class="strength-text">{{ getStrengthText() }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作提示 -->
|
||||
<view class="operation-tips">
|
||||
<view class="tips-title">操作提示</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">• 请确保新密码符合强度要求</view>
|
||||
<view class="tip-item">• 密码修改后需要重新登录</view>
|
||||
<view class="tip-item">• 如忘记当前密码,请联系管理员重置</view>
|
||||
<view class="tip-item">• 请妥善保管您的密码,不要泄露给他人</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from "vue"
|
||||
|
||||
// 密码表单
|
||||
const passwordForm = ref({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
})
|
||||
|
||||
// 显示密码
|
||||
const showPassword = ref(false)
|
||||
|
||||
// 切换密码显示状态
|
||||
function togglePassword() {
|
||||
showPassword.value = !showPassword.value
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 获取密码强度等级
|
||||
function getPasswordStrength() {
|
||||
const password = passwordForm.value.newPassword
|
||||
if (!password) return 0
|
||||
|
||||
let strength = 0
|
||||
if (password.length >= 8) strength++
|
||||
if (/[A-Z]/.test(password)) strength++
|
||||
if (/[a-z]/.test(password)) strength++
|
||||
if (/[0-9]/.test(password)) strength++
|
||||
if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) strength++
|
||||
|
||||
return strength
|
||||
}
|
||||
|
||||
// 获取密码强度样式类
|
||||
function getStrengthClass() {
|
||||
const strength = getPasswordStrength()
|
||||
switch (strength) {
|
||||
case 0: return 'weak'
|
||||
case 1: return 'weak'
|
||||
case 2: return 'medium'
|
||||
case 3: return 'medium'
|
||||
case 4: return 'strong'
|
||||
case 5: return 'strong'
|
||||
default: return 'weak'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取密码强度文本
|
||||
function getStrengthText() {
|
||||
const strength = getPasswordStrength()
|
||||
switch (strength) {
|
||||
case 0: return '未设置'
|
||||
case 1: return '弱'
|
||||
case 2: return '较弱'
|
||||
case 3: return '中等'
|
||||
case 4: return '强'
|
||||
case 5: return '很强'
|
||||
default: return '未设置'
|
||||
}
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
function validatePassword() {
|
||||
if (!passwordForm.value.oldPassword) {
|
||||
uni.showToast({ title: '请输入当前密码', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
if (!passwordForm.value.newPassword) {
|
||||
uni.showToast({ title: '请输入新密码', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
if (passwordForm.value.newPassword.length < 8) {
|
||||
uni.showToast({ title: '新密码长度至少8位', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
if (passwordForm.value.newPassword !== passwordForm.value.confirmPassword) {
|
||||
uni.showToast({ title: '两次输入的新密码不一致', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
if (passwordForm.value.newPassword === passwordForm.value.oldPassword) {
|
||||
uni.showToast({ title: '新密码不能与当前密码相同', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 保存密码
|
||||
function savePassword() {
|
||||
if (!validatePassword()) {
|
||||
return
|
||||
}
|
||||
|
||||
// 实际项目中应调用接口修改密码
|
||||
uni.showLoading({ title: '修改中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showModal({
|
||||
title: '修改成功',
|
||||
content: '密码修改成功,请重新登录',
|
||||
showCancel: false,
|
||||
success: function() {
|
||||
// 实际项目中应跳转到登录页面
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.password-change-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
.form-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
padding: 0 100rpx 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f9f9f9;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2rpx rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.password-toggle {
|
||||
position: absolute;
|
||||
right: 24rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 32rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 密码强度 */
|
||||
.strength-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 24rpx;
|
||||
padding-left: 12rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.strength-tips {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.tip-item.active {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.strength-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.strength-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.strength-bars {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.strength-bar {
|
||||
height: 8rpx;
|
||||
border-radius: 4rpx;
|
||||
flex: 1;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.strength-bar.weak {
|
||||
background-color: #f56c6c;
|
||||
}
|
||||
|
||||
.strength-bar.medium {
|
||||
background-color: #e6a23c;
|
||||
}
|
||||
|
||||
.strength-bar.strong {
|
||||
background-color: #67c23a;
|
||||
}
|
||||
|
||||
.strength-text {
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.strength-text.weak {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.strength-text.medium {
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
.strength-text.strong {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
/* 操作提示 */
|
||||
.operation-tips {
|
||||
padding: 32rpx;
|
||||
background-color: #ecf5ff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.password-change-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
height: 100rpx;
|
||||
font-size: 32rpx;
|
||||
padding: 0 120rpx 0 32rpx;
|
||||
}
|
||||
|
||||
.strength-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.operation-tips {
|
||||
padding: 40rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
499
src/pages/mine/personal-info.vue
Normal file
499
src/pages/mine/personal-info.vue
Normal file
@@ -0,0 +1,499 @@
|
||||
<template>
|
||||
<view class="personal-info-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">个人资料修改</view>
|
||||
<view class="header-right" @click="saveInfo">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 个人信息表单 -->
|
||||
<view class="form-section">
|
||||
<view class="avatar-section">
|
||||
<view class="avatar-preview" @click="chooseAvatar">
|
||||
<view v-if="userInfo.avatar" class="avatar-img">
|
||||
<image :src="userInfo.avatar" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view v-else class="avatar-placeholder">
|
||||
<view class="avatar-icon">{{ userInitial }}</view>
|
||||
<view class="avatar-tip">点击更换头像</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">姓名</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="userInfo.name"
|
||||
class="form-input"
|
||||
placeholder="请输入姓名"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">手机号</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="userInfo.phone"
|
||||
class="form-input"
|
||||
placeholder="请输入手机号"
|
||||
maxlength="15"
|
||||
type="number"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">邮箱</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="userInfo.email"
|
||||
class="form-input"
|
||||
placeholder="请输入邮箱"
|
||||
maxlength="50"
|
||||
type="email"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">性别</view>
|
||||
<view class="form-control">
|
||||
<picker
|
||||
v-model="userInfo.gender"
|
||||
:range="genders"
|
||||
class="form-picker"
|
||||
>
|
||||
<view class="picker-display">{{ userInfo.gender || '请选择性别' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">所属驾校</view>
|
||||
<view class="form-control">
|
||||
<view class="form-text">{{ userInfo.school || '顺达驾校' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">职位</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="userInfo.position"
|
||||
class="form-input"
|
||||
placeholder="请输入职位"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">简介</view>
|
||||
<view class="form-control">
|
||||
<textarea
|
||||
v-model="userInfo.bio"
|
||||
class="form-textarea"
|
||||
placeholder="请输入个人简介"
|
||||
maxlength="200"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 账号信息 -->
|
||||
<view class="account-section">
|
||||
<view class="section-title">账号信息</view>
|
||||
<view class="account-info">
|
||||
<view class="info-item">
|
||||
<view class="info-label">账号ID</view>
|
||||
<view class="info-value">{{ userInfo.id || '10001' }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">注册时间</view>
|
||||
<view class="info-value">{{ userInfo.registerTime || '2026-01-01' }}</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<view class="info-label">最后登录</view>
|
||||
<view class="info-value">{{ userInfo.lastLogin || '2026-01-29' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 性别选项
|
||||
const genders = ['男', '女', '保密']
|
||||
|
||||
// 用户信息
|
||||
const userInfo = ref({
|
||||
name: '李教练',
|
||||
phone: '13900139000',
|
||||
email: 'li@shunda.com',
|
||||
gender: '男',
|
||||
school: '顺达驾校',
|
||||
position: '科目二教练',
|
||||
bio: '拥有10年驾驶教学经验,擅长科目二倒车入库教学',
|
||||
id: '10002',
|
||||
registerTime: '2026-01-15',
|
||||
lastLogin: '2026-01-29 10:30:00'
|
||||
})
|
||||
|
||||
// 计算用户名首字母
|
||||
const userInitial = computed(() => {
|
||||
return userInfo.value.name ? userInfo.value.name.charAt(0).toUpperCase() : 'U'
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取用户信息
|
||||
// loadUserInfo()
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 选择头像
|
||||
function chooseAvatar() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: function(res) {
|
||||
// 实际项目中应上传图片到服务器
|
||||
userInfo.value.avatar = res.tempFilePaths[0]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 保存个人信息
|
||||
function saveInfo() {
|
||||
// 表单验证
|
||||
if (!userInfo.value.name) {
|
||||
uni.showToast({ title: '请输入姓名', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!userInfo.value.phone) {
|
||||
uni.showToast({ title: '请输入手机号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 实际项目中应调用接口保存信息
|
||||
uni.showLoading({ title: '保存中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
goBack()
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.personal-info-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
.form-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/* 头像部分 */
|
||||
.avatar-section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.avatar-img image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.avatar-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #409eff 0%, #667eea 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.avatar-icon {
|
||||
font-size: 80rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.avatar-tip {
|
||||
font-size: 20rpx;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
padding: 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f9f9f9;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2rpx rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
min-height: 160rpx;
|
||||
padding: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f9f9f9;
|
||||
box-sizing: border-box;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2rpx rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.form-picker {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f9f9f9;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.picker-display {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.form-text {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 账号信息 */
|
||||
.account-section {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 24rpx;
|
||||
padding-left: 12rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #e4e7ed;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.personal-info-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
height: 100rpx;
|
||||
font-size: 32rpx;
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
min-height: 200rpx;
|
||||
font-size: 32rpx;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.form-text {
|
||||
height: 100rpx;
|
||||
font-size: 32rpx;
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.account-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
383
src/pages/mine/school-info.vue
Normal file
383
src/pages/mine/school-info.vue
Normal file
@@ -0,0 +1,383 @@
|
||||
<template>
|
||||
<view class="school-info-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">驾校信息维护</view>
|
||||
<view class="header-right" @click="saveInfo">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 驾校信息表单 -->
|
||||
<view class="form-section">
|
||||
<view class="form-group">
|
||||
<view class="form-label">驾校名称</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="schoolInfo.name"
|
||||
class="form-input"
|
||||
placeholder="请输入驾校名称"
|
||||
maxlength="50"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">联系人</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="schoolInfo.contact"
|
||||
class="form-input"
|
||||
placeholder="请输入联系人姓名"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">联系电话</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="schoolInfo.phone"
|
||||
class="form-input"
|
||||
placeholder="请输入联系电话"
|
||||
maxlength="15"
|
||||
type="number"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">地址</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="schoolInfo.address"
|
||||
class="form-input"
|
||||
placeholder="请输入驾校地址"
|
||||
maxlength="100"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">邮箱</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="schoolInfo.email"
|
||||
class="form-input"
|
||||
placeholder="请输入邮箱地址"
|
||||
maxlength="50"
|
||||
type="email"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">经营范围</view>
|
||||
<view class="form-control">
|
||||
<textarea
|
||||
v-model="schoolInfo.businessScope"
|
||||
class="form-textarea"
|
||||
placeholder="请输入经营范围"
|
||||
maxlength="200"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<view class="form-label">驾校简介</view>
|
||||
<view class="form-control">
|
||||
<textarea
|
||||
v-model="schoolInfo.description"
|
||||
class="form-textarea"
|
||||
placeholder="请输入驾校简介"
|
||||
maxlength="500"
|
||||
rows="4"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示信息 -->
|
||||
<view class="tips-section">
|
||||
<view class="tips-title">注意事项</view>
|
||||
<view class="tips-content">
|
||||
<view class="tip-item">• 驾校名称、联系人和联系电话为必填项</view>
|
||||
<view class="tip-item">• 核心功能开关由平台控制,不可在此修改</view>
|
||||
<view class="tip-item">• 修改信息后需点击保存按钮生效</view>
|
||||
<view class="tip-item">• 请确保填写的信息真实有效</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue"
|
||||
|
||||
// 驾校信息
|
||||
const schoolInfo = ref({
|
||||
name: '顺达驾校',
|
||||
contact: '张校长',
|
||||
phone: '13800138000',
|
||||
address: '北京市朝阳区建国路88号',
|
||||
email: 'contact@shunda.com',
|
||||
businessScope: '机动车驾驶员培训(小型汽车、大型货车)',
|
||||
description: '顺达驾校成立于2005年,是北京市知名的驾驶员培训机构,拥有专业的教练团队和完善的教学设施,致力于为学员提供优质的驾驶培训服务。'
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取驾校信息
|
||||
// loadSchoolInfo()
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 保存驾校信息
|
||||
function saveInfo() {
|
||||
// 表单验证
|
||||
if (!schoolInfo.value.name) {
|
||||
uni.showToast({ title: '请输入驾校名称', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!schoolInfo.value.contact) {
|
||||
uni.showToast({ title: '请输入联系人', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!schoolInfo.value.phone) {
|
||||
uni.showToast({ title: '请输入联系电话', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 实际项目中应调用接口保存信息
|
||||
uni.showLoading({ title: '保存中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
goBack()
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.school-info-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
.form-section {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
padding: 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f9f9f9;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2rpx rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
min-height: 160rpx;
|
||||
padding: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #f9f9f9;
|
||||
box-sizing: border-box;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2rpx rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
/* 提示信息 */
|
||||
.tips-section {
|
||||
padding: 32rpx;
|
||||
background-color: #ecf5ff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.school-info-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
height: 100rpx;
|
||||
font-size: 32rpx;
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
min-height: 200rpx;
|
||||
font-size: 32rpx;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.tips-section {
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.tips-content {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板和大屏响应式 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.form-section {
|
||||
padding: 50rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
height: 120rpx;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
min-height: 240rpx;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,110 +1,485 @@
|
||||
<template>
|
||||
<view class="work-container">
|
||||
<!-- 轮播图 -->
|
||||
<uni-swiper-dot class="uni-swiper-dot-box" :info="data" :current="current" field="content">
|
||||
<swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper">
|
||||
<swiper-item v-for="(item, index) in data" :key="index">
|
||||
<view class="swiper-item" @click="clickBannerItem(item)">
|
||||
<image :src="item.image" mode="aspectFill" :draggable="false" class="banner-image" />
|
||||
<!-- 账号管理 -->
|
||||
<view class="section">
|
||||
<view class="section-title">账号管理</view>
|
||||
<view class="feature-row">
|
||||
<!-- 管理员功能 -->
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToAccountManage">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">👥</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">账号创建与管控</view>
|
||||
<view class="feature-desc">创建、冻结分销员账号,配置权限</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</uni-swiper-dot>
|
||||
|
||||
<!-- 宫格组件 -->
|
||||
<view class="grid-body">
|
||||
<view class="grid-title">系统功能</view>
|
||||
<uni-grid :column="4" :showBorder="false">
|
||||
<uni-grid-item @click="goToDistributor">
|
||||
<view class="grid-item-box distributor">
|
||||
<view class="icon-container">
|
||||
<uni-icons type="share" size="36" color="#409eff" />
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToQuotaManage">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">🎁</view>
|
||||
</view>
|
||||
<text class="text">分销员管理</text>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">赠会员额度分配</view>
|
||||
<view class="feature-desc">分配分销员每月赠会员额度</view>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
<uni-grid-item @click="showUnderConstruction">
|
||||
<view class="grid-item-box user">
|
||||
<view class="icon-container">
|
||||
<uni-icons type="person-filled" size="36" color="#67c23a" />
|
||||
</view>
|
||||
<text class="text">用户管理</text>
|
||||
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToLogManage">
|
||||
<view class="feature-icon dept-icon">
|
||||
<view class="icon-text">📋</view>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
<uni-grid-item @click="showUnderConstruction">
|
||||
<view class="grid-item-box dept">
|
||||
<view class="icon-container">
|
||||
<uni-icons type="settings-filled" size="36" color="#e6a23c" />
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">操作日志查看</view>
|
||||
<view class="feature-desc">查看账号核心操作日志</view>
|
||||
</view>
|
||||
<text class="text">部门管理</text>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
<uni-grid-item @click="showUnderConstruction">
|
||||
<view class="grid-item-box notice">
|
||||
<view class="icon-container">
|
||||
<uni-icons type="chat-filled" size="36" color="#f56c6c" />
|
||||
|
||||
<!-- 分销员功能 -->
|
||||
<view v-if="userRole === 'distributor'" class="feature-card" @click="goToPersonalAccount">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">👤</view>
|
||||
</view>
|
||||
<text class="text">通知公告</text>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">个人账号管理</view>
|
||||
<view class="feature-desc">修改个人资料、登录密码</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分销管理 -->
|
||||
<view class="section">
|
||||
<view class="section-title">分销管理</view>
|
||||
<view class="feature-row">
|
||||
<!-- 管理员功能 -->
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToDistributorManage">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">👥</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">分销员管理</view>
|
||||
<view class="feature-desc">查看、编辑、批量管理分销员</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToProfitRule">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">💰</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">分润规则配置</view>
|
||||
<view class="feature-desc">配置扫码注册、购买会员分润比例</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToDistributionData">
|
||||
<view class="feature-icon dept-icon">
|
||||
<view class="icon-text">📊</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">分销数据查看</view>
|
||||
<view class="feature-desc">查看推广数据、分润明细</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToQrCodeManage">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">🔗</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">专属二维码管理</view>
|
||||
<view class="feature-desc">批量生成推广二维码</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分销员功能 -->
|
||||
<view v-if="userRole === 'distributor'" class="feature-card" @click="goToPersonalPromotion">
|
||||
<view class="feature-icon log-icon">
|
||||
<view class="icon-text">📱</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">个人推广管理</view>
|
||||
<view class="feature-desc">领取、分享个人推广二维码</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'distributor'" class="feature-card" @click="goToProfitQuery">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">💵</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">分润查询</view>
|
||||
<view class="feature-desc">查看个人提成总额、分润明细</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 学员学情监控 -->
|
||||
<view class="section">
|
||||
<view class="section-title">学员学情监控</view>
|
||||
<view class="feature-row">
|
||||
<view class="feature-card" @click="goToStudentList">
|
||||
<view class="feature-icon dept-icon">
|
||||
<view class="icon-text">🎓</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">学员列表管理</view>
|
||||
<view class="feature-desc">查看、筛选学员列表</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="goToStudentDetail">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">📈</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">学情详情查看</view>
|
||||
<view class="feature-desc">查看学员学习数据、AI充值状态</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="goToLearningAnalysis">
|
||||
<view class="feature-icon log-icon">
|
||||
<view class="icon-text">📊</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">学情统计分析</view>
|
||||
<view class="feature-desc">查看学情数据可视化报表</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="goToLearningRemind">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">🔔</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">学习提醒</view>
|
||||
<view class="feature-desc">向学员发送个性化学习提醒</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 会员维护 -->
|
||||
<view class="section">
|
||||
<view class="section-title">会员维护</view>
|
||||
<view class="feature-row">
|
||||
<!-- 管理员功能 -->
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToMemberOrder">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">🛒</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">会员订单管理</view>
|
||||
<view class="feature-desc">查看、处理会员订单异常</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToGiftMember">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">🎁</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">赠送会员管理</view>
|
||||
<view class="feature-desc">生成、管理赠送会员核验码</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'admin'" class="feature-card" @click="goToGeneralCode">
|
||||
<view class="feature-icon log-icon">
|
||||
<view class="icon-text">🔗</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">通用会员推广码</view>
|
||||
<view class="feature-desc">生成、查看通用推广码</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分销员功能 -->
|
||||
<view v-if="userRole === 'distributor'" class="feature-card" @click="goToPersonalOrder">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">📋</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">订单查看</view>
|
||||
<view class="feature-desc">查看个人名下学员订单概览</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'distributor'" class="feature-card" @click="goToPersonalGiftMember">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">🎁</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">赠送会员操作</view>
|
||||
<view class="feature-desc">生成、分享赠送会员核验码</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常提醒 -->
|
||||
<view class="section">
|
||||
<view class="section-title">异常提醒</view>
|
||||
<view class="feature-row">
|
||||
<view class="feature-card" @click="goToProfitException">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">💰</view>
|
||||
<view v-if="exceptionCount.profit > 0" class="exception-badge">{{ exceptionCount.profit }}</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">分润异常提醒</view>
|
||||
<view class="feature-desc">处理账户余额不足等分润异常</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="goToAiRechargeException">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">🤖</view>
|
||||
<view v-if="exceptionCount.ai > 0" class="exception-badge">{{ exceptionCount.ai }}</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">AI充值订单异常</view>
|
||||
<view class="feature-desc">处理AI充值订单失败等异常</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="goToMemberOrderException">
|
||||
<view class="feature-icon notice-icon">
|
||||
<view class="icon-text">🛒</view>
|
||||
<view v-if="exceptionCount.member > 0" class="exception-badge">{{ exceptionCount.member }}</view>
|
||||
</view>
|
||||
<view class="feature-info">
|
||||
<view class="feature-title">会员订单异常</view>
|
||||
<view class="feature-desc">处理会员订单支付失败等异常</view>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
<uni-grid-item @click="showUnderConstruction">
|
||||
<view class="grid-item-box log">
|
||||
<view class="icon-container">
|
||||
<uni-icons type="wallet-filled" size="36" color="#909399" />
|
||||
</view>
|
||||
<text class="text">日志管理</text>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
</uni-grid>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, getCurrentInstance } from "vue"
|
||||
import { ref, getCurrentInstance, onMounted } from "vue"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const current = ref(0)
|
||||
const swiperDotIndex = ref(0)
|
||||
const data = ref([{ image: '/static/images/banner/banner01.jpg' }, { image: '/static/images/banner/banner02.jpg' }, { image: '/static/images/banner/banner03.jpg' }])
|
||||
const userRole = ref('admin') // 模拟角色,实际应从登录状态获取
|
||||
const exceptionCount = ref({ // 模拟异常数量
|
||||
profit: 2, // 分润异常数量
|
||||
ai: 1, // AI充值订单异常数量
|
||||
member: 3 // 会员订单异常数量
|
||||
})
|
||||
|
||||
function clickBannerItem(item) {
|
||||
console.info(item)
|
||||
}
|
||||
onMounted(() => {
|
||||
// 实际项目中应从登录状态或接口获取用户角色
|
||||
// userRole.value = getUserRole()
|
||||
|
||||
function changeSwiper(e) {
|
||||
current.value = e.detail.current
|
||||
}
|
||||
// 实际项目中应从接口获取异常数量
|
||||
// getExceptionCount()
|
||||
})
|
||||
|
||||
// 跳转到分销员管理页面
|
||||
function goToDistributor() {
|
||||
console.log('准备跳转到分销员管理页面')
|
||||
// 账号管理相关
|
||||
function goToAccountManage() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/distributor/index',
|
||||
success: function() {
|
||||
console.log('跳转成功')
|
||||
},
|
||||
fail: function(err) {
|
||||
console.log('跳转失败:', err)
|
||||
// 尝试使用其他跳转方式
|
||||
uni.redirectTo({
|
||||
url: '/pages/distributor/index',
|
||||
success: function() {
|
||||
console.log('redirectTo跳转成功')
|
||||
},
|
||||
fail: function(err2) {
|
||||
console.log('redirectTo跳转失败:', err2)
|
||||
// 显示错误信息
|
||||
proxy.$modal.showToast('跳转失败,请重试')
|
||||
}
|
||||
})
|
||||
}
|
||||
url: '/pages/account/manage'
|
||||
})
|
||||
}
|
||||
|
||||
// 显示建设中提示
|
||||
function showUnderConstruction() {
|
||||
proxy.$modal.showToast('模块建设中~')
|
||||
function goToQuotaManage() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/account/quota'
|
||||
})
|
||||
}
|
||||
|
||||
function goToLogManage() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/account/log'
|
||||
})
|
||||
}
|
||||
|
||||
function goToPersonalAccount() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/account/personal'
|
||||
})
|
||||
}
|
||||
|
||||
// 分销管理相关
|
||||
function goToDistributorManage() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/distributor/index'
|
||||
})
|
||||
}
|
||||
|
||||
function goToProfitRule() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/distribution/profit-rule'
|
||||
})
|
||||
}
|
||||
|
||||
function goToDistributionData() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/distribution/data'
|
||||
})
|
||||
}
|
||||
|
||||
function goToQrCodeManage() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/distribution/qrcode'
|
||||
})
|
||||
}
|
||||
|
||||
function goToPersonalPromotion() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/distribution/personal'
|
||||
})
|
||||
}
|
||||
|
||||
function goToProfitQuery() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/distribution/profit'
|
||||
})
|
||||
}
|
||||
|
||||
// 学员学情监控相关
|
||||
function goToStudentList() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/student/list'
|
||||
})
|
||||
}
|
||||
|
||||
function goToStudentDetail() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/student/detail'
|
||||
})
|
||||
}
|
||||
|
||||
function goToLearningAnalysis() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/student/analysis'
|
||||
})
|
||||
}
|
||||
|
||||
function goToLearningRemind() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/student/remind'
|
||||
})
|
||||
}
|
||||
|
||||
// 会员维护相关
|
||||
function goToMemberOrder() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/member/order'
|
||||
})
|
||||
}
|
||||
|
||||
function goToGiftMember() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/member/gift'
|
||||
})
|
||||
}
|
||||
|
||||
function goToGeneralCode() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/member/general-code'
|
||||
})
|
||||
}
|
||||
|
||||
function goToPersonalOrder() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/member/personal-order'
|
||||
})
|
||||
}
|
||||
|
||||
function goToPersonalGiftMember() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/member/personal-gift'
|
||||
})
|
||||
}
|
||||
|
||||
// 统计分析相关
|
||||
function goToDistributionStatistics() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/distribution'
|
||||
})
|
||||
}
|
||||
|
||||
function goToMemberStatistics() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/member'
|
||||
})
|
||||
}
|
||||
|
||||
function goToStudentStatistics() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/student'
|
||||
})
|
||||
}
|
||||
|
||||
function goToPersonalStatistics() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/stats/personal'
|
||||
})
|
||||
}
|
||||
|
||||
function goToDataShare() {
|
||||
// 生成并分享业绩数据图片
|
||||
uni.showToast({
|
||||
title: '生成分享图片中...',
|
||||
duration: 1500
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.showActionSheet({
|
||||
itemList: ['分享到微信', '分享到朋友圈', '保存图片'],
|
||||
success: function(res) {
|
||||
switch(res.tapIndex) {
|
||||
case 0:
|
||||
uni.showToast({ title: '分享到微信', duration: 1000 })
|
||||
break
|
||||
case 1:
|
||||
uni.showToast({ title: '分享到朋友圈', duration: 1000 })
|
||||
break
|
||||
case 2:
|
||||
uni.showToast({ title: '图片已保存', duration: 1000 })
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
// 异常提醒相关
|
||||
function goToProfitException() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/exception/profit'
|
||||
})
|
||||
}
|
||||
|
||||
function goToAiRechargeException() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/exception/ai-recharge'
|
||||
})
|
||||
}
|
||||
|
||||
function goToMemberOrderException() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/exception/member-order'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取异常数量
|
||||
function getExceptionCount() {
|
||||
// 实际项目中应从接口获取异常数量
|
||||
uni.request({
|
||||
url: '/api/exception/count',
|
||||
success: function(res) {
|
||||
if (res.data.code === 200) {
|
||||
exceptionCount.value = res.data.data
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -130,123 +505,190 @@
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 轮播图样式 */
|
||||
.uni-swiper-dot-box {
|
||||
.section {
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
height: 200px;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
height: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.banner-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
/* 宫格样式 */
|
||||
.grid-body {
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.grid-title {
|
||||
font-size: 30rpx;
|
||||
/* 标题样式 */
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 10rpx;
|
||||
border-left: 6rpx solid #409eff;
|
||||
margin-bottom: 24rpx;
|
||||
padding-left: 12rpx;
|
||||
border-left: 8rpx solid #409eff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.grid-item-box {
|
||||
flex: 1;
|
||||
/* 横行排列容器 */
|
||||
.feature-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20rpx 0;
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 8rpx;
|
||||
position: relative;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.grid-item-box:active {
|
||||
/* 功能卡片样式 */
|
||||
.feature-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.feature-card:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
/* 图标容器 */
|
||||
.feature-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 15rpx;
|
||||
background-color: #f0f9eb;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 图标文本样式 */
|
||||
.icon-text {
|
||||
font-size: 36rpx;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 异常徽章样式 */
|
||||
.exception-badge {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
right: -8rpx;
|
||||
min-width: 36rpx;
|
||||
height: 36rpx;
|
||||
padding: 0 12rpx;
|
||||
background-color: #f56c6c;
|
||||
color: #fff;
|
||||
border-radius: 18rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2rpx 8rpx rgba(245, 108, 108, 0.5);
|
||||
}
|
||||
|
||||
/* 图标容器相对定位,用于异常徽章 */
|
||||
.feature-icon {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 各模块颜色 */
|
||||
.distributor .icon-container {
|
||||
.distributor-icon {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.user .icon-container {
|
||||
.user-icon {
|
||||
background-color: #f0f9eb;
|
||||
}
|
||||
|
||||
.dept .icon-container {
|
||||
.dept-icon {
|
||||
background-color: #fdf6ec;
|
||||
}
|
||||
|
||||
.notice .icon-container {
|
||||
.notice-icon {
|
||||
background-color: #fef0f0;
|
||||
}
|
||||
|
||||
.log .icon-container {
|
||||
.log-icon {
|
||||
background-color: #f4f4f5;
|
||||
}
|
||||
|
||||
.text {
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
/* 功能信息 */
|
||||
.feature-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 22rpx;
|
||||
color: #909399;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.work-container {
|
||||
max-width: 800px;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
height: 240px;
|
||||
.section-title {
|
||||
font-size: 36rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
height: 240px;
|
||||
.feature-card {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.grid-item-box {
|
||||
padding: 25rpx 0;
|
||||
.feature-icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板和大屏响应式 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.work-container {
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 36rpx;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.icon-text {
|
||||
font-size: 52rpx;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
|
||||
.feature-desc {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user