sc
This commit is contained in:
@@ -198,6 +198,18 @@
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/member/setting",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/member/setting-form",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/mine/school-info",
|
||||
"style": {
|
||||
|
||||
473
src/pages/member/setting-form.vue
Normal file
473
src/pages/member/setting-form.vue
Normal file
@@ -0,0 +1,473 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="header">
|
||||
<view class="back-btn" @click="goBack">
|
||||
<text>←</text>
|
||||
</view>
|
||||
<view class="title">{{ isEditMode ? '编辑会员' : '新增会员' }}</view>
|
||||
<view class="right-btn"></view>
|
||||
</view>
|
||||
|
||||
<view class="form-container">
|
||||
<!-- 会员名称 -->
|
||||
<view class="form-item">
|
||||
<view class="label">会员名称</view>
|
||||
<input type="text" v-model="formData.name" placeholder="请输入会员名称" class="input" />
|
||||
</view>
|
||||
|
||||
<!-- 车型 -->
|
||||
<view class="form-item">
|
||||
<view class="label">车型</view>
|
||||
<picker @change="bindCarTypeChange" :range="carTypes" :value="carTypeIndex" class="picker">
|
||||
<view class="picker-text">{{ carTypes[carTypeIndex] || '请选择车型' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 科目 -->
|
||||
<view class="form-item">
|
||||
<view class="label">科目</view>
|
||||
<picker @change="bindSubjectChange" :range="subjects" :value="subjectIndex" class="picker">
|
||||
<view class="picker-text">{{ subjects[subjectIndex] || '请选择科目' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 原价 -->
|
||||
<view class="form-item">
|
||||
<view class="label">原价</view>
|
||||
<input type="number" v-model="formData.originalPrice" placeholder="请输入原价" class="input" />
|
||||
</view>
|
||||
|
||||
<!-- 折扣价 -->
|
||||
<view class="form-item">
|
||||
<view class="label">折扣价</view>
|
||||
<input type="number" v-model="formData.discountPrice" placeholder="请输入折扣价" class="input" />
|
||||
</view>
|
||||
|
||||
<!-- 有效期 -->
|
||||
<view class="form-item">
|
||||
<view class="label">有效期</view>
|
||||
<view class="有效期-input">
|
||||
<input type="number" v-model="formData.validityPeriod" placeholder="请输入数字" class="validity-input" />
|
||||
<picker @change="bindUnitChange" :range="units" :value="unitIndex" class="unit-picker">
|
||||
<view class="unit-text">{{ units[unitIndex] }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用方式 -->
|
||||
<view class="form-item">
|
||||
<view class="label">使用方式</view>
|
||||
<view class="use-type-container">
|
||||
<view class="use-type-item" @click="toggleUseType('student')">
|
||||
<view class="checkbox" :class="{ checked: formData.useTypes.includes('student') }"></view>
|
||||
<view class="use-type-text">学员购买</view>
|
||||
</view>
|
||||
<view class="use-type-item" @click="toggleUseType('admin')">
|
||||
<view class="checkbox" :class="{ checked: formData.useTypes.includes('admin') }"></view>
|
||||
<view class="use-type-text">客服赠送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 包含权益 -->
|
||||
<view class="form-item">
|
||||
<view class="label">包含权益</view>
|
||||
<view class="rights-container">
|
||||
<view v-if="loading" class="loading">加载中...</view>
|
||||
<view v-else-if="rights.length === 0" class="no-rights">暂无权益</view>
|
||||
<view v-else class="rights-list">
|
||||
<view v-for="right in rights" :key="right.id" class="right-item">
|
||||
<view class="checkbox" :class="{ checked: formData.rights.includes(right.id) }" @click="toggleRight(right.id)"></view>
|
||||
<view class="right-text">{{ right.name }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-btn" @click="submitForm">
|
||||
<view class="btn-text">{{ isEditMode ? '保存修改' : '保存新增' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
id: '',
|
||||
name: '',
|
||||
carType: '',
|
||||
subject: '',
|
||||
originalPrice: '',
|
||||
discountPrice: '',
|
||||
validityPeriod: '',
|
||||
unit: '天',
|
||||
useTypes: [],
|
||||
rights: []
|
||||
})
|
||||
|
||||
// 车型选项
|
||||
const carTypes = ref(['C1', 'C2', 'A1', 'A2', 'B1', 'B2'])
|
||||
const carTypeIndex = ref(0)
|
||||
|
||||
// 科目选项
|
||||
const subjects = ref(['科目一', '科目二', '科目三', '科目四', '全科'])
|
||||
const subjectIndex = ref(0)
|
||||
|
||||
// 单位选项
|
||||
const units = ref(['天', '年'])
|
||||
const unitIndex = ref(0)
|
||||
|
||||
// 包含权益
|
||||
const rights = ref([])
|
||||
const loading = ref(false)
|
||||
|
||||
// 编辑模式
|
||||
const isEditMode = ref(false)
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
getRightsList()
|
||||
checkEditMode()
|
||||
})
|
||||
|
||||
// 检查是否为编辑模式
|
||||
function checkEditMode() {
|
||||
const pages = getCurrentPages()
|
||||
const currentPage = pages[pages.length - 1]
|
||||
const options = currentPage.options
|
||||
|
||||
if (options.id) {
|
||||
// 编辑模式,获取会员详情
|
||||
isEditMode.value = true
|
||||
getMemberDetail(options.id)
|
||||
} else {
|
||||
// 新增模式
|
||||
isEditMode.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取会员详情
|
||||
function getMemberDetail(id) {
|
||||
// 实际项目中应调用接口获取会员详情
|
||||
setTimeout(() => {
|
||||
const mockData = {
|
||||
id: id,
|
||||
name: '基础会员',
|
||||
carType: 'C1',
|
||||
subject: '科目一',
|
||||
originalPrice: 199,
|
||||
discountPrice: 99,
|
||||
validityPeriod: 30,
|
||||
unit: '天',
|
||||
useTypes: ['student'],
|
||||
rights: [1, 4]
|
||||
}
|
||||
|
||||
formData.value = {
|
||||
id: mockData.id,
|
||||
name: mockData.name,
|
||||
carType: mockData.carType,
|
||||
subject: mockData.subject,
|
||||
originalPrice: mockData.originalPrice,
|
||||
discountPrice: mockData.discountPrice,
|
||||
validityPeriod: mockData.validityPeriod,
|
||||
unit: mockData.unit,
|
||||
useTypes: [...mockData.useTypes],
|
||||
rights: [...mockData.rights]
|
||||
}
|
||||
|
||||
// 设置选择器索引
|
||||
carTypeIndex.value = carTypes.value.indexOf(mockData.carType)
|
||||
subjectIndex.value = subjects.value.indexOf(mockData.subject)
|
||||
unitIndex.value = units.value.indexOf(mockData.unit)
|
||||
}, 300)
|
||||
}
|
||||
|
||||
// 获取权益列表
|
||||
function getRightsList() {
|
||||
loading.value = true
|
||||
// 实际项目中应调用接口获取权益列表
|
||||
setTimeout(() => {
|
||||
rights.value = [
|
||||
{ id: 1, name: '无限次模拟考试' },
|
||||
{ id: 2, name: '视频课程免费看' },
|
||||
{ id: 3, name: '一对一在线辅导' },
|
||||
{ id: 4, name: '错题本' },
|
||||
{ id: 5, name: '考试技巧指导' }
|
||||
]
|
||||
loading.value = false
|
||||
}, 500)
|
||||
}
|
||||
|
||||
// 车型选择
|
||||
function bindCarTypeChange(e) {
|
||||
carTypeIndex.value = e.detail.value
|
||||
formData.value.carType = carTypes.value[e.detail.value]
|
||||
}
|
||||
|
||||
// 科目选择
|
||||
function bindSubjectChange(e) {
|
||||
subjectIndex.value = e.detail.value
|
||||
formData.value.subject = subjects.value[e.detail.value]
|
||||
}
|
||||
|
||||
// 单位选择
|
||||
function bindUnitChange(e) {
|
||||
unitIndex.value = e.detail.value
|
||||
formData.value.unit = units.value[e.detail.value]
|
||||
}
|
||||
|
||||
// 切换使用方式
|
||||
function toggleUseType(type) {
|
||||
const index = formData.value.useTypes.indexOf(type)
|
||||
if (index === -1) {
|
||||
formData.value.useTypes.push(type)
|
||||
} else {
|
||||
formData.value.useTypes.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 切换权益
|
||||
function toggleRight(rightId) {
|
||||
const index = formData.value.rights.indexOf(rightId)
|
||||
if (index === -1) {
|
||||
formData.value.rights.push(rightId)
|
||||
} else {
|
||||
formData.value.rights.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
function submitForm() {
|
||||
// 实际项目中应调用接口提交表单
|
||||
console.log('表单数据:', formData.value)
|
||||
|
||||
if (isEditMode.value) {
|
||||
uni.showToast({
|
||||
title: '修改成功',
|
||||
icon: 'success'
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '新增成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
flex: 1;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
background-color: #fff;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-btn text {
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.right-btn {
|
||||
width: 44px;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: #fff;
|
||||
margin-top: 10px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.form-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 8px;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.picker {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 8px;
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.有效期-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.validity-input {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 8px 0 0 8px;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.unit-picker {
|
||||
width: 100px;
|
||||
height: 44px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-left: none;
|
||||
border-radius: 0 8px 8px 0;
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.unit-text {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.use-type-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.use-type-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.checkbox.checked {
|
||||
background-color: #007aff;
|
||||
border-color: #007aff;
|
||||
}
|
||||
|
||||
.checkbox.checked::after {
|
||||
content: '✓';
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.use-type-text {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.rights-container {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.no-rights {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.rights-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.right-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.right-text {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
margin: 24px 16px;
|
||||
height: 44px;
|
||||
background-color: #007aff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
430
src/pages/member/setting.vue
Normal file
430
src/pages/member/setting.vue
Normal file
@@ -0,0 +1,430 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="header">
|
||||
<view class="back-btn" @click="goBack">
|
||||
<text>←</text>
|
||||
</view>
|
||||
<view class="title">会员配置</view>
|
||||
<view class="right-btn">
|
||||
<view class="add-btn" @click="goToAdd">
|
||||
<text>新增</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表视图 -->
|
||||
<view class="list-container">
|
||||
<view v-if="loading" class="loading">加载中...</view>
|
||||
<view v-else-if="memberList.length === 0" class="empty-list">
|
||||
<view class="empty-icon">📋</view>
|
||||
<view class="empty-text">暂无会员配置</view>
|
||||
<view class="empty-btn" @click="goToAdd">
|
||||
<view class="btn-text">新增会员配置</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="member-list">
|
||||
<view v-for="member in memberList" :key="member.id" class="member-item">
|
||||
<view class="member-info">
|
||||
<view class="flex justify-between" style="border-bottom: 1px solid #f0f0f0;">
|
||||
<view class="member-name">{{ member.name }}</view>
|
||||
<view class="member-actions">
|
||||
<view class="action-btn edit-btn" @click="goToEdit(member)">
|
||||
<text>编辑</text>
|
||||
</view>
|
||||
<view class="action-btn delete-btn" @click="deleteMember(member.id)">
|
||||
<text>删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="member-details">
|
||||
<view class="detail-row">
|
||||
<view class="detail-item">车型:{{ member.carType }}</view>
|
||||
<view class="detail-item">科目:{{ member.subject }}</view>
|
||||
</view>
|
||||
<view class="detail-item price-item">
|
||||
<span class="price-label">价格:</span>
|
||||
<span class="discount-price">¥{{ member.discountPrice }}</span>
|
||||
<span class="original-price"> (原价:¥{{ member.originalPrice }})</span>
|
||||
</view>
|
||||
<view class="detail-item">有效期:{{ member.validityPeriod }}{{ member.unit }}</view>
|
||||
<view class="detail-item">
|
||||
<span class="detail-label">使用方式:</span>
|
||||
<view class="use-type-tags">
|
||||
<span v-for="(type, index) in member.useTypes" :key="index" class="use-type-tag">
|
||||
{{ type === 'student' ? '学员购买' : '客服赠送' }}
|
||||
</span>
|
||||
</view>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<span class="detail-label">包含权益:</span>
|
||||
<view class="rights-tags">
|
||||
<span v-for="(right, index) in member.rights" :key="index" class="right-tag">
|
||||
{{ right }}
|
||||
</span>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
// 会员列表
|
||||
const memberList = ref([])
|
||||
const loading = ref(false)
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
getMemberList()
|
||||
})
|
||||
|
||||
// 获取会员列表
|
||||
function getMemberList() {
|
||||
loading.value = true
|
||||
// 实际项目中应调用接口获取会员列表
|
||||
setTimeout(() => {
|
||||
memberList.value = [
|
||||
{
|
||||
id: 1,
|
||||
name: '基础会员',
|
||||
carType: 'C1',
|
||||
subject: '科目一',
|
||||
originalPrice: 199,
|
||||
discountPrice: 99,
|
||||
validityPeriod: 30,
|
||||
unit: '天',
|
||||
useTypes: ['student'],
|
||||
rights: ['无限次模拟考试', '错题本']
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '高级会员',
|
||||
carType: 'C1',
|
||||
subject: '全科',
|
||||
originalPrice: 599,
|
||||
discountPrice: 299,
|
||||
validityPeriod: 1,
|
||||
unit: '年',
|
||||
useTypes: ['student', 'admin'],
|
||||
rights: ['无限次模拟考试', '视频课程免费看', '一对一在线辅导', '错题本', '考试技巧指导']
|
||||
}
|
||||
]
|
||||
loading.value = false
|
||||
}, 500)
|
||||
}
|
||||
|
||||
// 跳转到新增页面
|
||||
function goToAdd() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/member/setting-form'
|
||||
})
|
||||
}
|
||||
|
||||
// 跳转到编辑页面
|
||||
function goToEdit(member) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/member/setting-form?id=${member.id}`
|
||||
})
|
||||
}
|
||||
|
||||
// 删除会员
|
||||
function deleteMember(id) {
|
||||
uni.showModal({
|
||||
title: '确认删除',
|
||||
content: '确定要删除该会员配置吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 实际项目中应调用接口删除会员
|
||||
memberList.value = memberList.value.filter(item => item.id !== id)
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
flex: 1;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
background-color: #fff;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-btn text {
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.right-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
padding: 6px 16px;
|
||||
color: #007aff;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.add-btn text {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 列表视图样式 */
|
||||
.list-container {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.empty-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.empty-btn {
|
||||
padding: 10px 24px;
|
||||
background-color: #007aff;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.member-list {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.member-item {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.member-item:hover {
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.member-info {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.member-name {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.member-details {
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
line-height: 1.4;
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.detail-item::before {
|
||||
content: "•";
|
||||
color: #007aff;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.detail-row .detail-item {
|
||||
flex: 0 0 auto;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
/* 价格样式 */
|
||||
.price-item {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price-label {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.discount-price {
|
||||
color: #ff4d4f;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.original-price {
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 详情标签样式 */
|
||||
.detail-label {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 使用方式标签 */
|
||||
.use-type-tags {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.use-type-tag {
|
||||
padding: 4px 12px;
|
||||
background-color: #e6f7ff;
|
||||
color: #007aff;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 权益标签 */
|
||||
.rights-tags {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.right-tag {
|
||||
padding: 4px 12px;
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border: 1px solid #d9f7be;
|
||||
}
|
||||
|
||||
.member-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 8px 10px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.edit-btn:hover {
|
||||
background-color: #e9ecef;
|
||||
border-color: #007aff;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(255, 77, 79, 0.1);
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 480px) {
|
||||
.detail-row {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.detail-row .detail-item {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,187 +1,5 @@
|
||||
<template>
|
||||
<view class="normal-login-container">
|
||||
<view class="logo-content align-center justify-center flex">
|
||||
<image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
|
||||
</image>
|
||||
<text class="title">若依移动端注册</text>
|
||||
</view>
|
||||
<view class="login-form-content">
|
||||
<view class="input-item flex align-center">
|
||||
<view class="iconfont icon-user icon"></view>
|
||||
<input v-model="registerForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30" />
|
||||
</view>
|
||||
<view class="input-item flex align-center">
|
||||
<view class="iconfont icon-password icon"></view>
|
||||
<input v-model="registerForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20" />
|
||||
</view>
|
||||
<view class="input-item flex align-center">
|
||||
<view class="iconfont icon-password icon"></view>
|
||||
<input v-model="registerForm.confirmPassword" type="password" class="input" placeholder="请输入重复密码" maxlength="20" />
|
||||
</view>
|
||||
<view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled">
|
||||
<view class="iconfont icon-code icon"></view>
|
||||
<input v-model="registerForm.code" type="number" class="input" placeholder="请输入验证码" maxlength="4" />
|
||||
<view class="login-code">
|
||||
<image :src="codeUrl" @click="getCode" class="login-code-img"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="action-btn">
|
||||
<button @click="handleRegister()" class="register-btn cu-btn block bg-blue lg round">注册</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="xieyi text-center">
|
||||
<text @click="handleUserLogin" class="text-blue">使用已有账号登录</text>
|
||||
</view>
|
||||
<view class="container">
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getCodeImg, register } from '@/api/login'
|
||||
import { ref, getCurrentInstance } from "vue"
|
||||
import { useConfigStore } from '@/store'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const globalConfig = useConfigStore().config
|
||||
const codeUrl = ref("")
|
||||
// 验证码开关
|
||||
const captchaEnabled = ref(true)
|
||||
const registerForm = ref({
|
||||
username: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
code: "",
|
||||
uuid: ""
|
||||
})
|
||||
|
||||
// 用户登录
|
||||
function handleUserLogin() {
|
||||
proxy.$tab.navigateTo(`/pages/login`)
|
||||
}
|
||||
|
||||
// 获取图形验证码
|
||||
function getCode() {
|
||||
getCodeImg().then(res => {
|
||||
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled
|
||||
if (captchaEnabled.value) {
|
||||
codeUrl.value = 'data:image/gif;base64,' + res.img
|
||||
registerForm.value.uuid = res.uuid
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 注册方法
|
||||
async function handleRegister() {
|
||||
if (registerForm.value.username === "") {
|
||||
proxy.$modal.msgError("请输入您的账号")
|
||||
} else if (registerForm.value.password === "") {
|
||||
proxy.$modal.msgError("请输入您的密码")
|
||||
} else if (registerForm.value.confirmPassword === "") {
|
||||
proxy.$modal.msgError("请再次输入您的密码")
|
||||
} else if (registerForm.value.password !== registerForm.value.confirmPassword) {
|
||||
proxy.$modal.msgError("两次输入的密码不一致")
|
||||
} else if (registerForm.value.code === "" && captchaEnabled.value) {
|
||||
proxy.$modal.msgError("请输入验证码")
|
||||
} else {
|
||||
proxy.$modal.loading("注册中,请耐心等待...")
|
||||
userRegister()
|
||||
}
|
||||
}
|
||||
|
||||
// 用户注册
|
||||
async function userRegister() {
|
||||
register(registerForm.value).then(res => {
|
||||
proxy.$modal.closeLoading()
|
||||
uni.showModal({
|
||||
title: "系统提示",
|
||||
content: "恭喜你,您的账号 " + registerForm.value.username + " 注册成功!",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
uni.redirectTo({ url: `/pages/login` })
|
||||
}
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
if (captchaEnabled.value) {
|
||||
getCode()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getCode()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.normal-login-container {
|
||||
width: 100%;
|
||||
|
||||
.logo-content {
|
||||
width: 100%;
|
||||
font-size: 21px;
|
||||
text-align: center;
|
||||
padding-top: 15%;
|
||||
|
||||
image {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-form-content {
|
||||
text-align: center;
|
||||
margin: 20px auto;
|
||||
margin-top: 15%;
|
||||
width: 80%;
|
||||
|
||||
.input-item {
|
||||
margin: 20px auto;
|
||||
background-color: #f5f6f7;
|
||||
height: 45px;
|
||||
border-radius: 20px;
|
||||
|
||||
.icon {
|
||||
font-size: 38rpx;
|
||||
margin-left: 10px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.register-btn {
|
||||
margin-top: 40px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.xieyi {
|
||||
color: #333;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.login-code {
|
||||
height: 38px;
|
||||
float: right;
|
||||
|
||||
.login-code-img {
|
||||
height: 38px;
|
||||
position: absolute;
|
||||
margin-left: 10px;
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 分销员功能 -->
|
||||
<view v-if="userRole === 'distributor'" class="feature-card" @click="goToPersonalPromotion">
|
||||
<view v-if="checkPermi(['work:distribution:selfPromotion'])" class="feature-card" @click="goToPersonalPromotion">
|
||||
<view class="feature-icon log-icon">
|
||||
<view class="icon-text">📱</view>
|
||||
</view>
|
||||
@@ -93,7 +93,7 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="userRole === 'distributor'" class="feature-card" @click="goToProfitQuery">
|
||||
<view v-if="checkPermi(['work:distribution:profitQuery'])" class="feature-card" @click="goToProfitQuery">
|
||||
<view class="feature-icon distributor-icon">
|
||||
<view class="icon-text">💵</view>
|
||||
</view>
|
||||
@@ -156,6 +156,16 @@
|
||||
<view class="section-title">会员维护</view>
|
||||
<view class="feature-row">
|
||||
<!-- 管理员功能 -->
|
||||
<view v-if="checkPermi(['work:member:setting'])" class="feature-card" @click="goToMemberSetting">
|
||||
<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="checkPermi(['work:member:order'])" class="feature-card" @click="goToMemberOrder">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">🛒</view>
|
||||
@@ -244,15 +254,12 @@
|
||||
import { checkPermi } from "@/utils/permission"
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const userRole = ref('admin') // 模拟角色,实际应从登录状态获取
|
||||
const exceptionCount = ref({ // 模拟异常数量
|
||||
profit: 2, // 分润异常数量
|
||||
member: 3 // 会员订单异常数量
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从登录状态或接口获取用户角色
|
||||
// userRole.value = getUserRole()
|
||||
|
||||
// 实际项目中应从接口获取异常数量
|
||||
// getExceptionCount()
|
||||
@@ -370,6 +377,12 @@
|
||||
})
|
||||
}
|
||||
|
||||
function goToMemberSetting() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/member/setting'
|
||||
})
|
||||
}
|
||||
|
||||
// 统计分析相关
|
||||
function goToDistributionStatistics() {
|
||||
uni.navigateTo({
|
||||
|
||||
Reference in New Issue
Block a user