页面初始化
This commit is contained in:
490
src/pages/account/log.vue
Normal file
490
src/pages/account/log.vue
Normal file
@@ -0,0 +1,490 @@
|
||||
<template>
|
||||
<view class="log-manage-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="exportLog">
|
||||
<view class="export-btn">导出</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 筛选条件 -->
|
||||
<view class="filter-section">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">操作类型</view>
|
||||
<view class="filter-control">
|
||||
<picker
|
||||
:range="operationOptions"
|
||||
:value="operationIndex"
|
||||
@change="onOperationChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ operationOptions[operationIndex] }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">时间范围</view>
|
||||
<view class="filter-control">
|
||||
<picker
|
||||
mode="date"
|
||||
start="2026-01-01"
|
||||
end="2026-12-31"
|
||||
:value="dateRange"
|
||||
@change="onDateChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ dateRangeDisplay }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">搜索</view>
|
||||
<view class="filter-control">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
class="search-input"
|
||||
placeholder="请输入操作人或账号"
|
||||
@input="onSearch"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 日志列表 -->
|
||||
<view class="log-list">
|
||||
<view
|
||||
v-for="(log, index) in logList"
|
||||
:key="index"
|
||||
class="log-item"
|
||||
>
|
||||
<view class="log-header">
|
||||
<view class="log-time">{{ log.time }}</view>
|
||||
<view class="log-status" :class="log.statusClass">{{ log.status }}</view>
|
||||
</view>
|
||||
<view class="log-content">
|
||||
<view class="log-operation">{{ log.operation }}</view>
|
||||
<view class="log-detail">{{ log.detail }}</view>
|
||||
</view>
|
||||
<view class="log-meta">
|
||||
<view class="log-operator">{{ log.operator }}</view>
|
||||
<view class="log-ip">{{ log.ip }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="logList.length === 0" class="empty-state">
|
||||
<view class="empty-icon">📋</view>
|
||||
<view class="empty-text">暂无操作日志</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页 -->
|
||||
<view v-if="logList.length > 0" class="pagination">
|
||||
<view class="page-info">
|
||||
共 {{ totalLogs }} 条,当前第 {{ currentPage }} 页
|
||||
</view>
|
||||
<view class="page-controls">
|
||||
<view
|
||||
class="page-btn"
|
||||
:class="{ disabled: currentPage === 1 }"
|
||||
@click="goToPage(currentPage - 1)"
|
||||
>
|
||||
上一页
|
||||
</view>
|
||||
<view
|
||||
class="page-btn"
|
||||
:class="{ disabled: currentPage === totalPages }"
|
||||
@click="goToPage(currentPage + 1)"
|
||||
>
|
||||
下一页
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 操作类型选项
|
||||
const operationOptions = ['全部', '账号创建', '账号冻结', '账号启用', '密码修改', '权限变更']
|
||||
const operationIndex = ref(0)
|
||||
|
||||
// 日期范围
|
||||
const dateRange = ref('2026-01-29')
|
||||
const dateRangeDisplay = ref('2026-01-29')
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref('')
|
||||
|
||||
// 日志列表
|
||||
const logList = ref([
|
||||
{
|
||||
id: 1,
|
||||
time: '2026-01-29 15:30:45',
|
||||
operation: '账号创建',
|
||||
detail: '创建了新的分销员账号:张教练',
|
||||
operator: '系统管理员',
|
||||
ip: '192.168.1.100',
|
||||
status: '成功',
|
||||
statusClass: 'status-success'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
time: '2026-01-29 14:20:30',
|
||||
operation: '账号冻结',
|
||||
detail: '冻结了分销员账号:王教练',
|
||||
operator: '系统管理员',
|
||||
ip: '192.168.1.100',
|
||||
status: '成功',
|
||||
statusClass: 'status-success'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
time: '2026-01-29 10:15:20',
|
||||
operation: '密码修改',
|
||||
detail: '修改了账号密码:李教练',
|
||||
operator: '李教练',
|
||||
ip: '192.168.1.101',
|
||||
status: '成功',
|
||||
statusClass: 'status-success'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
time: '2026-01-28 16:45:10',
|
||||
operation: '权限变更',
|
||||
detail: '修改了分销员权限:张教练',
|
||||
operator: '系统管理员',
|
||||
ip: '192.168.1.100',
|
||||
status: '成功',
|
||||
statusClass: 'status-success'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
time: '2026-01-28 09:30:00',
|
||||
operation: '账号创建',
|
||||
detail: '创建了新的分销员账号:刘教练',
|
||||
operator: '系统管理员',
|
||||
ip: '192.168.1.100',
|
||||
status: '成功',
|
||||
statusClass: 'status-success'
|
||||
}
|
||||
])
|
||||
|
||||
// 分页信息
|
||||
const currentPage = ref(1)
|
||||
const totalLogs = ref(100)
|
||||
const pageSize = ref(10)
|
||||
|
||||
// 计算总页数
|
||||
const totalPages = computed(() => {
|
||||
return Math.ceil(totalLogs.value / pageSize.value)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取操作日志
|
||||
// loadLogList()
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 导出日志
|
||||
function exportLog() {
|
||||
uni.showModal({
|
||||
title: '导出日志',
|
||||
content: '确定要导出当前筛选条件的操作日志吗?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: '导出中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '导出成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// 实际项目中应调用接口导出日志
|
||||
// exportLogData()
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 操作类型变更
|
||||
function onOperationChange(e) {
|
||||
const value = e.detail.value
|
||||
operationIndex.value = value
|
||||
// 实际项目中应根据操作类型筛选日志
|
||||
// filterLogList()
|
||||
}
|
||||
|
||||
// 日期变更
|
||||
function onDateChange(e) {
|
||||
dateRange.value = e.detail.value
|
||||
dateRangeDisplay.value = e.detail.value
|
||||
// 实际项目中应根据日期筛选日志
|
||||
// filterLogList()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function onSearch() {
|
||||
// 实际项目中应根据关键词搜索日志
|
||||
// searchLogList()
|
||||
}
|
||||
|
||||
// 跳转到指定页码
|
||||
function goToPage(page) {
|
||||
if (page < 1 || page > totalPages.value) {
|
||||
return
|
||||
}
|
||||
currentPage.value = page
|
||||
// 实际项目中应加载指定页码的日志
|
||||
// loadLogList(page)
|
||||
}
|
||||
</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 */
|
||||
|
||||
.log-manage-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;
|
||||
}
|
||||
|
||||
.export-btn {
|
||||
font-size: 28rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 筛选条件 */
|
||||
.filter-section {
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex: 1;
|
||||
min-width: 200rpx;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.filter-control {
|
||||
background-color: #f9f9f9;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.picker {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 日志列表 */
|
||||
.log-list {
|
||||
flex: 1;
|
||||
padding: 0 16rpx;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.log-time {
|
||||
font-size: 20rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.log-status {
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.status-success {
|
||||
color: #67c23a;
|
||||
background-color: rgba(103, 194, 58, 0.1);
|
||||
}
|
||||
|
||||
.status-fail {
|
||||
color: #f56c6c;
|
||||
background-color: rgba(245, 108, 108, 0.1);
|
||||
}
|
||||
|
||||
.log-content {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.log-operation {
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.log-detail {
|
||||
font-size: 20rpx;
|
||||
color: #606266;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.log-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 20rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 80rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 分页 */
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.page-info {
|
||||
font-size: 20rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.page-controls {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.page-btn {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.page-btn.disabled {
|
||||
color: #909399;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
390
src/pages/account/manage.vue
Normal file
390
src/pages/account/manage.vue
Normal file
@@ -0,0 +1,390 @@
|
||||
<template>
|
||||
<view class="account-manage-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="addAccount">
|
||||
<view class="add-btn">+ 添加</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 筛选条件 -->
|
||||
<view class="filter-section">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">账号状态</view>
|
||||
<view class="filter-control">
|
||||
<picker
|
||||
:range="statusOptions"
|
||||
:value="statusIndex"
|
||||
@change="onStatusChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ statusOptions[statusIndex] }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">搜索</view>
|
||||
<view class="filter-control">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
class="search-input"
|
||||
placeholder="请输入账号名称或手机号"
|
||||
@input="onSearch"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 账号列表 -->
|
||||
<view class="account-list">
|
||||
<view
|
||||
v-for="(account, index) in accountList"
|
||||
:key="index"
|
||||
class="account-item"
|
||||
>
|
||||
<view class="account-info">
|
||||
<view class="account-name">{{ account.name }}</view>
|
||||
<view class="account-meta">
|
||||
<view class="meta-item">{{ account.phone }}</view>
|
||||
<view class="meta-item">{{ account.role }}</view>
|
||||
<view class="meta-item status-{{ account.status }}">{{ account.statusText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="account-actions">
|
||||
<view class="action-btn edit-btn" @click="editAccount(account.id)">
|
||||
编辑
|
||||
</view>
|
||||
<view
|
||||
class="action-btn"
|
||||
:class="account.status === 'active' ? 'disable-btn' : 'enable-btn'"
|
||||
@click="toggleAccountStatus(account.id, account.status)"
|
||||
>
|
||||
{{ account.status === 'active' ? '冻结' : '启用' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="accountList.length === 0" class="empty-state">
|
||||
<view class="empty-icon">👥</view>
|
||||
<view class="empty-text">暂无账号数据</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue"
|
||||
|
||||
// 状态选项
|
||||
const statusOptions = ['全部', '启用', '冻结']
|
||||
const statusIndex = ref(0)
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref('')
|
||||
|
||||
// 账号列表
|
||||
const accountList = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '张教练',
|
||||
phone: '138****1234',
|
||||
role: '分销员',
|
||||
status: 'active',
|
||||
statusText: '启用'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '李教练',
|
||||
phone: '139****5678',
|
||||
role: '分销员',
|
||||
status: 'active',
|
||||
statusText: '启用'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '王教练',
|
||||
phone: '137****9012',
|
||||
role: '分销员',
|
||||
status: 'inactive',
|
||||
statusText: '冻结'
|
||||
}
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取账号列表
|
||||
// loadAccountList()
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 添加账号
|
||||
function addAccount() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/account/add'
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑账号
|
||||
function editAccount(accountId) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/account/edit?id=${accountId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 切换账号状态
|
||||
function toggleAccountStatus(accountId, currentStatus) {
|
||||
const newStatus = currentStatus === 'active' ? 'inactive' : 'active'
|
||||
const newStatusText = newStatus === 'active' ? '启用' : '冻结'
|
||||
|
||||
uni.showModal({
|
||||
title: '确认操作',
|
||||
content: `确定要${newStatusText}该账号吗?`,
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
// 实际项目中应调用接口切换账号状态
|
||||
const account = accountList.value.find(item => item.id === accountId)
|
||||
if (account) {
|
||||
account.status = newStatus
|
||||
account.statusText = newStatusText
|
||||
}
|
||||
uni.showToast({
|
||||
title: `账号已${newStatusText}`,
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 状态变更
|
||||
function onStatusChange(e) {
|
||||
const value = e.detail.value
|
||||
statusIndex.value = value
|
||||
// 实际项目中应根据状态筛选账号列表
|
||||
// filterAccountList()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function onSearch() {
|
||||
// 实际项目中应根据关键词搜索账号列表
|
||||
// searchAccountList()
|
||||
}
|
||||
</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 */
|
||||
|
||||
.account-manage-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: 100rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
font-size: 24rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 筛选条件 */
|
||||
.filter-section {
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.filter-control {
|
||||
background-color: #f9f9f9;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.picker {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 账号列表 */
|
||||
.account-list {
|
||||
flex: 1;
|
||||
padding: 0 16rpx;
|
||||
}
|
||||
|
||||
.account-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.account-info {
|
||||
flex: 1;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.account-meta {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
font-size: 20rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.status-inactive {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.account-actions {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
background-color: #ecf5ff;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.disable-btn {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.enable-btn {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 80rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
410
src/pages/account/personal.vue
Normal file
410
src/pages/account/personal.vue
Normal file
@@ -0,0 +1,410 @@
|
||||
<template>
|
||||
<view class="personal-account-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="saveChanges">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 个人信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">个人信息</view>
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">姓名</view>
|
||||
<view class="info-control">
|
||||
<input
|
||||
v-model="userInfo.name"
|
||||
class="info-input"
|
||||
placeholder="请输入姓名"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">手机号码</view>
|
||||
<view class="info-control">
|
||||
<input
|
||||
v-model="userInfo.phone"
|
||||
class="info-input"
|
||||
placeholder="请输入手机号码"
|
||||
maxlength="11"
|
||||
type="number"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">邮箱</view>
|
||||
<view class="info-control">
|
||||
<input
|
||||
v-model="userInfo.email"
|
||||
class="info-input"
|
||||
placeholder="请输入邮箱"
|
||||
maxlength="50"
|
||||
type="email"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">性别</view>
|
||||
<view class="info-control">
|
||||
<picker
|
||||
:range="genders"
|
||||
:value="genderIndex"
|
||||
@change="onGenderChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ userInfo.gender || '请选择性别' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">所属驾校</view>
|
||||
<view class="info-control">
|
||||
<view class="info-text">{{ userInfo.school || '顺达驾校' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">职位</view>
|
||||
<view class="info-control">
|
||||
<input
|
||||
v-model="userInfo.position"
|
||||
class="info-input"
|
||||
placeholder="请输入职位"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 账号安全 -->
|
||||
<view class="security-section">
|
||||
<view class="section-title">账号安全</view>
|
||||
<view class="security-card">
|
||||
<view class="security-item" @click="goToPasswordChange">
|
||||
<view class="security-label">修改登录密码</view>
|
||||
<view class="security-arrow">→</view>
|
||||
</view>
|
||||
<view class="security-item" @click="bindPhone">
|
||||
<view class="security-label">绑定手机号</view>
|
||||
<view class="security-status">{{ userInfo.phone ? '已绑定' : '未绑定' }}</view>
|
||||
<view class="security-arrow">→</view>
|
||||
</view>
|
||||
<view class="security-item" @click="bindEmail">
|
||||
<view class="security-label">绑定邮箱</view>
|
||||
<view class="security-status">{{ userInfo.email ? '已绑定' : '未绑定' }}</view>
|
||||
<view class="security-arrow">→</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 账号信息 -->
|
||||
<view class="account-info-section">
|
||||
<view class="section-title">账号信息</view>
|
||||
<view class="info-card">
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">账号ID</view>
|
||||
<view class="info-value">{{ userInfo.id || '10001' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">账号类型</view>
|
||||
<view class="info-value">{{ userInfo.role || '分销员' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">注册时间</view>
|
||||
<view class="info-value">{{ userInfo.registerTime || '2026-01-15' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<view class="info-label">最后登录</view>
|
||||
<view class="info-value">{{ userInfo.lastLogin || '2026-01-29 10:30:00' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 性别选项
|
||||
const genders = ['男', '女', '保密']
|
||||
|
||||
// 用户信息
|
||||
const userInfo = ref({
|
||||
id: '10001',
|
||||
name: '张教练',
|
||||
phone: '13800138000',
|
||||
email: 'zhang@shunda.com',
|
||||
gender: '男',
|
||||
school: '顺达驾校',
|
||||
position: '科目二教练',
|
||||
role: '分销员',
|
||||
registerTime: '2026-01-15',
|
||||
lastLogin: '2026-01-29 10:30:00'
|
||||
})
|
||||
|
||||
// 计算性别索引
|
||||
const genderIndex = computed(() => {
|
||||
return genders.indexOf(userInfo.value.gender)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取用户信息
|
||||
// loadUserInfo()
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 保存修改
|
||||
function saveChanges() {
|
||||
uni.showModal({
|
||||
title: '保存修改',
|
||||
content: '确定要保存个人信息修改吗?',
|
||||
success: function(res) {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({ title: '保存中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// 实际项目中应调用接口保存用户信息
|
||||
// saveUserInfo()
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 性别变更
|
||||
function onGenderChange(e) {
|
||||
const index = e.detail.value
|
||||
userInfo.value.gender = genders[index]
|
||||
}
|
||||
|
||||
// 跳转到修改密码页面
|
||||
function goToPasswordChange() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mine/password-change'
|
||||
})
|
||||
}
|
||||
|
||||
// 绑定手机号
|
||||
function bindPhone() {
|
||||
uni.showToast({
|
||||
title: '绑定手机号功能开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
// 绑定邮箱
|
||||
function bindEmail() {
|
||||
uni.showToast({
|
||||
title: '绑定邮箱功能开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
</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-account-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;
|
||||
}
|
||||
|
||||
/* 通用部分样式 */
|
||||
.info-section,
|
||||
.security-section,
|
||||
.account-info-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;
|
||||
}
|
||||
|
||||
/* 个人信息 */
|
||||
.info-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.info-control {
|
||||
background-color: #f9f9f9;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.info-input {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.info-text {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.picker {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 账号安全 */
|
||||
.security-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.security-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.security-label {
|
||||
flex: 1;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.security-status {
|
||||
font-size: 20rpx;
|
||||
color: #67c23a;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.security-arrow {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
454
src/pages/account/quota.vue
Normal file
454
src/pages/account/quota.vue
Normal file
@@ -0,0 +1,454 @@
|
||||
<template>
|
||||
<view class="quota-manage-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="saveQuota">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 筛选条件 -->
|
||||
<view class="filter-section">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">选择月份</view>
|
||||
<view class="filter-control">
|
||||
<picker
|
||||
mode="date"
|
||||
fields="month"
|
||||
:value="currentMonth"
|
||||
start="2026-01"
|
||||
end="2026-12"
|
||||
@change="onMonthChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ currentMonthDisplay }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 总额度设置 -->
|
||||
<view class="total-quota-section">
|
||||
<view class="section-title">总额度设置</view>
|
||||
<view class="quota-card">
|
||||
<view class="quota-item">
|
||||
<view class="quota-label">月度赠会员总额度</view>
|
||||
<view class="quota-control">
|
||||
<input
|
||||
v-model="totalQuota"
|
||||
type="number"
|
||||
class="quota-input"
|
||||
placeholder="请输入总额度"
|
||||
min="0"
|
||||
max="1000"
|
||||
/>
|
||||
<view class="quota-unit">个</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="quota-hint">
|
||||
• 总额度将分配给所有分销员
|
||||
• 单个分销员最高可分配额度为总额度的50%
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分销员额度分配 -->
|
||||
<view class="distributor-quota-section">
|
||||
<view class="section-title">分销员额度分配</view>
|
||||
<view class="quota-list">
|
||||
<view
|
||||
v-for="(distributor, index) in distributors"
|
||||
:key="distributor.id"
|
||||
class="quota-item"
|
||||
>
|
||||
<view class="distributor-info">
|
||||
<view class="distributor-name">{{ distributor.name }}</view>
|
||||
<view class="distributor-id">ID: {{ distributor.id }}</view>
|
||||
</view>
|
||||
<view class="quota-control">
|
||||
<input
|
||||
v-model="distributor.quota"
|
||||
type="number"
|
||||
class="quota-input"
|
||||
placeholder="0"
|
||||
min="0"
|
||||
:max="maxDistributorQuota"
|
||||
/>
|
||||
<view class="quota-unit">个</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 配额统计 -->
|
||||
<view class="quota-stats">
|
||||
<view class="stats-item">
|
||||
<view class="stats-label">已分配额度:</view>
|
||||
<view class="stats-value">{{ allocatedQuota }} 个</view>
|
||||
</view>
|
||||
<view class="stats-item">
|
||||
<view class="stats-label">剩余额度:</view>
|
||||
<view class="stats-value" :class="{ 'warning': remainingQuota < 0 }">
|
||||
{{ remainingQuota }} 个
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
|
||||
// 当前月份
|
||||
const currentMonth = ref('2026-01')
|
||||
const currentMonthDisplay = ref('2026年01月')
|
||||
|
||||
// 总额度
|
||||
const totalQuota = ref(100)
|
||||
|
||||
// 分销员列表
|
||||
const distributors = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '张分销',
|
||||
quota: 30
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '李分销',
|
||||
quota: 25
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '王分销',
|
||||
quota: 20
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '刘分销',
|
||||
quota: 15
|
||||
}
|
||||
])
|
||||
|
||||
// 计算单个分销员最大可分配额度
|
||||
const maxDistributorQuota = computed(() => {
|
||||
return Math.floor(totalQuota.value * 0.5)
|
||||
})
|
||||
|
||||
// 计算已分配额度
|
||||
const allocatedQuota = computed(() => {
|
||||
return distributors.value.reduce((sum, distributor) => {
|
||||
return sum + parseInt(distributor.quota || 0)
|
||||
}, 0)
|
||||
})
|
||||
|
||||
// 计算剩余额度
|
||||
const remainingQuota = computed(() => {
|
||||
return totalQuota.value - allocatedQuota.value
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
|
||||
// 月份变更
|
||||
function onMonthChange(e) {
|
||||
currentMonth.value = e.detail.value
|
||||
const date = new Date(e.detail.value)
|
||||
currentMonthDisplay.value = `${date.getFullYear()}年${String(date.getMonth() + 1).padStart(2, '0')}月`
|
||||
// 实际项目中应根据选择的月份加载对应的额度配置
|
||||
// loadQuotaByMonth(currentMonth.value)
|
||||
}
|
||||
|
||||
// 保存配额
|
||||
function saveQuota() {
|
||||
if (!totalQuota.value || totalQuota.value <= 0) {
|
||||
uni.showToast({
|
||||
title: '请设置有效的总额度',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (remainingQuota.value < 0) {
|
||||
uni.showToast({
|
||||
title: '已分配额度超过总额度',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.showLoading({ title: '保存中...' })
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
// 实际项目中应调用接口保存配额配置
|
||||
// saveQuotaConfig()
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取分销员列表和当前月份的配额配置
|
||||
// loadDistributors()
|
||||
// loadCurrentMonthQuota()
|
||||
})
|
||||
</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 */
|
||||
|
||||
.quota-manage-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;
|
||||
}
|
||||
|
||||
/* 筛选条件 */
|
||||
.filter-section {
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #fff;
|
||||
margin: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.filter-control {
|
||||
background-color: #f9f9f9;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.picker {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 通用部分样式 */
|
||||
.total-quota-section,
|
||||
.distributor-quota-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;
|
||||
}
|
||||
|
||||
/* 总额度设置 */
|
||||
.quota-card {
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.quota-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.quota-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.quota-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.quota-input {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
background-color: #fff;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 16rpx;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.quota-unit {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.quota-hint {
|
||||
font-size: 20rpx;
|
||||
color: #909399;
|
||||
margin-top: 16rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 分销员额度分配 */
|
||||
.quota-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.distributor-info {
|
||||
flex: 1;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.distributor-name {
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.distributor-id {
|
||||
font-size: 20rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 配额统计 */
|
||||
.quota-stats {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 24rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.stats-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.stats-value.warning {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (min-width: 500px) {
|
||||
.quota-manage-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.quota-input {
|
||||
width: 160rpx;
|
||||
height: 72rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.distributor-name {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user