Initial commit - full huishou project

This commit is contained in:
jiapengyu
2026-07-27 14:07:26 +08:00
commit 60790ad1b3
39127 changed files with 5989265 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const stores_order = require("../../stores/order.js");
const stores_price = require("../../stores/price.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "index",
setup(__props) {
const orderStore = stores_order.useOrderStore();
const priceStore = stores_price.usePriceStore();
const totalOrders = common_vendor.computed(() => orderStore.orders.length);
const totalAmount = common_vendor.computed(() => {
return orderStore.orders.reduce((sum, order) => sum + order.amount, 0);
});
const totalWeight = common_vendor.computed(() => {
return orderStore.orders.reduce((sum, order) => sum + (order.weight || 0), 0);
});
const categoriesCount = common_vendor.computed(() => priceStore.prices.length);
const recentOrders = common_vendor.computed(() => {
return [...orderStore.orders].reverse().slice(0, 5);
});
const getStatusText = (status) => {
const statusMap = {
pending: "待处理",
completed: "已完成",
cancelled: "已取消"
};
return statusMap[status] || status;
};
const logout = () => {
common_vendor.index.showModal({
title: "确认退出",
content: "确定要退出登录吗?",
success: (res) => {
if (res.confirm) {
common_vendor.index.removeStorageSync("admin_login");
common_vendor.index.redirectTo({ url: "/pages/admin/login" });
}
}
});
};
const goToOrderList = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/order/list" });
};
const goToPriceManager = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/price/list" });
};
const goToUserManager = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/user/list" });
};
const goToStatistics = () => {
common_vendor.index.navigateTo({ url: "/pages/admin/statistics" });
};
const goToOrderDetail = (id) => {
common_vendor.index.navigateTo({ url: `/pages/order/detail?id=${id}` });
};
common_vendor.onMounted(() => {
const isLogin = common_vendor.index.getStorageSync("admin_login");
if (!isLogin) {
common_vendor.index.redirectTo({ url: "/pages/admin/login" });
return;
}
orderStore.loadOrders();
priceStore.loadPrices();
});
return (_ctx, _cache) => {
return {
a: common_vendor.o(logout),
b: common_vendor.t(totalOrders.value),
c: common_vendor.t(totalAmount.value.toFixed(2)),
d: common_vendor.t(totalWeight.value.toFixed(2)),
e: common_vendor.t(categoriesCount.value),
f: common_vendor.o(goToOrderList),
g: common_vendor.o(goToPriceManager),
h: common_vendor.o(goToUserManager),
i: common_vendor.o(goToStatistics),
j: common_vendor.o(goToOrderList),
k: common_vendor.f(recentOrders.value, (order, k0, i0) => {
return {
a: common_vendor.t(order.id),
b: common_vendor.t(order.createTime),
c: common_vendor.t(order.amount.toFixed(2)),
d: common_vendor.t(getStatusText(order.status)),
e: common_vendor.n(order.status),
f: order.id,
g: common_vendor.o(($event) => goToOrderDetail(order.id), order.id)
};
}),
l: common_vendor.o(goToOrderList),
m: common_vendor.o(goToPriceManager),
n: common_vendor.o(goToUserManager)
};
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-f94c733c"]]);
wx.createPage(MiniProgramPage);
+5
View File
@@ -0,0 +1,5 @@
{
"navigationStyle": "custom",
"navigationBarTitleText": "管理后台",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="admin-container data-v-f94c733c"><view class="admin-header data-v-f94c733c"><view class="header-left data-v-f94c733c"><text class="header-title data-v-f94c733c">管理后台</text><text class="header-subtitle data-v-f94c733c">易分宝现场回收系统</text></view><view class="header-right data-v-f94c733c" bindtap="{{a}}"><text class="logout-icon data-v-f94c733c">📤</text><text class="logout-text data-v-f94c733c">退出</text></view></view><view class="stats-grid data-v-f94c733c"><view class="stat-card data-v-f94c733c"><view class="stat-icon data-v-f94c733c">📊</view><view class="stat-info data-v-f94c733c"><text class="stat-value data-v-f94c733c">{{b}}</text><text class="stat-label data-v-f94c733c">今日订单</text></view></view><view class="stat-card data-v-f94c733c"><view class="stat-icon data-v-f94c733c">💰</view><view class="stat-info data-v-f94c733c"><text class="stat-value data-v-f94c733c">¥{{c}}</text><text class="stat-label data-v-f94c733c">今日金额</text></view></view><view class="stat-card data-v-f94c733c"><view class="stat-icon data-v-f94c733c">♻️</view><view class="stat-info data-v-f94c733c"><text class="stat-value data-v-f94c733c">{{d}}kg</text><text class="stat-label data-v-f94c733c">回收总量</text></view></view><view class="stat-card data-v-f94c733c"><view class="stat-icon data-v-f94c733c">📦</view><view class="stat-info data-v-f94c733c"><text class="stat-value data-v-f94c733c">{{e}}</text><text class="stat-label data-v-f94c733c">回收品类</text></view></view></view><view class="quick-actions data-v-f94c733c"><view class="section-title data-v-f94c733c">快捷操作</view><view class="action-grid data-v-f94c733c"><view class="action-item data-v-f94c733c" bindtap="{{f}}"><view class="action-icon data-v-f94c733c">📋</view><text class="action-name data-v-f94c733c">订单管理</text></view><view class="action-item data-v-f94c733c" bindtap="{{g}}"><view class="action-icon data-v-f94c733c">💰</view><text class="action-name data-v-f94c733c">价格管理</text></view><view class="action-item data-v-f94c733c" bindtap="{{h}}"><view class="action-icon data-v-f94c733c">👥</view><text class="action-name data-v-f94c733c">用户管理</text></view><view class="action-item data-v-f94c733c" bindtap="{{i}}"><view class="action-icon data-v-f94c733c">📈</view><text class="action-name data-v-f94c733c">统计报表</text></view></view></view><view class="recent-orders data-v-f94c733c"><view class="section-title data-v-f94c733c"><text class="data-v-f94c733c">最近订单</text><text class="view-all data-v-f94c733c" bindtap="{{j}}">查看全部</text></view><view class="order-list data-v-f94c733c"><view wx:for="{{k}}" wx:for-item="order" wx:key="f" class="order-item data-v-f94c733c" bindtap="{{order.g}}"><view class="order-left data-v-f94c733c"><view class="order-id data-v-f94c733c">{{order.a}}</view><view class="order-time data-v-f94c733c">{{order.b}}</view></view><view class="order-right data-v-f94c733c"><view class="order-amount data-v-f94c733c">¥{{order.c}}</view><view class="{{['order-status', 'data-v-f94c733c', order.e]}}">{{order.d}}</view></view></view></view></view><view class="tab-bar data-v-f94c733c"><view class="tab-item active data-v-f94c733c"><text class="tab-icon data-v-f94c733c">🏠</text><text class="tab-text data-v-f94c733c">首页</text></view><view class="tab-item data-v-f94c733c" bindtap="{{l}}"><text class="tab-icon data-v-f94c733c">📋</text><text class="tab-text data-v-f94c733c">订单</text></view><view class="tab-item data-v-f94c733c" bindtap="{{m}}"><text class="tab-icon data-v-f94c733c">💰</text><text class="tab-text data-v-f94c733c">价格</text></view><view class="tab-item data-v-f94c733c" bindtap="{{n}}"><text class="tab-icon data-v-f94c733c">👤</text><text class="tab-text data-v-f94c733c">用户</text></view></view></view>
+198
View File
@@ -0,0 +1,198 @@
.admin-container.data-v-f94c733c {
min-height: 100vh;
background: #f5f7fa;
padding-bottom: 120rpx;
}
.admin-header.data-v-f94c733c {
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
padding: 48rpx 32rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.header-left.data-v-f94c733c {
color: #fff;
}
.header-title.data-v-f94c733c {
font-size: 40rpx;
font-weight: 700;
display: block;
}
.header-subtitle.data-v-f94c733c {
font-size: 24rpx;
opacity: 0.8;
margin-top: 4rpx;
}
.header-right.data-v-f94c733c {
display: flex;
align-items: center;
color: #fff;
padding: 12rpx 24rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 24rpx;
}
.logout-icon.data-v-f94c733c {
font-size: 28rpx;
margin-right: 8rpx;
}
.logout-text.data-v-f94c733c {
font-size: 26rpx;
}
.stats-grid.data-v-f94c733c {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 16rpx;
padding: 32rpx;
}
.stat-card.data-v-f94c733c {
background: #fff;
border-radius: 12rpx;
padding: 20rpx 16rpx;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.stat-icon.data-v-f94c733c {
font-size: 40rpx;
margin-bottom: 12rpx;
}
.stat-info.data-v-f94c733c {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.stat-value.data-v-f94c733c {
font-size: 28rpx;
font-weight: 700;
color: #3366ff;
}
.stat-label.data-v-f94c733c {
font-size: 20rpx;
color: #999;
margin-top: 4rpx;
}
.quick-actions.data-v-f94c733c, .recent-orders.data-v-f94c733c {
padding: 0 32rpx 32rpx;
}
.section-title.data-v-f94c733c {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.view-all.data-v-f94c733c {
font-size: 26rpx;
color: #3366ff;
font-weight: normal;
}
.action-grid.data-v-f94c733c {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 24rpx;
}
.action-item.data-v-f94c733c {
background: #fff;
border-radius: 16rpx;
padding: 24rpx 16rpx;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.action-item.data-v-f94c733c:active {
opacity: 0.8;
}
.action-icon.data-v-f94c733c {
font-size: 48rpx;
margin-bottom: 12rpx;
}
.action-name.data-v-f94c733c {
font-size: 24rpx;
color: #333;
text-align: center;
}
.order-list.data-v-f94c733c {
background: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.order-item.data-v-f94c733c {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.order-item.data-v-f94c733c:last-child {
border-bottom: none;
}
.order-item.data-v-f94c733c:active {
background: #f9f9f9;
}
.order-id.data-v-f94c733c {
font-size: 28rpx;
font-weight: 600;
color: #333;
}
.order-time.data-v-f94c733c {
font-size: 24rpx;
color: #999;
margin-top: 4rpx;
}
.order-amount.data-v-f94c733c {
font-size: 32rpx;
font-weight: 700;
color: #3366ff;
}
.order-status.data-v-f94c733c {
font-size: 22rpx;
padding: 6rpx 16rpx;
border-radius: 20rpx;
margin-top: 8rpx;
}
.order-status.pending.data-v-f94c733c {
background: #fff3e0;
color: #f59e0b;
}
.order-status.completed.data-v-f94c733c {
background: #dcfce7;
color: #3366ff;
}
.order-status.cancelled.data-v-f94c733c {
background: #fef2f2;
color: #ef4444;
}
.tab-bar.data-v-f94c733c {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
background: #fff;
display: flex;
box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.tab-item.data-v-f94c733c {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.tab-item.active .tab-icon.data-v-f94c733c, .tab-item.active .tab-text.data-v-f94c733c {
color: #3366ff;
}
.tab-icon.data-v-f94c733c {
font-size: 36rpx;
}
.tab-text.data-v-f94c733c {
font-size: 22rpx;
color: #999;
margin-top: 4rpx;
}
+48
View File
@@ -0,0 +1,48 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "login",
setup(__props) {
const username = common_vendor.ref("");
const password = common_vendor.ref("");
const rememberMe = common_vendor.ref(false);
const login = () => {
if (!username.value) {
common_vendor.index.showToast({ title: "请输入用户名", icon: "none" });
return;
}
if (!password.value) {
common_vendor.index.showToast({ title: "请输入密码", icon: "none" });
return;
}
if (username.value === "admin" && password.value === "123456") {
common_vendor.index.setStorageSync("admin_login", true);
common_vendor.index.showToast({ title: "登录成功", icon: "success" });
setTimeout(() => {
common_vendor.index.redirectTo({ url: "/pages/admin/index" });
}, 1500);
} else {
common_vendor.index.showToast({ title: "用户名或密码错误", icon: "none" });
}
};
const forgotPassword = () => {
common_vendor.index.showToast({ title: "请联系管理员重置密码", icon: "none" });
};
return (_ctx, _cache) => {
return common_vendor.e({
a: username.value,
b: common_vendor.o(($event) => username.value = $event.detail.value),
c: password.value,
d: common_vendor.o(($event) => password.value = $event.detail.value),
e: rememberMe.value
}, rememberMe.value ? {} : {}, {
f: rememberMe.value ? 1 : "",
g: common_vendor.o(($event) => rememberMe.value = !rememberMe.value),
h: common_vendor.o(login),
i: common_vendor.o(forgotPassword)
});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-6b759fa6"]]);
wx.createPage(MiniProgramPage);
+5
View File
@@ -0,0 +1,5 @@
{
"navigationStyle": "custom",
"navigationBarTitleText": "管理员登录",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="login-container data-v-6b759fa6"><view class="login-box data-v-6b759fa6"><view class="login-logo data-v-6b759fa6">🔧</view><view class="login-title data-v-6b759fa6">易分宝管理后台</view><view class="login-subtitle data-v-6b759fa6">管理员登录</view><view class="form-group data-v-6b759fa6"><view class="form-label data-v-6b759fa6">用户名</view><input type="text" class="form-input data-v-6b759fa6" placeholder="请输入用户名" value="{{a}}" bindinput="{{b}}"/></view><view class="form-group data-v-6b759fa6"><view class="form-label data-v-6b759fa6">密码</view><input type="password" class="form-input data-v-6b759fa6" placeholder="请输入密码" value="{{c}}" bindinput="{{d}}"/></view><view class="form-group data-v-6b759fa6"><view class="checkbox data-v-6b759fa6" bindtap="{{g}}"><view class="{{['checkbox-box', 'data-v-6b759fa6', f && 'checked']}}"><text wx:if="{{e}}" class="data-v-6b759fa6">✓</text></view><text class="data-v-6b759fa6">记住密码</text></view></view><view class="login-btn data-v-6b759fa6" bindtap="{{h}}"><text class="data-v-6b759fa6">登录</text></view><view class="forgot-link data-v-6b759fa6" bindtap="{{i}}"><text class="data-v-6b759fa6">忘记密码?</text></view></view></view>
+102
View File
@@ -0,0 +1,102 @@
.login-container.data-v-6b759fa6 {
min-height: 100vh;
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 32rpx;
}
.login-box.data-v-6b759fa6 {
width: 100%;
max-width: 600rpx;
background: #fff;
border-radius: 24rpx;
padding: 64rpx 48rpx;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.15);
}
.login-logo.data-v-6b759fa6 {
font-size: 96rpx;
text-align: center;
margin-bottom: 24rpx;
}
.login-title.data-v-6b759fa6 {
font-size: 40rpx;
font-weight: 700;
color: #333;
text-align: center;
margin-bottom: 8rpx;
}
.login-subtitle.data-v-6b759fa6 {
font-size: 28rpx;
color: #999;
text-align: center;
margin-bottom: 48rpx;
}
.form-group.data-v-6b759fa6 {
margin-bottom: 32rpx;
}
.form-label.data-v-6b759fa6 {
font-size: 28rpx;
color: #666;
margin-bottom: 12rpx;
}
.form-input.data-v-6b759fa6 {
width: 100%;
height: 88rpx;
border: 2rpx solid #e5e7eb;
border-radius: 12rpx;
padding: 0 24rpx;
font-size: 32rpx;
box-sizing: border-box;
}
.form-input.data-v-6b759fa6:focus {
border-color: #3366ff;
}
.checkbox.data-v-6b759fa6 {
display: flex;
align-items: center;
font-size: 26rpx;
color: #666;
}
.checkbox-box.data-v-6b759fa6 {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #ccc;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12rpx;
font-size: 24rpx;
color: #fff;
}
.checkbox-box.checked.data-v-6b759fa6 {
background: #3366ff;
border-color: #3366ff;
}
.login-btn.data-v-6b759fa6 {
width: 100%;
height: 88rpx;
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
margin-top: 16rpx;
}
.login-btn text.data-v-6b759fa6 {
font-size: 32rpx;
font-weight: 600;
color: #fff;
}
.login-btn.data-v-6b759fa6:active {
opacity: 0.9;
}
.forgot-link.data-v-6b759fa6 {
text-align: center;
margin-top: 32rpx;
}
.forgot-link text.data-v-6b759fa6 {
font-size: 26rpx;
color: #3366ff;
}
+126
View File
@@ -0,0 +1,126 @@
"use strict";
const common_vendor = require("../../../common/vendor.js");
const stores_order = require("../../../stores/order.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "list",
setup(__props) {
const orderStore = stores_order.useOrderStore();
const searchKeyword = common_vendor.ref("");
const currentFilter = common_vendor.ref("all");
const filters = [
{ label: "全部", value: "all" },
{ label: "待处理", value: "pending" },
{ label: "已完成", value: "completed" },
{ label: "已取消", value: "cancelled" }
];
const filteredOrders = common_vendor.computed(() => {
let orders = orderStore.orders;
if (currentFilter.value !== "all") {
orders = orders.filter((order) => order.status === currentFilter.value);
}
if (searchKeyword.value) {
const keyword = searchKeyword.value.toLowerCase();
orders = orders.filter(
(order) => order.id.toLowerCase().includes(keyword) || order.name.toLowerCase().includes(keyword)
);
}
return [...orders].reverse();
});
const getStatusText = (status) => {
const statusMap = {
pending: "待处理",
completed: "已完成",
cancelled: "已取消"
};
return statusMap[status] || status;
};
const goToDetail = (id) => {
common_vendor.index.navigateTo({ url: `/pages/order/detail?id=${id}` });
};
const confirmOrder = (id) => {
common_vendor.index.showModal({
title: "确认订单",
content: "确定要确认此订单吗?",
success: (res) => {
if (res.confirm) {
orderStore.updateOrderStatus(id, "completed");
common_vendor.index.showToast({ title: "已确认", icon: "success" });
}
}
});
};
const cancelOrder = (id) => {
common_vendor.index.showModal({
title: "取消订单",
content: "确定要取消此订单吗?",
success: (res) => {
if (res.confirm) {
orderStore.updateOrderStatus(id, "cancelled");
common_vendor.index.showToast({ title: "已取消", icon: "success" });
}
}
});
};
const goToHome = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/index" });
};
const goToPriceManager = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/price/list" });
};
const goToUserManager = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/user/list" });
};
common_vendor.onMounted(() => {
const isLogin = common_vendor.index.getStorageSync("admin_login");
if (!isLogin) {
common_vendor.index.redirectTo({ url: "/pages/admin/login" });
return;
}
orderStore.loadOrders();
});
return (_ctx, _cache) => {
return common_vendor.e({
a: searchKeyword.value,
b: common_vendor.o(($event) => searchKeyword.value = $event.detail.value),
c: common_vendor.f(filters, (filter, k0, i0) => {
return {
a: common_vendor.t(filter.label),
b: filter.value,
c: currentFilter.value === filter.value ? 1 : "",
d: common_vendor.o(($event) => currentFilter.value = filter.value, filter.value)
};
}),
d: common_vendor.f(filteredOrders.value, (order, k0, i0) => {
return common_vendor.e({
a: common_vendor.t(order.id),
b: common_vendor.t(getStatusText(order.status)),
c: common_vendor.n(order.status),
d: common_vendor.t(order.name),
e: common_vendor.t(order.weight ? order.weight + "kg" : order.count ? order.count + "个" : "-"),
f: common_vendor.t(order.unitPrice),
g: common_vendor.t(order.unit === "kg" ? "kg" : "个"),
h: common_vendor.t(order.createTime),
i: common_vendor.t(order.amount.toFixed(2)),
j: order.status === "pending"
}, order.status === "pending" ? {
k: common_vendor.o(($event) => confirmOrder(order.id), order.id)
} : {}, {
l: order.status !== "cancelled"
}, order.status !== "cancelled" ? {
m: common_vendor.o(($event) => cancelOrder(order.id), order.id)
} : {}, {
n: order.id,
o: common_vendor.o(($event) => goToDetail(order.id), order.id)
});
}),
e: filteredOrders.value.length === 0
}, filteredOrders.value.length === 0 ? {} : {}, {
f: common_vendor.o(goToHome),
g: common_vendor.o(goToPriceManager),
h: common_vendor.o(goToUserManager)
});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-cdbe62fb"]]);
wx.createPage(MiniProgramPage);
+5
View File
@@ -0,0 +1,5 @@
{
"navigationStyle": "custom",
"navigationBarTitleText": "订单管理",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="admin-container data-v-cdbe62fb"><view class="admin-header data-v-cdbe62fb"><view class="header-left data-v-cdbe62fb"><text class="header-title data-v-cdbe62fb">订单管理</text><text class="header-subtitle data-v-cdbe62fb">全部订单</text></view></view><view class="search-bar data-v-cdbe62fb"><view class="search-input-wrap data-v-cdbe62fb"><text class="search-icon data-v-cdbe62fb">🔍</text><input type="text" class="search-input data-v-cdbe62fb" placeholder="搜索订单号或品类" value="{{a}}" bindinput="{{b}}"/></view></view><view class="filter-bar data-v-cdbe62fb"><view wx:for="{{c}}" wx:for-item="filter" wx:key="b" class="{{['filter-item', 'data-v-cdbe62fb', filter.c && 'active']}}" bindtap="{{filter.d}}">{{filter.a}}</view></view><view class="order-list data-v-cdbe62fb"><view wx:for="{{d}}" wx:for-item="order" wx:key="n" class="order-card data-v-cdbe62fb" bindtap="{{order.o}}"><view class="order-header data-v-cdbe62fb"><view class="order-id data-v-cdbe62fb">订单? {{order.a}}</view><view class="{{['order-status', 'data-v-cdbe62fb', order.c]}}">{{order.b}}</view></view><view class="order-info data-v-cdbe62fb"><view class="info-row data-v-cdbe62fb"><text class="info-label data-v-cdbe62fb">品类:</text><text class="info-value data-v-cdbe62fb">{{order.d}}</text></view><view class="info-row data-v-cdbe62fb"><text class="info-label data-v-cdbe62fb">重量:</text><text class="info-value data-v-cdbe62fb">{{order.e}}</text></view><view class="info-row data-v-cdbe62fb"><text class="info-label data-v-cdbe62fb">单价:</text><text class="info-value data-v-cdbe62fb">¥{{order.f}}/{{order.g}}</text></view><view class="info-row data-v-cdbe62fb"><text class="info-label data-v-cdbe62fb">时间:</text><text class="info-value data-v-cdbe62fb">{{order.h}}</text></view></view><view class="order-footer data-v-cdbe62fb"><text class="total-amount data-v-cdbe62fb">¥{{order.i}}</text><view class="order-actions data-v-cdbe62fb"><view wx:if="{{order.j}}" class="action-btn confirm data-v-cdbe62fb" catchtap="{{order.k}}"> 确认 </view><view wx:if="{{order.l}}" class="action-btn cancel data-v-cdbe62fb" catchtap="{{order.m}}"> 取消 </view></view></view></view></view><view wx:if="{{e}}" class="empty-state data-v-cdbe62fb"><text class="empty-icon data-v-cdbe62fb">📭</text><text class="empty-text data-v-cdbe62fb">暂无订单</text></view><view class="tab-bar data-v-cdbe62fb"><view class="tab-item data-v-cdbe62fb" bindtap="{{f}}"><text class="tab-icon data-v-cdbe62fb">🏠</text><text class="tab-text data-v-cdbe62fb">首页</text></view><view class="tab-item active data-v-cdbe62fb"><text class="tab-icon data-v-cdbe62fb">📋</text><text class="tab-text data-v-cdbe62fb">订单</text></view><view class="tab-item data-v-cdbe62fb" bindtap="{{g}}"><text class="tab-icon data-v-cdbe62fb">💰</text><text class="tab-text data-v-cdbe62fb">价格</text></view><view class="tab-item data-v-cdbe62fb" bindtap="{{h}}"><text class="tab-icon data-v-cdbe62fb">👤</text><text class="tab-text data-v-cdbe62fb">用户</text></view></view></view>
+189
View File
@@ -0,0 +1,189 @@
.admin-container.data-v-cdbe62fb {
min-height: 100vh;
background: #f5f7fa;
padding-bottom: 120rpx;
}
.admin-header.data-v-cdbe62fb {
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
padding: 48rpx 32rpx;
}
.header-left.data-v-cdbe62fb {
color: #fff;
}
.header-title.data-v-cdbe62fb {
font-size: 40rpx;
font-weight: 700;
display: block;
}
.header-subtitle.data-v-cdbe62fb {
font-size: 24rpx;
opacity: 0.8;
margin-top: 4rpx;
}
.search-bar.data-v-cdbe62fb {
padding: 24rpx 32rpx;
}
.search-input-wrap.data-v-cdbe62fb {
display: flex;
align-items: center;
background: #fff;
border-radius: 40rpx;
padding: 0 24rpx;
height: 72rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.search-icon.data-v-cdbe62fb {
font-size: 28rpx;
margin-right: 16rpx;
}
.search-input.data-v-cdbe62fb {
flex: 1;
font-size: 28rpx;
}
.filter-bar.data-v-cdbe62fb {
display: flex;
gap: 16rpx;
padding: 0 32rpx 24rpx;
overflow-x: auto;
}
.filter-item.data-v-cdbe62fb {
padding: 12rpx 28rpx;
background: #fff;
border-radius: 24rpx;
font-size: 26rpx;
color: #666;
white-space: nowrap;
}
.filter-item.active.data-v-cdbe62fb {
background: #3366ff;
color: #fff;
}
.order-list.data-v-cdbe62fb {
padding: 0 32rpx;
}
.order-card.data-v-cdbe62fb {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.order-header.data-v-cdbe62fb {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.order-id.data-v-cdbe62fb {
font-size: 26rpx;
color: #666;
}
.order-status.data-v-cdbe62fb {
font-size: 22rpx;
padding: 6rpx 16rpx;
border-radius: 20rpx;
}
.order-status.pending.data-v-cdbe62fb {
background: #fff3e0;
color: #f59e0b;
}
.order-status.completed.data-v-cdbe62fb {
background: #dcfce7;
color: #3366ff;
}
.order-status.cancelled.data-v-cdbe62fb {
background: #fef2f2;
color: #ef4444;
}
.order-info.data-v-cdbe62fb {
margin-bottom: 20rpx;
}
.info-row.data-v-cdbe62fb {
display: flex;
margin-bottom: 12rpx;
}
.info-row.data-v-cdbe62fb:last-child {
margin-bottom: 0;
}
.info-label.data-v-cdbe62fb {
font-size: 26rpx;
color: #999;
width: 100rpx;
}
.info-value.data-v-cdbe62fb {
font-size: 26rpx;
color: #333;
}
.order-footer.data-v-cdbe62fb {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 16rpx;
border-top: 1rpx solid #f0f0f0;
}
.total-amount.data-v-cdbe62fb {
font-size: 32rpx;
font-weight: 700;
color: #3366ff;
}
.order-actions.data-v-cdbe62fb {
display: flex;
gap: 16rpx;
}
.action-btn.data-v-cdbe62fb {
padding: 12rpx 28rpx;
border-radius: 24rpx;
font-size: 24rpx;
}
.action-btn.confirm.data-v-cdbe62fb {
background: #3366ff;
color: #fff;
}
.action-btn.cancel.data-v-cdbe62fb {
background: #f5f5f5;
color: #666;
}
.empty-state.data-v-cdbe62fb {
display: flex;
flex-direction: column;
align-items: center;
padding: 100rpx 0;
}
.empty-icon.data-v-cdbe62fb {
font-size: 96rpx;
margin-bottom: 24rpx;
}
.empty-text.data-v-cdbe62fb {
font-size: 28rpx;
color: #999;
}
.tab-bar.data-v-cdbe62fb {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
background: #fff;
display: flex;
box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.tab-item.data-v-cdbe62fb {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.tab-item.active .tab-icon.data-v-cdbe62fb, .tab-item.active .tab-text.data-v-cdbe62fb {
color: #3366ff;
}
.tab-icon.data-v-cdbe62fb {
font-size: 36rpx;
}
.tab-text.data-v-cdbe62fb {
font-size: 22rpx;
color: #999;
margin-top: 4rpx;
}
+162
View File
@@ -0,0 +1,162 @@
"use strict";
const common_vendor = require("../../../common/vendor.js");
const stores_price = require("../../../stores/price.js");
const utils_price = require("../../../utils/price.js");
if (!Array) {
const _easycom_uni_icons2 = common_vendor.resolveComponent("uni-icons");
_easycom_uni_icons2();
}
const _easycom_uni_icons = () => "../../../node-modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons.js";
if (!Math) {
_easycom_uni_icons();
}
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "list",
setup(__props) {
const priceStore = stores_price.usePriceStore();
const searchKeyword = common_vendor.ref("");
const showAddModal = common_vendor.ref(false);
const editingItem = common_vendor.ref(null);
const originalCategory = common_vendor.ref("");
const formData = common_vendor.reactive({
category: "",
name: "",
price: "",
unit: "kg"
});
const filteredPrices = common_vendor.computed(() => {
let prices = priceStore.prices;
if (searchKeyword.value) {
const keyword = searchKeyword.value.toLowerCase();
prices = prices.filter(
(item) => item.name.toLowerCase().includes(keyword) || item.category.toLowerCase().includes(keyword)
);
}
return prices;
});
const editPrice = (item) => {
editingItem.value = item;
originalCategory.value = item.category;
formData.category = item.category;
formData.name = item.name;
formData.price = item.price.toString();
formData.unit = item.unit;
showAddModal.value = true;
};
const deletePrice = (category) => {
common_vendor.index.showModal({
title: "确认删除",
content: "确定要删除此品类吗?",
success: (res) => {
if (res.confirm) {
priceStore.deletePrice(category);
common_vendor.index.showToast({ title: "删除成功", icon: "success" });
}
}
});
};
const closeModal = () => {
showAddModal.value = false;
editingItem.value = null;
originalCategory.value = "";
formData.category = "";
formData.name = "";
formData.price = "";
formData.unit = "kg";
};
const savePrice = () => {
if (!formData.category) {
common_vendor.index.showToast({ title: "请输入品类代码", icon: "none" });
return;
}
if (!formData.name) {
common_vendor.index.showToast({ title: "请输入品类名称", icon: "none" });
return;
}
if (!formData.price || parseFloat(formData.price) <= 0) {
common_vendor.index.showToast({ title: "请输入有效单价", icon: "none" });
return;
}
if (editingItem.value) {
priceStore.updatePrice({
category: formData.category,
name: formData.name,
price: parseFloat(formData.price),
unit: formData.unit
});
common_vendor.index.showToast({ title: "修改成功", icon: "success" });
} else {
priceStore.addPrice({
category: formData.category,
name: formData.name,
price: parseFloat(formData.price),
unit: formData.unit
});
common_vendor.index.showToast({ title: "新增成功", icon: "success" });
}
closeModal();
};
const goToHome = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/index" });
};
const goToOrderList = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/order/list" });
};
const goToUserManager = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/user/list" });
};
common_vendor.onMounted(() => {
priceStore.loadPrices();
});
return (_ctx, _cache) => {
return common_vendor.e({
a: common_vendor.o(($event) => showAddModal.value = true),
b: searchKeyword.value,
c: common_vendor.o(($event) => searchKeyword.value = $event.detail.value),
d: common_vendor.f(filteredPrices.value, (item, k0, i0) => {
return {
a: "ce40c64c-0-" + i0,
b: common_vendor.p({
type: common_vendor.unref(utils_price.getCategoryIcon)(item.category),
size: 48,
color: "#3366ff"
}),
c: common_vendor.t(item.name),
d: common_vendor.t(item.category),
e: common_vendor.t(item.price),
f: common_vendor.t(item.unit === "kg" ? "kg" : "个"),
g: common_vendor.o(($event) => editPrice(item), item.category),
h: common_vendor.o(($event) => deletePrice(item.category), item.category),
i: item.category
};
}),
e: filteredPrices.value.length === 0
}, filteredPrices.value.length === 0 ? {} : {}, {
f: common_vendor.o(goToHome),
g: common_vendor.o(goToOrderList),
h: common_vendor.o(goToUserManager),
i: showAddModal.value
}, showAddModal.value ? {
j: common_vendor.t(editingItem.value ? "编辑品类" : "新增品类"),
k: common_vendor.o(closeModal),
l: formData.category,
m: common_vendor.o(($event) => formData.category = $event.detail.value),
n: formData.name,
o: common_vendor.o(($event) => formData.name = $event.detail.value),
p: formData.price,
q: common_vendor.o(($event) => formData.price = $event.detail.value),
r: formData.unit === "kg" ? 1 : "",
s: common_vendor.o(($event) => formData.unit = "kg"),
t: formData.unit === "piece" ? 1 : "",
v: common_vendor.o(($event) => formData.unit = "piece"),
w: common_vendor.o(closeModal),
x: common_vendor.o(savePrice),
y: common_vendor.o(() => {
}),
z: common_vendor.o(closeModal)
} : {});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-ce40c64c"]]);
wx.createPage(MiniProgramPage);
+7
View File
@@ -0,0 +1,7 @@
{
"navigationStyle": "custom",
"navigationBarTitleText": "价格管理",
"usingComponents": {
"uni-icons": "../../../node-modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons"
}
}
+1
View File
@@ -0,0 +1 @@
<view class="admin-container data-v-ce40c64c"><view class="admin-header data-v-ce40c64c"><view class="header-left data-v-ce40c64c"><text class="header-title data-v-ce40c64c">价格管理</text><text class="header-subtitle data-v-ce40c64c">回收品类价格设置</text></view><view class="header-right data-v-ce40c64c" bindtap="{{a}}"><text class="add-icon data-v-ce40c64c">+</text><text class="add-text data-v-ce40c64c">新增</text></view></view><view class="search-bar data-v-ce40c64c"><view class="search-input-wrap data-v-ce40c64c"><text class="search-icon data-v-ce40c64c">🔍</text><input type="text" class="search-input data-v-ce40c64c" placeholder="搜索品类名称" value="{{b}}" bindinput="{{c}}"/></view></view><view class="category-list data-v-ce40c64c"><view wx:for="{{d}}" wx:for-item="item" wx:key="i" class="category-card data-v-ce40c64c"><view class="category-icon-wrap data-v-ce40c64c"><uni-icons wx:if="{{item.b}}" class="category-icon data-v-ce40c64c" u-i="{{item.a}}" bind:__l="__l" u-p="{{item.b}}"/></view><view class="category-info data-v-ce40c64c"><view class="category-name data-v-ce40c64c">{{item.c}}</view><view class="category-category data-v-ce40c64c">{{item.d}}</view></view><view class="category-price-info data-v-ce40c64c"><view class="price-value data-v-ce40c64c">¥{{item.e}}</view><view class="price-unit data-v-ce40c64c">/{{item.f}}</view></view><view class="category-actions data-v-ce40c64c"><view class="action-btn edit data-v-ce40c64c" bindtap="{{item.g}}">✏️</view><view class="action-btn delete data-v-ce40c64c" bindtap="{{item.h}}">🗑️</view></view></view></view><view wx:if="{{e}}" class="empty-state data-v-ce40c64c"><text class="empty-icon data-v-ce40c64c">📦</text><text class="empty-text data-v-ce40c64c">暂无品类</text></view><view class="tab-bar data-v-ce40c64c"><view class="tab-item data-v-ce40c64c" bindtap="{{f}}"><text class="tab-icon data-v-ce40c64c">🏠</text><text class="tab-text data-v-ce40c64c">首页</text></view><view class="tab-item data-v-ce40c64c" bindtap="{{g}}"><text class="tab-icon data-v-ce40c64c">📋</text><text class="tab-text data-v-ce40c64c">订单</text></view><view class="tab-item active data-v-ce40c64c"><text class="tab-icon data-v-ce40c64c">💰</text><text class="tab-text data-v-ce40c64c">价格</text></view><view class="tab-item data-v-ce40c64c" bindtap="{{h}}"><text class="tab-icon data-v-ce40c64c">👥</text><text class="tab-text data-v-ce40c64c">用户</text></view></view><view wx:if="{{i}}" class="modal-overlay data-v-ce40c64c" bindtap="{{z}}"><view class="modal-box data-v-ce40c64c" catchtap="{{y}}"><view class="modal-header data-v-ce40c64c"><text class="modal-title data-v-ce40c64c">{{j}}</text><view class="modal-close data-v-ce40c64c" bindtap="{{k}}">×</view></view><view class="modal-body data-v-ce40c64c"><view class="form-group data-v-ce40c64c"><text class="form-label data-v-ce40c64c">品类代码</text><input type="text" class="form-input data-v-ce40c64c" placeholder="如:plastic_bottle" value="{{l}}" bindinput="{{m}}"/></view><view class="form-group data-v-ce40c64c"><text class="form-label data-v-ce40c64c">品类名称</text><input type="text" class="form-input data-v-ce40c64c" placeholder="如:塑料瓶" value="{{n}}" bindinput="{{o}}"/></view><view class="form-group data-v-ce40c64c"><text class="form-label data-v-ce40c64c">单价</text><view class="price-input-wrap data-v-ce40c64c"><text class="price-symbol data-v-ce40c64c">¥</text><input type="digit" class="form-input price-input data-v-ce40c64c" placeholder="0.00" value="{{p}}" bindinput="{{q}}"/></view></view><view class="form-group data-v-ce40c64c"><text class="form-label data-v-ce40c64c">单位</text><view class="unit-options data-v-ce40c64c"><view class="{{['unit-option', 'data-v-ce40c64c', r && 'active']}}" bindtap="{{s}}">kg</view><view class="{{['unit-option', 'data-v-ce40c64c', t && 'active']}}" bindtap="{{v}}">个</view></view></view></view><view class="modal-footer data-v-ce40c64c"><view class="modal-btn cancel data-v-ce40c64c" bindtap="{{w}}">取消</view><view class="modal-btn confirm data-v-ce40c64c" bindtap="{{x}}">保存</view></view></view></view></view>
+286
View File
@@ -0,0 +1,286 @@
.admin-container.data-v-ce40c64c {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 120rpx;
}
.admin-header.data-v-ce40c64c {
display: flex;
justify-content: space-between;
align-items: center;
padding: 60rpx 30rpx 30rpx;
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
}
.admin-header .header-left .header-title.data-v-ce40c64c {
font-size: 40rpx;
font-weight: bold;
color: #fff;
display: block;
}
.admin-header .header-left .header-subtitle.data-v-ce40c64c {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
margin-top: 8rpx;
display: block;
}
.admin-header .header-right.data-v-ce40c64c {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.2);
padding: 16rpx 32rpx;
border-radius: 40rpx;
}
.admin-header .header-right .add-icon.data-v-ce40c64c {
font-size: 32rpx;
color: #fff;
margin-right: 8rpx;
}
.admin-header .header-right .add-text.data-v-ce40c64c {
font-size: 28rpx;
color: #fff;
}
.search-bar.data-v-ce40c64c {
padding: 20rpx 30rpx;
}
.search-bar .search-input-wrap.data-v-ce40c64c {
display: flex;
align-items: center;
background: #fff;
border-radius: 40rpx;
padding: 0 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.search-bar .search-input-wrap .search-icon.data-v-ce40c64c {
font-size: 28rpx;
margin-right: 20rpx;
}
.search-bar .search-input-wrap .search-input.data-v-ce40c64c {
flex: 1;
height: 80rpx;
font-size: 28rpx;
}
.category-list.data-v-ce40c64c {
padding: 0 30rpx;
}
.category-card.data-v-ce40c64c {
display: flex;
align-items: center;
background: #fff;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.category-card .category-icon-wrap.data-v-ce40c64c {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
}
.category-card .category-icon-wrap .category-icon.data-v-ce40c64c {
font-size: 36rpx;
}
.category-card .category-info.data-v-ce40c64c {
flex: 1;
}
.category-card .category-info .category-name.data-v-ce40c64c {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.category-card .category-info .category-category.data-v-ce40c64c {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
.category-card .category-price-info.data-v-ce40c64c {
text-align: right;
margin-right: 24rpx;
}
.category-card .category-price-info .price-value.data-v-ce40c64c {
font-size: 36rpx;
font-weight: bold;
color: #3366ff;
}
.category-card .category-price-info .price-unit.data-v-ce40c64c {
font-size: 24rpx;
color: #999;
}
.category-card .category-actions.data-v-ce40c64c {
display: flex;
flex-direction: column;
}
.category-card .category-actions .action-btn.data-v-ce40c64c {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10rpx;
}
.category-card .category-actions .action-btn.edit.data-v-ce40c64c {
background: #fff3e0;
}
.category-card .category-actions .action-btn.delete.data-v-ce40c64c {
background: #ffebee;
}
.empty-state.data-v-ce40c64c {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
}
.empty-state .empty-icon.data-v-ce40c64c {
font-size: 100rpx;
margin-bottom: 20rpx;
}
.empty-state .empty-text.data-v-ce40c64c {
font-size: 28rpx;
color: #999;
}
.tab-bar.data-v-ce40c64c {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
background: #fff;
padding: 20rpx 0 60rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.tab-bar .tab-item.data-v-ce40c64c {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.tab-bar .tab-item .tab-icon.data-v-ce40c64c {
font-size: 40rpx;
margin-bottom: 8rpx;
}
.tab-bar .tab-item .tab-text.data-v-ce40c64c {
font-size: 22rpx;
color: #999;
}
.tab-bar .tab-item.active .tab-text.data-v-ce40c64c {
color: #3366ff;
font-weight: bold;
}
.modal-overlay.data-v-ce40c64c {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-overlay .modal-box.data-v-ce40c64c {
width: 600rpx;
background: #fff;
border-radius: 30rpx;
overflow: hidden;
}
.modal-overlay .modal-box .modal-header.data-v-ce40c64c {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #eee;
}
.modal-overlay .modal-box .modal-header .modal-title.data-v-ce40c64c {
font-size: 34rpx;
font-weight: bold;
color: #333;
}
.modal-overlay .modal-box .modal-header .modal-close.data-v-ce40c64c {
font-size: 40rpx;
color: #999;
padding: 10rpx;
}
.modal-overlay .modal-box .modal-body.data-v-ce40c64c {
padding: 30rpx;
}
.modal-overlay .modal-box .modal-body .form-group.data-v-ce40c64c {
margin-bottom: 30rpx;
}
.modal-overlay .modal-box .modal-body .form-group .form-label.data-v-ce40c64c {
font-size: 28rpx;
color: #666;
margin-bottom: 16rpx;
display: block;
}
.modal-overlay .modal-box .modal-body .form-group .form-input.data-v-ce40c64c {
width: 100%;
height: 80rpx;
border: 2rpx solid #eee;
border-radius: 16rpx;
padding: 0 24rpx;
font-size: 28rpx;
box-sizing: border-box;
}
.modal-overlay .modal-box .modal-body .form-group .form-input.price-input.data-v-ce40c64c {
padding-left: 60rpx;
}
.modal-overlay .modal-box .modal-body .form-group .price-input-wrap.data-v-ce40c64c {
position: relative;
}
.modal-overlay .modal-box .modal-body .form-group .price-input-wrap .price-symbol.data-v-ce40c64c {
position: absolute;
left: 24rpx;
top: 50%;
transform: translateY(-50%);
font-size: 28rpx;
color: #3366ff;
font-weight: bold;
}
.modal-overlay .modal-box .modal-body .form-group .unit-options.data-v-ce40c64c {
display: flex;
}
.modal-overlay .modal-box .modal-body .form-group .unit-options .unit-option.data-v-ce40c64c {
flex: 1;
height: 80rpx;
border: 2rpx solid #eee;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
margin-right: 20rpx;
}
.modal-overlay .modal-box .modal-body .form-group .unit-options .unit-option.data-v-ce40c64c:last-child {
margin-right: 0;
}
.modal-overlay .modal-box .modal-body .form-group .unit-options .unit-option.active.data-v-ce40c64c {
border-color: #3366ff;
color: #3366ff;
background: rgba(51, 102, 255, 0.1);
}
.modal-overlay .modal-box .modal-footer.data-v-ce40c64c {
display: flex;
border-top: 1rpx solid #eee;
}
.modal-overlay .modal-box .modal-footer .modal-btn.data-v-ce40c64c {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
}
.modal-overlay .modal-box .modal-footer .modal-btn.cancel.data-v-ce40c64c {
color: #666;
border-right: 1rpx solid #eee;
}
.modal-overlay .modal-box .modal-footer .modal-btn.confirm.data-v-ce40c64c {
color: #3366ff;
font-weight: bold;
}
+121
View File
@@ -0,0 +1,121 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const stores_order = require("../../stores/order.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "statistics",
setup(__props) {
const orderStore = stores_order.useOrderStore();
const currentFilter = common_vendor.ref("today");
const timeFilters = [
{ label: "今日", value: "today" },
{ label: "本周", value: "week" },
{ label: "本月", value: "month" },
{ label: "全部", value: "all" }
];
const summaryData = common_vendor.computed(() => {
const orders = orderStore.orders;
const totalOrders = orders.length;
const totalAmount = orders.reduce((sum, order) => sum + order.amount, 0);
const totalWeight = orders.reduce((sum, order) => sum + (order.weight || 0), 0);
const avgAmount = totalOrders > 0 ? totalAmount / totalOrders : 0;
return {
totalOrders,
totalAmount,
totalWeight,
avgAmount
};
});
const categoryStats = common_vendor.computed(() => {
const categoryMap = {};
orderStore.orders.forEach((order) => {
if (!categoryMap[order.category]) {
categoryMap[order.category] = { name: order.name, amount: 0 };
}
categoryMap[order.category].amount += order.amount;
});
return Object.values(categoryMap).sort((a, b) => b.amount - a.amount).slice(0, 5);
});
const dailyStats = common_vendor.computed(() => {
const days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
return days.map((label, index) => ({
date: `2026-05-${String(index + 1).padStart(2, "0")}`,
label,
amount: Math.floor(Math.random() * 500) + 100
}));
});
const statusStats = common_vendor.computed(() => {
const stats = { pending: 0, completed: 0, cancelled: 0 };
orderStore.orders.forEach((order) => {
if (order.status in stats) {
stats[order.status]++;
}
});
return stats;
});
const getRankClass = (index) => {
if (index === 0) return "rank-1";
if (index === 1) return "rank-2";
if (index === 2) return "rank-3";
return "";
};
const getBarWidth = (amount) => {
const maxAmount = Math.max(...categoryStats.value.map((item) => item.amount), 1);
return amount / maxAmount * 100;
};
const getBarHeight = (amount) => {
const maxAmount = Math.max(...dailyStats.value.map((item) => item.amount), 1);
return amount / maxAmount * 100;
};
common_vendor.onMounted(() => {
const isLogin = common_vendor.index.getStorageSync("admin_login");
if (!isLogin) {
common_vendor.index.redirectTo({ url: "/pages/admin/login" });
return;
}
orderStore.loadOrders();
});
return (_ctx, _cache) => {
return {
a: common_vendor.f(timeFilters, (filter, k0, i0) => {
return {
a: common_vendor.t(filter.label),
b: filter.value,
c: currentFilter.value === filter.value ? 1 : "",
d: common_vendor.o(($event) => currentFilter.value = filter.value, filter.value)
};
}),
b: common_vendor.t(summaryData.value.totalOrders),
c: common_vendor.t(summaryData.value.totalAmount.toFixed(2)),
d: common_vendor.t(summaryData.value.totalWeight.toFixed(2)),
e: common_vendor.t(summaryData.value.avgAmount.toFixed(2)),
f: common_vendor.f(categoryStats.value, (item, index, i0) => {
return {
a: common_vendor.t(index + 1),
b: common_vendor.n(getRankClass(index)),
c: common_vendor.t(item.name),
d: getBarWidth(item.amount) + "%",
e: common_vendor.t(item.amount.toFixed(2)),
f: item.category
};
}),
g: common_vendor.f(5, (i, k0, i0) => {
return {
a: i
};
}),
h: common_vendor.f(dailyStats.value, (day, k0, i0) => {
return {
a: getBarHeight(day.amount) + "%",
b: common_vendor.t(day.label),
c: day.date
};
}),
i: common_vendor.t(statusStats.value.pending),
j: common_vendor.t(statusStats.value.completed),
k: common_vendor.t(statusStats.value.cancelled)
};
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-8cc66245"]]);
wx.createPage(MiniProgramPage);
+6
View File
@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "统计报表",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="admin-container data-v-8cc66245"><view class="admin-header data-v-8cc66245"><view class="header-left data-v-8cc66245"><text class="header-title data-v-8cc66245">统计报表</text><text class="header-subtitle data-v-8cc66245">数据统计与分析</text></view></view><view class="time-filter data-v-8cc66245"><view wx:for="{{a}}" wx:for-item="filter" wx:key="b" class="{{['filter-item', 'data-v-8cc66245', filter.c && 'active']}}" bindtap="{{filter.d}}">{{filter.a}}</view></view><view class="summary-cards data-v-8cc66245"><view class="summary-card data-v-8cc66245"><view class="card-icon data-v-8cc66245">📊</view><view class="card-content data-v-8cc66245"><text class="card-value data-v-8cc66245">{{b}}</text><text class="card-label data-v-8cc66245">总订单数</text></view></view><view class="summary-card data-v-8cc66245"><view class="card-icon data-v-8cc66245">💰</view><view class="card-content data-v-8cc66245"><text class="card-value data-v-8cc66245">¥{{c}}</text><text class="card-label data-v-8cc66245">总金额</text></view></view><view class="summary-card data-v-8cc66245"><view class="card-icon data-v-8cc66245">♻️</view><view class="card-content data-v-8cc66245"><text class="card-value data-v-8cc66245">{{d}}kg</text><text class="card-label data-v-8cc66245">总回收量</text></view></view><view class="summary-card data-v-8cc66245"><view class="card-icon data-v-8cc66245">📈</view><view class="card-content data-v-8cc66245"><text class="card-value data-v-8cc66245">{{e}}</text><text class="card-label data-v-8cc66245">平均单价</text></view></view></view><view class="chart-section data-v-8cc66245"><view class="section-header data-v-8cc66245"><text class="section-title data-v-8cc66245">品类回收排行</text></view><view class="chart-list data-v-8cc66245"><view wx:for="{{f}}" wx:for-item="item" wx:key="f" class="chart-item data-v-8cc66245"><view class="{{['chart-rank', 'data-v-8cc66245', item.b]}}">{{item.a}}</view><view class="chart-info data-v-8cc66245"><view class="chart-name data-v-8cc66245">{{item.c}}</view><view class="chart-bar-wrap data-v-8cc66245"><view class="chart-bar data-v-8cc66245" style="{{'width:' + item.d}}"></view></view></view><view class="chart-value data-v-8cc66245">¥{{item.e}}</view></view></view></view><view class="chart-section data-v-8cc66245"><view class="section-header data-v-8cc66245"><text class="section-title data-v-8cc66245">每日趋势</text></view><view class="line-chart data-v-8cc66245"><view class="chart-grid data-v-8cc66245"><view wx:for="{{g}}" wx:for-item="i" wx:key="a" class="grid-line data-v-8cc66245"></view></view><view class="chart-bars data-v-8cc66245"><view wx:for="{{h}}" wx:for-item="day" wx:key="c" class="bar-item data-v-8cc66245"><view class="bar data-v-8cc66245" style="{{'height:' + day.a}}"></view><text class="bar-label data-v-8cc66245">{{day.b}}</text></view></view></view></view><view class="detail-section data-v-8cc66245"><view class="section-header data-v-8cc66245"><text class="section-title data-v-8cc66245">订单状态分布</text></view><view class="status-stats data-v-8cc66245"><view class="status-item data-v-8cc66245"><view class="status-circle pending data-v-8cc66245"><text class="status-value data-v-8cc66245">{{i}}</text></view><text class="status-label data-v-8cc66245">待处理</text></view><view class="status-item data-v-8cc66245"><view class="status-circle completed data-v-8cc66245"><text class="status-value data-v-8cc66245">{{j}}</text></view><text class="status-label data-v-8cc66245">已完成</text></view><view class="status-item data-v-8cc66245"><view class="status-circle cancelled data-v-8cc66245"><text class="status-value data-v-8cc66245">{{k}}</text></view><text class="status-label data-v-8cc66245">已取消</text></view></view></view></view>
+231
View File
@@ -0,0 +1,231 @@
.admin-container.data-v-8cc66245 {
min-height: 100vh;
background: #f5f7fa;
padding-bottom: 32rpx;
}
.admin-header.data-v-8cc66245 {
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
padding: 48rpx 32rpx;
}
.header-left.data-v-8cc66245 {
color: #fff;
}
.header-title.data-v-8cc66245 {
font-size: 40rpx;
font-weight: 700;
display: block;
}
.header-subtitle.data-v-8cc66245 {
font-size: 24rpx;
opacity: 0.8;
margin-top: 4rpx;
}
.time-filter.data-v-8cc66245 {
display: flex;
gap: 16rpx;
padding: 24rpx 32rpx;
background: #fff;
}
.filter-item.data-v-8cc66245 {
padding: 12rpx 28rpx;
background: #f5f5f5;
border-radius: 24rpx;
font-size: 26rpx;
color: #666;
}
.filter-item.active.data-v-8cc66245 {
background: #3366ff;
color: #fff;
}
.summary-cards.data-v-8cc66245 {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 16rpx;
padding: 32rpx;
}
.summary-card.data-v-8cc66245 {
background: #fff;
border-radius: 12rpx;
padding: 20rpx 16rpx;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.card-icon.data-v-8cc66245 {
font-size: 40rpx;
margin-bottom: 12rpx;
}
.card-content.data-v-8cc66245 {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.card-value.data-v-8cc66245 {
font-size: 28rpx;
font-weight: 700;
color: #3366ff;
}
.card-label.data-v-8cc66245 {
font-size: 20rpx;
color: #999;
margin-top: 4rpx;
}
.chart-section.data-v-8cc66245, .detail-section.data-v-8cc66245 {
margin: 0 32rpx 32rpx;
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.section-header.data-v-8cc66245 {
margin-bottom: 24rpx;
}
.section-title.data-v-8cc66245 {
font-size: 30rpx;
font-weight: 600;
color: #333;
}
.chart-list.data-v-8cc66245 {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.chart-item.data-v-8cc66245 {
display: flex;
align-items: center;
}
.chart-rank.data-v-8cc66245 {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
background: #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
font-size: 24rpx;
font-weight: 600;
color: #666;
margin-right: 16rpx;
}
.chart-rank.rank-1.data-v-8cc66245 {
background: #ffd700;
color: #fff;
}
.chart-rank.rank-2.data-v-8cc66245 {
background: #c0c0c0;
color: #fff;
}
.chart-rank.rank-3.data-v-8cc66245 {
background: #cd7f32;
color: #fff;
}
.chart-info.data-v-8cc66245 {
flex: 1;
}
.chart-name.data-v-8cc66245 {
font-size: 26rpx;
color: #333;
margin-bottom: 8rpx;
}
.chart-bar-wrap.data-v-8cc66245 {
height: 12rpx;
background: #f0f0f0;
border-radius: 6rpx;
overflow: hidden;
}
.chart-bar.data-v-8cc66245 {
height: 100%;
background: linear-gradient(90deg, #3366ff 0%, #254edb 100%);
border-radius: 6rpx;
transition: width 0.5s ease;
}
.chart-value.data-v-8cc66245 {
font-size: 26rpx;
font-weight: 600;
color: #3366ff;
margin-left: 16rpx;
}
.line-chart.data-v-8cc66245 {
position: relative;
height: 300rpx;
}
.chart-grid.data-v-8cc66245 {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 40rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.grid-line.data-v-8cc66245 {
height: 1rpx;
background: #f0f0f0;
}
.chart-bars.data-v-8cc66245 {
position: absolute;
bottom: 40rpx;
left: 0;
right: 0;
display: flex;
justify-content: space-around;
align-items: flex-end;
height: calc(100% - 40rpx);
}
.bar-item.data-v-8cc66245 {
display: flex;
flex-direction: column;
align-items: center;
width: 10%;
}
.bar.data-v-8cc66245 {
width: 80%;
background: linear-gradient(180deg, #3366ff 0%, #254edb 100%);
border-radius: 4rpx 4rpx 0 0;
min-height: 4rpx;
transition: height 0.5s ease;
}
.bar-label.data-v-8cc66245 {
font-size: 20rpx;
color: #999;
margin-top: 8rpx;
}
.status-stats.data-v-8cc66245 {
display: flex;
justify-content: space-around;
}
.status-item.data-v-8cc66245 {
display: flex;
flex-direction: column;
align-items: center;
}
.status-circle.data-v-8cc66245 {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 12rpx;
}
.status-circle.pending.data-v-8cc66245 {
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
}
.status-circle.completed.data-v-8cc66245 {
background: linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%);
}
.status-circle.cancelled.data-v-8cc66245 {
background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
}
.status-value.data-v-8cc66245 {
font-size: 40rpx;
font-weight: 700;
color: #333;
}
.status-label.data-v-8cc66245 {
font-size: 24rpx;
color: #666;
}
+135
View File
@@ -0,0 +1,135 @@
"use strict";
const common_vendor = require("../../../common/vendor.js");
const stores_user = require("../../../stores/user.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "list",
setup(__props) {
const userStore = stores_user.useUserStore();
const searchKeyword = common_vendor.ref("");
const showAddModal = common_vendor.ref(false);
const editingUser = common_vendor.ref(null);
const formData = common_vendor.reactive({
name: "",
phone: "",
role: "collector"
});
const filteredUsers = common_vendor.computed(() => {
let users = userStore.users;
if (searchKeyword.value) {
const keyword = searchKeyword.value.toLowerCase();
users = users.filter(
(item) => item.name.toLowerCase().includes(keyword) || item.phone.includes(keyword)
);
}
return users;
});
const editUser = (user) => {
editingUser.value = user;
formData.name = user.name;
formData.phone = user.phone;
formData.role = user.role;
showAddModal.value = true;
};
const deleteUser = (id) => {
common_vendor.index.showModal({
title: "确认删除",
content: "确定要删除此用户吗?",
success: (res) => {
if (res.confirm) {
userStore.deleteUser(id);
common_vendor.index.showToast({ title: "删除成功", icon: "success" });
}
}
});
};
const closeModal = () => {
showAddModal.value = false;
editingUser.value = null;
formData.name = "";
formData.phone = "";
formData.role = "collector";
};
const saveUser = async () => {
if (!formData.name) {
common_vendor.index.showToast({ title: "请输入用户名", icon: "none" });
return;
}
if (!formData.phone || formData.phone.length !== 11) {
common_vendor.index.showToast({ title: "请输入正确的手机号", icon: "none" });
return;
}
if (editingUser.value) {
await userStore.updateUser({
id: editingUser.value.id,
name: formData.name,
phone: formData.phone,
role: formData.role
});
common_vendor.index.showToast({ title: "修改成功", icon: "success" });
} else {
await userStore.addUser({
name: formData.name,
phone: formData.phone,
role: formData.role
});
common_vendor.index.showToast({ title: "新增成功", icon: "success" });
}
closeModal();
};
const goToHome = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/index" });
};
const goToOrderList = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/order/list" });
};
const goToPriceManager = () => {
common_vendor.index.redirectTo({ url: "/pages/admin/price/list" });
};
common_vendor.onMounted(() => {
userStore.loadUsers();
});
return (_ctx, _cache) => {
return common_vendor.e({
a: common_vendor.o(($event) => showAddModal.value = true),
b: searchKeyword.value,
c: common_vendor.o(($event) => searchKeyword.value = $event.detail.value),
d: common_vendor.f(filteredUsers.value, (user, k0, i0) => {
return {
a: common_vendor.t(user.name.charAt(0)),
b: common_vendor.t(user.name),
c: common_vendor.t(user.phone),
d: common_vendor.t(user.role === "admin" ? "管理员" : "回收员"),
e: common_vendor.n(user.role),
f: common_vendor.o(($event) => editUser(user), user.id),
g: common_vendor.o(($event) => deleteUser(user.id), user.id),
h: user.id
};
}),
e: filteredUsers.value.length === 0
}, filteredUsers.value.length === 0 ? {} : {}, {
f: common_vendor.o(goToHome),
g: common_vendor.o(goToOrderList),
h: common_vendor.o(goToPriceManager),
i: showAddModal.value
}, showAddModal.value ? {
j: common_vendor.t(editingUser.value ? "编辑用户" : "新增用户"),
k: common_vendor.o(closeModal),
l: formData.name,
m: common_vendor.o(($event) => formData.name = $event.detail.value),
n: formData.phone,
o: common_vendor.o(($event) => formData.phone = $event.detail.value),
p: formData.role === "admin" ? 1 : "",
q: common_vendor.o(($event) => formData.role = "admin"),
r: formData.role === "collector" ? 1 : "",
s: common_vendor.o(($event) => formData.role = "collector"),
t: common_vendor.o(closeModal),
v: common_vendor.o(saveUser),
w: common_vendor.o(() => {
}),
x: common_vendor.o(closeModal)
} : {});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-709108fb"]]);
wx.createPage(MiniProgramPage);
+5
View File
@@ -0,0 +1,5 @@
{
"navigationStyle": "custom",
"navigationBarTitleText": "用户管理",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="admin-container data-v-709108fb"><view class="admin-header data-v-709108fb"><view class="header-left data-v-709108fb"><text class="header-title data-v-709108fb">用户管理</text><text class="header-subtitle data-v-709108fb">系统用户列表</text></view><view class="header-right data-v-709108fb" bindtap="{{a}}"><text class="add-icon data-v-709108fb">+</text><text class="add-text data-v-709108fb">新增</text></view></view><view class="search-bar data-v-709108fb"><view class="search-input-wrap data-v-709108fb"><text class="search-icon data-v-709108fb">🔍</text><input type="text" class="search-input data-v-709108fb" placeholder="搜索用户名或手机号" value="{{b}}" bindinput="{{c}}"/></view></view><view class="user-list data-v-709108fb"><view wx:for="{{d}}" wx:for-item="user" wx:key="h" class="user-card data-v-709108fb"><view class="user-avatar data-v-709108fb"><text class="avatar-icon data-v-709108fb">{{user.a}}</text></view><view class="user-info data-v-709108fb"><view class="user-name data-v-709108fb">{{user.b}}</view><view class="user-phone data-v-709108fb">{{user.c}}</view></view><view class="user-role data-v-709108fb"><text class="{{['role-tag', 'data-v-709108fb', user.e]}}">{{user.d}}</text></view><view class="user-actions data-v-709108fb"><view class="action-btn edit data-v-709108fb" bindtap="{{user.f}}">✏️</view><view class="action-btn delete data-v-709108fb" bindtap="{{user.g}}">🗑️</view></view></view></view><view wx:if="{{e}}" class="empty-state data-v-709108fb"><text class="empty-icon data-v-709108fb">👥</text><text class="empty-text data-v-709108fb">暂无用户</text></view><view class="tab-bar data-v-709108fb"><view class="tab-item data-v-709108fb" bindtap="{{f}}"><text class="tab-icon data-v-709108fb">🏠</text><text class="tab-text data-v-709108fb">首页</text></view><view class="tab-item data-v-709108fb" bindtap="{{g}}"><text class="tab-icon data-v-709108fb">📋</text><text class="tab-text data-v-709108fb">订单</text></view><view class="tab-item data-v-709108fb" bindtap="{{h}}"><text class="tab-icon data-v-709108fb">💰</text><text class="tab-text data-v-709108fb">价格</text></view><view class="tab-item active data-v-709108fb"><text class="tab-icon data-v-709108fb">👥</text><text class="tab-text data-v-709108fb">用户</text></view></view><view wx:if="{{i}}" class="modal-overlay data-v-709108fb" bindtap="{{x}}"><view class="modal-box data-v-709108fb" catchtap="{{w}}"><view class="modal-header data-v-709108fb"><text class="modal-title data-v-709108fb">{{j}}</text><view class="modal-close data-v-709108fb" bindtap="{{k}}">×</view></view><view class="modal-body data-v-709108fb"><view class="form-group data-v-709108fb"><text class="form-label data-v-709108fb">用户名</text><input type="text" class="form-input data-v-709108fb" placeholder="请输入用户名" value="{{l}}" bindinput="{{m}}"/></view><view class="form-group data-v-709108fb"><text class="form-label data-v-709108fb">手机号</text><input type="number" class="form-input data-v-709108fb" placeholder="请输入手机号" value="{{n}}" bindinput="{{o}}"/></view><view class="form-group data-v-709108fb"><text class="form-label data-v-709108fb">角色</text><view class="role-options data-v-709108fb"><view class="{{['role-option', 'data-v-709108fb', p && 'active']}}" bindtap="{{q}}">管理员</view><view class="{{['role-option', 'data-v-709108fb', r && 'active']}}" bindtap="{{s}}">回收员</view></view></view></view><view class="modal-footer data-v-709108fb"><view class="modal-btn cancel data-v-709108fb" bindtap="{{t}}">取消</view><view class="modal-btn confirm data-v-709108fb" bindtap="{{v}}">保存</view></view></view></view></view>
+275
View File
@@ -0,0 +1,275 @@
.admin-container.data-v-709108fb {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 120rpx;
}
.admin-header.data-v-709108fb {
display: flex;
justify-content: space-between;
align-items: center;
padding: 60rpx 30rpx 30rpx;
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
}
.admin-header .header-left .header-title.data-v-709108fb {
font-size: 40rpx;
font-weight: bold;
color: #fff;
display: block;
}
.admin-header .header-left .header-subtitle.data-v-709108fb {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
margin-top: 8rpx;
display: block;
}
.admin-header .header-right.data-v-709108fb {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.2);
padding: 16rpx 32rpx;
border-radius: 40rpx;
}
.admin-header .header-right .add-icon.data-v-709108fb {
font-size: 32rpx;
color: #fff;
margin-right: 8rpx;
}
.admin-header .header-right .add-text.data-v-709108fb {
font-size: 28rpx;
color: #fff;
}
.search-bar.data-v-709108fb {
padding: 20rpx 30rpx;
}
.search-bar .search-input-wrap.data-v-709108fb {
display: flex;
align-items: center;
background: #fff;
border-radius: 40rpx;
padding: 0 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.search-bar .search-input-wrap .search-icon.data-v-709108fb {
font-size: 28rpx;
margin-right: 20rpx;
}
.search-bar .search-input-wrap .search-input.data-v-709108fb {
flex: 1;
height: 80rpx;
font-size: 28rpx;
}
.user-list.data-v-709108fb {
padding: 0 30rpx;
}
.user-card.data-v-709108fb {
display: flex;
align-items: center;
background: #fff;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.user-card .user-avatar.data-v-709108fb {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
}
.user-card .user-avatar .avatar-icon.data-v-709108fb {
font-size: 32rpx;
color: #fff;
font-weight: bold;
}
.user-card .user-info.data-v-709108fb {
flex: 1;
}
.user-card .user-info .user-name.data-v-709108fb {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.user-card .user-info .user-phone.data-v-709108fb {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
.user-card .user-role.data-v-709108fb {
margin-right: 24rpx;
}
.user-card .user-role .role-tag.data-v-709108fb {
font-size: 22rpx;
padding: 8rpx 20rpx;
border-radius: 20rpx;
}
.user-card .user-role .role-tag.admin.data-v-709108fb {
background: #ffebee;
color: #e53935;
}
.user-card .user-role .role-tag.collector.data-v-709108fb {
background: #e3f2fd;
color: #1976d2;
}
.user-card .user-actions.data-v-709108fb {
display: flex;
}
.user-card .user-actions .action-btn.data-v-709108fb {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-left: 10rpx;
}
.user-card .user-actions .action-btn.edit.data-v-709108fb {
background: #fff3e0;
}
.user-card .user-actions .action-btn.delete.data-v-709108fb {
background: #ffebee;
}
.empty-state.data-v-709108fb {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
}
.empty-state .empty-icon.data-v-709108fb {
font-size: 100rpx;
margin-bottom: 20rpx;
}
.empty-state .empty-text.data-v-709108fb {
font-size: 28rpx;
color: #999;
}
.tab-bar.data-v-709108fb {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
background: #fff;
padding: 20rpx 0 60rpx;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.tab-bar .tab-item.data-v-709108fb {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.tab-bar .tab-item .tab-icon.data-v-709108fb {
font-size: 40rpx;
margin-bottom: 8rpx;
}
.tab-bar .tab-item .tab-text.data-v-709108fb {
font-size: 22rpx;
color: #999;
}
.tab-bar .tab-item.active .tab-text.data-v-709108fb {
color: #3366ff;
font-weight: bold;
}
.modal-overlay.data-v-709108fb {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-overlay .modal-box.data-v-709108fb {
width: 600rpx;
background: #fff;
border-radius: 30rpx;
overflow: hidden;
}
.modal-overlay .modal-box .modal-header.data-v-709108fb {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #eee;
}
.modal-overlay .modal-box .modal-header .modal-title.data-v-709108fb {
font-size: 34rpx;
font-weight: bold;
color: #333;
}
.modal-overlay .modal-box .modal-header .modal-close.data-v-709108fb {
font-size: 40rpx;
color: #999;
padding: 10rpx;
}
.modal-overlay .modal-box .modal-body.data-v-709108fb {
padding: 30rpx;
}
.modal-overlay .modal-box .modal-body .form-group.data-v-709108fb {
margin-bottom: 30rpx;
}
.modal-overlay .modal-box .modal-body .form-group .form-label.data-v-709108fb {
font-size: 28rpx;
color: #666;
margin-bottom: 16rpx;
display: block;
}
.modal-overlay .modal-box .modal-body .form-group .form-input.data-v-709108fb {
width: 100%;
height: 80rpx;
border: 2rpx solid #eee;
border-radius: 16rpx;
padding: 0 24rpx;
font-size: 28rpx;
box-sizing: border-box;
}
.modal-overlay .modal-box .modal-body .form-group .role-options.data-v-709108fb {
display: flex;
}
.modal-overlay .modal-box .modal-body .form-group .role-options .role-option.data-v-709108fb {
flex: 1;
height: 80rpx;
border: 2rpx solid #eee;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
margin-right: 20rpx;
}
.modal-overlay .modal-box .modal-body .form-group .role-options .role-option.data-v-709108fb:last-child {
margin-right: 0;
}
.modal-overlay .modal-box .modal-body .form-group .role-options .role-option.active.data-v-709108fb {
border-color: #3366ff;
color: #3366ff;
background: rgba(51, 102, 255, 0.1);
}
.modal-overlay .modal-box .modal-footer.data-v-709108fb {
display: flex;
border-top: 1rpx solid #eee;
}
.modal-overlay .modal-box .modal-footer .modal-btn.data-v-709108fb {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
}
.modal-overlay .modal-box .modal-footer .modal-btn.cancel.data-v-709108fb {
color: #666;
border-right: 1rpx solid #eee;
}
.modal-overlay .modal-box .modal-footer .modal-btn.confirm.data-v-709108fb {
color: #3366ff;
font-weight: bold;
}