shish 11 месяцев назад
Родитель
Сommit
cfe5fa9af3
1 измененных файлов с 519 добавлено и 63 удалено
  1. 519 63
      hdApp/src/admin/member/level.vue

+ 519 - 63
hdApp/src/admin/member/level.vue

@@ -1,93 +1,549 @@
 <template>
 	<view class="app-content">
-		<view>
-			<t-table :headerBackgroundColor="'#F0F2F6'">
-				<view>
-					<t-tr header>
-						<t-th><view style="color:black;">会员等级</view></t-th>
-						<t-th>
-							<view style="color:black;">
-								<view>消费金额</view>
-							</view>
-						</t-th>
-					</t-tr>
-				</view>
-				<view>
-                    <view v-for="(item, inIndex) in map" :key="inIndex">
-                        <t-tr>
-                            <t-td align="center" color="info">
-                                <view style="color:black;font-weight:bold;font-size:30upx;">{{ item.name }}</view>
-                            </t-td>
-                            <t-td align="center" color="info">
-                                <view>
-                                <input v-model="item.amount" type="digit" style="border:1upx solid #cccccc;color:black;font-size:30upx;" @focus="() => clearDiscount(inIndex)" placeholder="请填写" />
-                                </view>
-                            </t-td>
-                        </t-tr>
-                    </view>
-				</view>
-			</t-table>
-			<view style="font-size:36upx;font-weight:bold;height:50upx;margin-top:50upx;display: flex;align-items: center;justify-content: center;">
-				超过
-				<input v-model="reduceDay" type="number" @focus="() => clearReduceDay()" placeholder="0不降级" style="border:1upx solid #cccccc;color:black;font-size:28upx;width:200upx;display: inline-block;text-align:center;margin:0 10upx 0 10upx;" />
-				天未消费降一级
+		<!-- 页面标题 -->
+		<view class="page-header">
+			<view class="page-title">会员等级设置</view>
+			<view class="page-subtitle">设置不同会员等级的消费金额标准</view>
+		</view>
+
+		<!-- 主要内容区域 -->
+		<view class="main-content">
+			<!-- 会员等级表格 -->
+			<view class="table-container">
+				<t-table :headerBackgroundColor="'#f8f9ff'">
+					<view>
+						<t-tr header>
+							<t-th>
+								<view class="table-header">会员等级</view>
+							</t-th>
+							<t-th>
+								<view class="table-header">消费金额 (元)</view>
+							</t-th>
+						</t-tr>
+					</view>
+					<view>
+						<view v-for="(item, inIndex) in map" :key="inIndex">
+							<t-tr>
+								<t-td align="center" color="info">
+									<view class="level-name">{{ item.name }}</view>
+								</t-td>
+								<t-td align="center" color="info">
+									<view class="input-wrapper">
+										<input
+											v-model="item.amount"
+											type="digit"
+											class="amount-input"
+											@focus="() => clearDiscount(inIndex)"
+											placeholder="请填写消费金额"
+										/>
+									</view>
+								</t-td>
+							</t-tr>
+						</view>
+					</view>
+				</t-table>
 			</view>
 
+			<!-- 降级规则设置 -->
+			<view class="rule-container">
+				<view class="rule-title">降级规则</view>
+				<view class="rule-content">
+					<text class="rule-text">超过</text>
+					<input
+						v-model="reduceDay"
+						type="number"
+						class="day-input"
+						@focus="() => clearReduceDay()"
+						placeholder="30"
+					/>
+					<text class="rule-text">天未消费降一级</text>
+				</view>
+				<view class="rule-tip">*设置为0表示不降级</view>
+			</view>
 		</view>
-        <view class="app-footer">
-			<view class="admin-button-com big blue" @click="goBack()">返回上页</view>
-		    <view style="margin-left:50upx;" class="admin-button-com big blue" @click="saveData">提交修改</view>
+
+		<!-- 底部按钮 -->
+		<view class="app-footer">
+			<view class="button-group">
+				<view class="btn btn-secondary" @click="goBack()">
+					<text class="btn-text">返回上页</text>
+				</view>
+				<view class="btn btn-primary" @click="saveData">
+					<text class="btn-text">提交修改</text>
+				</view>
+			</view>
 		</view>
 	</view>
 </template>
 <script>
 import AppWrapperEmpty from "@/components/app-wrapper-empty";
-import list from '@/mixins/list'
+import list from '@/mixins/list';
 import ModalModule from "@/components/plugin/modal";
-import { getLevelInitData,modifyLevel } from '@/api/member'
+import { getLevelInitData, modifyLevel } from '@/api/member';
+
 export default {
-	name: "addPrice",
+	name: "MemberLevel",
 	components: {
-		AppWrapperEmpty,ModalModule
+		AppWrapperEmpty,
+		ModalModule
 	},
-	mixins:[list],
+	mixins: [list],
 	data() {
 		return {
-			map:[],
-			reduceDay:30
+			// 会员等级数据
+			map: [],
+			// 降级天数设置
+			reduceDay: 30
 		};
 	},
 	methods: {
-        init(){
-			getLevelInitData().then(res=>{
-				if(res.code == 1){
-					this.map = res.data.member?res.data.member:[]
-					this.reduceDay = res.data.reduceDay?res.data.reduceDay:30
+		/**
+		 * 初始化页面数据
+		 */
+		init() {
+			getLevelInitData().then(res => {
+				if (res.code === 1) {
+					this.map = res.data.member || [];
+					this.reduceDay = res.data.reduceDay || 30;
 				}
-			})
-        },
-		clearDiscount(index){
-			this.$set(this.map[index], 'amount', '')
+			}).catch(err => {
+				console.error('获取会员等级数据失败:', err);
+				this.$msg('获取数据失败,请重试');
+			});
 		},
-		clearReduceDay(){
-			this.reduceDay = ''
+
+		/**
+		 * 清空指定等级的消费金额
+		 * @param {number} index - 等级索引
+		 */
+		clearDiscount(index) {
+			this.$set(this.map[index], 'amount', '');
 		},
-		goBack(){
-			uni.navigateBack()
+
+		/**
+		 * 清空降级天数设置
+		 */
+		clearReduceDay() {
+			this.reduceDay = '';
+		},
+
+		/**
+		 * 返回上一页
+		 */
+		goBack() {
+			uni.navigateBack();
 		},
-		saveData(){
-			this.$util.confirmModal({content:'确认提交?提交后将不能再修改'},() => {
-				modifyLevel({data:this.map,reduceDay:this.reduceDay}).then(res=>{
-					if(res.code == 1){
-						this.$msg(res.msg)
+
+		/**
+		 * 保存数据
+		 */
+		saveData() {
+			// 数据验证
+			if (!this.validateData()) {
+				return;
+			}
+
+			const confirmContent = '确认提交?提交后将不能再修改';
+			this.$util.confirmModal({ content: confirmContent }, () => {
+				const requestData = {
+					data: this.map,
+					reduceDay: this.reduceDay
+				};
+
+				modifyLevel(requestData).then(res => {
+					if (res.code === 1) {
+						this.$msg(res.msg);
 						setTimeout(() => {
-							uni.navigateBack({})
+							uni.navigateBack();
 						}, 900);
+					} else {
+						this.$msg(res.msg || '保存失败,请重试');
 					}
-				})
-			})
+				}).catch(err => {
+					console.error('保存会员等级设置失败:', err);
+					this.$msg('保存失败,请重试');
+				});
+			});
+		},
+
+		/**
+		 * 验证表单数据
+		 * @returns {boolean} 验证结果
+		 */
+		validateData() {
+			// 检查是否有空的消费金额
+			const hasEmptyAmount = this.map.some(item => !item.amount || item.amount === '');
+			if (hasEmptyAmount) {
+				this.$msg('请填写完整的消费金额');
+				return false;
+			}
+
+			// 检查消费金额是否为正数
+			const hasInvalidAmount = this.map.some(item => {
+				const amount = parseFloat(item.amount);
+				return isNaN(amount) || amount < 0;
+			});
+			if (hasInvalidAmount) {
+				this.$msg('请输入有效的消费金额');
+				return false;
+			}
+
+			// 检查降级天数
+			if (this.reduceDay !== '' && this.reduceDay !== 0) {
+				const reduceDayNum = parseInt(this.reduceDay);
+				if (isNaN(reduceDayNum) || reduceDayNum < 0) {
+					this.$msg('请输入有效的降级天数');
+					return false;
+				}
+			}
+
+			return true;
 		}
 	}
 };
 </script>
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.app-content {
+	background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+	min-height: 100vh;
+	padding: 0;
+	padding-bottom: 160rpx; /* 为底部按钮预留足够空间 */
+	display: flex;
+	flex-direction: column;
+}
+
+/* 页面头部 */
+.page-header {
+	background: #fff;
+	padding: 40rpx 30rpx 30rpx;
+	margin-bottom: 30rpx;
+	box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
+	border-radius: 0 0 20rpx 20rpx;
+	
+	.page-title {
+		font-size: 44rpx;
+		font-weight: 600;
+		color: #2c3e50;
+		text-align: center;
+		margin-bottom: 12rpx;
+	}
+	
+	.page-subtitle {
+		font-size: 28rpx;
+		color: #7f8c8d;
+		text-align: center;
+		opacity: 0.8;
+	}
+}
+
+/* 主要内容区域 */
+.main-content {
+	padding: 0 30rpx;
+	flex: 1;
+}
+
+/* 表格容器 */
+.table-container {
+	background: #fff;
+	border-radius: 16rpx;
+	box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
+	overflow: hidden;
+	margin-bottom: 40rpx;
+	
+	/* 覆盖表格组件默认样式 */
+	:deep(.t-table) {
+		border: none;
+		
+		.t-tr {
+			border-bottom: 1rpx solid #f0f2f5;
+			
+			&:last-child {
+				border-bottom: none;
+			}
+		}
+		
+		.t-th, .t-td {
+			padding: 24rpx 20rpx;
+			border-right: 1rpx solid #f0f2f5;
+			
+			&:last-child {
+				border-right: none;
+			}
+		}
+		
+		.t-th {
+			background: #f8f9ff !important;
+		}
+	}
+}
+
+.table-header {
+	color: #2c3e50;
+	font-size: 32rpx;
+	font-weight: 600;
+}
+
+.level-name {
+	color: #2c3e50;
+	font-weight: 600;
+	font-size: 32rpx;
+	padding: 8rpx 16rpx;
+	background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
+	background: -webkit-linear-gradient(45deg, #667eea 0%, #764ba2 100%);
+	color: #fff;
+	border-radius: 20rpx;
+	display: inline-block;
+	min-width: 120rpx;
+	text-align: center;
+}
+
+.input-wrapper {
+	padding: 8rpx;
+}
+
+.amount-input {
+	width: 200rpx;
+	height: 70rpx;
+	border: 2rpx solid #e1e8ed;
+	border-radius: 12rpx;
+	padding: 0 20rpx;
+	font-size: 30rpx;
+	color: #2c3e50;
+	text-align: center;
+	background: #fff;
+	transition: all 0.3s ease;
+	
+	&:focus {
+		border-color: #667eea;
+		box-shadow: 0 0 0 6rpx rgba(102, 126, 234, 0.1);
+		outline: none;
+	}
+	
+	&::placeholder {
+		color: #bdc3c7;
+		font-size: 26rpx;
+	}
+}
+
+/* 降级规则设置 */
+.rule-container {
+	background: #fff;
+	border-radius: 16rpx;
+	padding: 40rpx 30rpx;
+	box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
+	margin-bottom: 120rpx; /* 增加底部间距,避免被按钮遮挡 */
+}
+
+.rule-title {
+	font-size: 36rpx;
+	font-weight: 600;
+	color: #2c3e50;
+	margin-bottom: 24rpx;
+	text-align: center;
+}
+
+.rule-content {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	flex-wrap: wrap;
+	gap: 16rpx;
+	margin-bottom: 20rpx;
+}
+
+.rule-text {
+	font-size: 32rpx;
+	color: #2c3e50;
+	font-weight: 500;
+}
+
+.day-input {
+	width: 120rpx;
+	height: 60rpx;
+	border: 2rpx solid #e1e8ed;
+	border-radius: 12rpx;
+	padding: 0 16rpx;
+	font-size: 30rpx;
+	color: #2c3e50;
+	text-align: center;
+	background: #fff;
+	transition: all 0.3s ease;
+	
+	&:focus {
+		border-color: #667eea;
+		box-shadow: 0 0 0 6rpx rgba(102, 126, 234, 0.1);
+		outline: none;
+	}
+	
+	&::placeholder {
+		color: #bdc3c7;
+		font-size: 26rpx;
+	}
+}
+
+.rule-tip {
+	font-size: 24rpx;
+	color: #95a5a6;
+	text-align: center;
+	font-style: italic;
+}
+
+/* 底部按钮区域 */
+.app-footer {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	background: #fff;
+	padding: 25rpx 30rpx 35rpx;
+	border-radius: 20rpx 20rpx 0 0;
+	box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.12);
+	z-index: 999;
+}
+
+.button-group {
+	display: flex;
+	gap: 24rpx;
+	justify-content: center;
+}
+
+.btn {
+	flex: 1;
+	min-width: 200rpx;
+	max-width: 320rpx;
+	height: 88rpx;
+	border-radius: 44rpx;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	transition: all 0.3s ease;
+	position: relative;
+	overflow: hidden;
+	padding: 0 30rpx; /* 增加内边距防止文字溢出 */
+	
+	&::before {
+		content: '';
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		background: rgba(255, 255, 255, 0.2);
+		opacity: 0;
+		transition: opacity 0.3s ease;
+	}
+	
+	&:active::before {
+		opacity: 1;
+	}
+}
+
+.btn-secondary {
+	background: linear-gradient(45deg, #95a5a6, #7f8c8d);
+	box-shadow: 0 4rpx 15rpx rgba(149, 165, 166, 0.4);
+	
+	&:active {
+		transform: translateY(2rpx);
+		box-shadow: 0 2rpx 8rpx rgba(149, 165, 166, 0.4);
+	}
+}
+
+.btn-primary {
+	background: linear-gradient(45deg, #667eea, #764ba2);
+	box-shadow: 0 4rpx 15rpx rgba(102, 126, 234, 0.4);
+	
+	&:active {
+		transform: translateY(2rpx);
+		box-shadow: 0 2rpx 8rpx rgba(102, 126, 234, 0.4);
+	}
+}
+
+.btn-text {
+	color: #fff;
+	font-size: 32rpx;
+	font-weight: 600;
+	white-space: nowrap; /* 防止文字换行 */
+	text-overflow: ellipsis; /* 文字溢出时显示省略号 */
+	overflow: hidden;
+}
+
+/* 响应式设计 */
+@media screen and (max-width: 750rpx) {
+	.page-header {
+		padding: 30rpx 20rpx 20rpx;
+		
+		.page-title {
+			font-size: 38rpx;
+		}
+		
+		.page-subtitle {
+			font-size: 26rpx;
+		}
+	}
+	
+	.main-content {
+		padding: 0 20rpx;
+	}
+	
+	.rule-content {
+		flex-direction: column;
+		gap: 12rpx;
+	}
+	
+	.button-group {
+		flex-direction: column;
+		gap: 16rpx;
+		
+		.btn {
+			max-width: none;
+			min-width: auto;
+		}
+	}
+	
+	.app-footer {
+		padding: 20rpx 20rpx 30rpx;
+	}
+}
+
+/* 动画效果 */
+.table-container {
+	animation: slideInUp 0.6s ease-out;
+}
+
+.rule-container {
+	animation: slideInUp 0.8s ease-out;
+}
+
+.app-footer {
+	animation: slideInUp 1s ease-out;
+}
+
+@keyframes slideInUp {
+	from {
+		opacity: 0;
+		transform: translateY(30rpx);
+	}
+	to {
+		opacity: 1;
+		transform: translateY(0);
+	}
+}
+
+/* 高亮聚焦效果 */
+.amount-input:focus,
+.day-input:focus {
+	animation: focusGlow 0.3s ease-in-out;
+}
+
+@keyframes focusGlow {
+	0% {
+		box-shadow: 0 0 0 0 rgba(102, 126, 234, 0.4);
+	}
+	50% {
+		box-shadow: 0 0 0 8rpx rgba(102, 126, 234, 0.2);
+	}
+	100% {
+		box-shadow: 0 0 0 6rpx rgba(102, 126, 234, 0.1);
+	}
+}
+</style>