Initial commit

This commit is contained in:
jiapengyu
2026-07-27 13:37:48 +08:00
commit ecba71e2a5
39123 changed files with 5989154 additions and 0 deletions
+327
View File
@@ -0,0 +1,327 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const BASE_URL = "http://192.168.123.111:3000/api";
const mockPrices = [
{ category: "001", name: "纸类", unit: "kg", price: 1.2 },
{ category: "002", name: "金属", unit: "kg", price: 2.5 },
{ category: "003", name: "易拉罐", unit: "piece", price: 0.1 },
{ category: "004", name: "塑料", unit: "kg", price: 3 },
{ category: "005", name: "织物", unit: "kg", price: 0.8 },
{ category: "006", name: "塑料瓶", unit: "piece", price: 0.05 }
];
const mockUsers = [
{ id: "1", name: "管理员", phone: "13800138000", role: "admin", createTime: "2024-01-01" },
{ id: "2", name: "回收员小王", phone: "18698102228", role: "collector", createTime: "2024-01-15" }
];
const request = async (url, options = {}) => {
return new Promise((resolve, reject) => {
common_vendor.index.request({
url: BASE_URL + url,
method: options.method || "GET",
data: options.data,
header: {
"Content-Type": "application/json",
...options.header
},
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data);
} else {
reject(new Error("请求失败"));
}
},
fail: (err) => {
console.error("API request failed, using mock data:", err);
reject(err);
}
});
});
};
const priceApi = {
async getPrices() {
try {
return await request("/prices");
} catch {
return {
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
prices: mockPrices
};
}
},
async addPrice(item) {
try {
const result = await request("/prices", {
method: "POST",
data: item
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_prices") || { date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], prices: mockPrices };
cached.prices.push(item);
common_vendor.index.setStorageSync("api_prices", cached);
return true;
}
},
async updatePrice(item, originalCategory) {
try {
const category = originalCategory || item.category;
const result = await request(`/prices/${category}`, {
method: "PUT",
data: item
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_prices") || { date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], prices: mockPrices };
const searchCategory = originalCategory || item.category;
const index = cached.prices.findIndex((p) => p.category === searchCategory);
if (index > -1) {
cached.prices[index] = item;
common_vendor.index.setStorageSync("api_prices", cached);
}
return true;
}
},
async deletePrice(category) {
try {
const result = await request(`/prices/${category}`, {
method: "DELETE"
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_prices") || { date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0], prices: mockPrices };
cached.prices = cached.prices.filter((p) => p.category !== category);
common_vendor.index.setStorageSync("api_prices", cached);
return true;
}
}
};
const orderApi = {
async getOrders() {
try {
const result = await request("/orders");
return result.data || [];
} catch {
const cached = common_vendor.index.getStorageSync("api_orders");
return cached || [];
}
},
async addOrder(order) {
try {
const result = await request("/orders", {
method: "POST",
data: order
});
return result.order || null;
} catch {
const cached = common_vendor.index.getStorageSync("api_orders") || [];
const newOrder = { ...order, id: Date.now().toString(), createTime: (/* @__PURE__ */ new Date()).toISOString() };
cached.unshift(newOrder);
common_vendor.index.setStorageSync("api_orders", cached);
return newOrder;
}
},
async updateOrder(order) {
try {
const result = await request(`/orders/${order.id}`, {
method: "PUT",
data: order
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_orders") || [];
const index = cached.findIndex((o) => o.id === order.id);
if (index > -1) {
cached[index] = order;
common_vendor.index.setStorageSync("api_orders", cached);
}
return true;
}
},
async deleteOrder(id) {
try {
const result = await request(`/orders/${id}`, {
method: "DELETE"
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_orders") || [];
const filtered = cached.filter((o) => o.id !== id);
common_vendor.index.setStorageSync("api_orders", filtered);
return true;
}
}
};
const userApi = {
async getUsers() {
try {
const result = await request("/users");
return result.data || [];
} catch {
const cached = common_vendor.index.getStorageSync("api_users");
return cached || mockUsers;
}
},
async addUser(user) {
try {
const result = await request("/users", {
method: "POST",
data: user
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_users") || mockUsers;
const newUser = {
...user,
id: Date.now().toString(),
createTime: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
};
cached.push(newUser);
common_vendor.index.setStorageSync("api_users", cached);
return true;
}
},
async updateUser(user) {
try {
const result = await request(`/users/${user.id}`, {
method: "PUT",
data: user
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_users") || mockUsers;
const index = cached.findIndex((u) => u.id === user.id);
if (index > -1) {
cached[index] = user;
common_vendor.index.setStorageSync("api_users", cached);
}
return true;
}
},
async deleteUser(id) {
try {
const result = await request(`/users/${id}`, {
method: "DELETE"
});
return result.success;
} catch {
const cached = common_vendor.index.getStorageSync("api_users") || mockUsers;
const filtered = cached.filter((u) => u.id !== id);
common_vendor.index.setStorageSync("api_users", filtered);
return true;
}
}
};
const regionApi = {
async getCities() {
var _a;
try {
const result = await request("/regions/cities");
return ((_a = result.data) == null ? void 0 : _a.map((c) => c.name)) || [];
} catch {
return ["天津市", "北京市", "上海市", "广州市"];
}
},
async getDistricts(city) {
var _a;
try {
const result = await request("/regions/districts");
return ((_a = result.data) == null ? void 0 : _a.filter((d) => d.cityName === city).map((d) => d.name)) || [];
} catch {
const districtMap = {
"天津市": ["高新区", "西青区", "保税区"],
"北京市": ["东城区", "西城区", "朝阳区", "海淀区", "丰台区"],
"上海市": ["黄浦区", "徐汇区", "浦东新区", "静安区", "长宁区"],
"广州市": ["天河区", "海珠区", "越秀区", "白云区", "荔湾区"]
};
return districtMap[city] || [];
}
},
async getStations(city, district) {
var _a, _b;
try {
const result = await request("/regions/stations");
return ((_a = result.data) == null ? void 0 : _a.filter((s) => s.cityName === city && s.districtName === district).map((s) => s.name)) || [];
} catch {
const stationMap = {
"天津市": {
"高新区": ["金融街融汇景苑", "金辉江山铭筑"],
"西青区": ["华兴里", "华兴南里"],
"保税区": ["意境兰庭"]
},
"北京市": {
"东城区": ["景山街道", "交道口街道", "东四街道", "朝阳门街道", "建国门街道"],
"西城区": ["西长安街街道", "新街口街道", "月坛街道", "展览路街道", "德胜街道"],
"朝阳区": ["朝外街道", "劲松街道", "呼家楼街道", "三里屯街道", "团结湖街道"],
"海淀区": ["海淀街道", "中关村街道", "学院路街道", "西三旗街道", "清河街道"]
},
"上海市": {
"黄浦区": ["南京东路街道", "外滩街道", "瑞金二路街道", "淮海中路街道", "豫园街道"],
"徐汇区": ["天平路街道", "湖南路街道", "斜土路街道", "枫林路街道", "长桥街道"],
"浦东新区": ["陆家嘴街道", "潍坊新村街道", "塘桥街道", "南码头路街道", "周家渡街道"]
},
"广州市": {
"天河区": ["五山街道", "员村街道", "车陂街道", "沙河街道", "石牌街道"],
"海珠区": ["赤岗街道", "新港街道", "昌岗街道", "江南中街道", "滨江街道"],
"越秀区": ["洪桥街道", "北京街道", "六榕街道", "流花街道", "光塔街道"]
}
};
return ((_b = stationMap[city]) == null ? void 0 : _b[district]) || [];
}
},
async getSiteUsers(stationName) {
var _a;
try {
const result = await request("/regions/site-users");
return ((_a = result.data) == null ? void 0 : _a.filter((u) => u.stationName === stationName).map((u) => u.name)) || [];
} catch {
return [];
}
},
async getCommunities(city, district) {
var _a;
try {
const result = await request(`/regions/communities?city=${encodeURIComponent(city)}&district=${encodeURIComponent(district)}`);
return result.data || [];
} catch {
const communityMap = {
"天津市": {
"高新区": ["金融街融汇景苑", "金辉江山铭筑"],
"西青区": ["华兴里", "华兴南里"],
"保税区": ["意境兰庭"]
},
"北京市": {
"东城区": ["景山街道", "交道口街道", "东四街道", "朝阳门街道", "建国门街道"],
"西城区": ["西长安街街道", "新街口街道", "月坛街道", "展览路街道", "德胜街道"],
"朝阳区": ["朝外街道", "劲松街道", "呼家楼街道", "三里屯街道", "团结湖街道"],
"海淀区": ["海淀街道", "中关村街道", "学院路街道", "西三旗街道", "清河街道"]
},
"上海市": {
"黄浦区": ["南京东路街道", "外滩街道", "瑞金二路街道", "淮海中路街道", "豫园街道"],
"徐汇区": ["天平路街道", "湖南路街道", "斜土路街道", "枫林路街道", "长桥街道"],
"浦东新区": ["陆家嘴街道", "潍坊新村街道", "塘桥街道", "南码头路街道", "周家渡街道"]
},
"广州市": {
"天河区": ["五山街道", "员村街道", "车陂街道", "沙河街道", "石牌街道"],
"海珠区": ["赤岗街道", "新港街道", "昌岗街道", "江南中街道", "滨江街道"],
"越秀区": ["洪桥街道", "北京街道", "六榕街道", "流花街道", "光塔街道"]
}
};
return ((_a = communityMap[city]) == null ? void 0 : _a[district]) || [];
}
},
async addRegion(city, district, community) {
try {
const result = await request("/regions", {
method: "POST",
data: { city, district, community }
});
return result.success;
} catch {
return true;
}
}
};
exports.orderApi = orderApi;
exports.priceApi = priceApi;
exports.regionApi = regionApi;
exports.userApi = userApi;
+46
View File
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const common_vendor = require("./common/vendor.js");
if (!Math) {
"./pages/user/login.js";
"./pages/index/index.js";
"./pages/price/price.js";
"./pages/weigh/weigh.js";
"./pages/bluetooth/bluetooth.js";
"./pages/order/list.js";
"./pages/order/detail.js";
"./pages/user/profile.js";
"./pages/admin/login.js";
"./pages/admin/index.js";
"./pages/admin/order/list.js";
"./pages/admin/price/list.js";
"./pages/admin/user/list.js";
"./pages/admin/statistics.js";
}
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "App",
setup(__props) {
common_vendor.onLaunch(() => {
console.log("App Launch");
});
common_vendor.onShow(() => {
console.log("App Show");
});
common_vendor.onHide(() => {
console.log("App Hide");
});
return () => {
};
}
});
function createApp() {
const app = common_vendor.createSSRApp(_sfc_main);
const pinia = common_vendor.createPinia();
app.use(pinia);
return {
app,
pinia
};
}
createApp().app.mount("#app");
exports.createApp = createApp;
+45
View File
@@ -0,0 +1,45 @@
{
"pages": [
"pages/user/login",
"pages/index/index",
"pages/price/price",
"pages/weigh/weigh",
"pages/bluetooth/bluetooth",
"pages/order/list",
"pages/order/detail",
"pages/user/profile",
"pages/admin/login",
"pages/admin/index",
"pages/admin/order/list",
"pages/admin/price/list",
"pages/admin/user/list",
"pages/admin/statistics"
],
"window": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "易分宝现场回收",
"navigationBarBackgroundColor": "#3366ff",
"backgroundColor": "#f5f5f5"
},
"tabBar": {
"color": "#999999",
"selectedColor": "#3366ff",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/icons/home.png",
"selectedIconPath": "static/icons/home-active.png"
},
{
"pagePath": "pages/order/list",
"text": "订单",
"iconPath": "static/icons/order.png",
"selectedIconPath": "static/icons/order-active.png"
}
]
},
"usingComponents": {}
}
+534
View File
@@ -0,0 +1,534 @@
.uniui-cart-filled:before {
content: "\e6d0";
}
.uniui-gift-filled:before {
content: "\e6c4";
}
.uniui-color:before {
content: "\e6cf";
}
.uniui-wallet:before {
content: "\e6b1";
}
.uniui-settings-filled:before {
content: "\e6ce";
}
.uniui-auth-filled:before {
content: "\e6cc";
}
.uniui-shop-filled:before {
content: "\e6cd";
}
.uniui-staff-filled:before {
content: "\e6cb";
}
.uniui-vip-filled:before {
content: "\e6c6";
}
.uniui-plus-filled:before {
content: "\e6c7";
}
.uniui-folder-add-filled:before {
content: "\e6c8";
}
.uniui-color-filled:before {
content: "\e6c9";
}
.uniui-tune-filled:before {
content: "\e6ca";
}
.uniui-calendar-filled:before {
content: "\e6c0";
}
.uniui-notification-filled:before {
content: "\e6c1";
}
.uniui-wallet-filled:before {
content: "\e6c2";
}
.uniui-medal-filled:before {
content: "\e6c3";
}
.uniui-fire-filled:before {
content: "\e6c5";
}
.uniui-refreshempty:before {
content: "\e6bf";
}
.uniui-location-filled:before {
content: "\e6af";
}
.uniui-person-filled:before {
content: "\e69d";
}
.uniui-personadd-filled:before {
content: "\e698";
}
.uniui-arrowthinleft:before {
content: "\e6d2";
}
.uniui-arrowthinup:before {
content: "\e6d3";
}
.uniui-arrowthindown:before {
content: "\e6d4";
}
.uniui-back:before {
content: "\e6b9";
}
.uniui-forward:before {
content: "\e6ba";
}
.uniui-arrow-right:before {
content: "\e6bb";
}
.uniui-arrow-left:before {
content: "\e6bc";
}
.uniui-arrow-up:before {
content: "\e6bd";
}
.uniui-arrow-down:before {
content: "\e6be";
}
.uniui-arrowthinright:before {
content: "\e6d1";
}
.uniui-down:before {
content: "\e6b8";
}
.uniui-bottom:before {
content: "\e6b8";
}
.uniui-arrowright:before {
content: "\e6d5";
}
.uniui-right:before {
content: "\e6b5";
}
.uniui-up:before {
content: "\e6b6";
}
.uniui-top:before {
content: "\e6b6";
}
.uniui-left:before {
content: "\e6b7";
}
.uniui-arrowup:before {
content: "\e6d6";
}
.uniui-eye:before {
content: "\e651";
}
.uniui-eye-filled:before {
content: "\e66a";
}
.uniui-eye-slash:before {
content: "\e6b3";
}
.uniui-eye-slash-filled:before {
content: "\e6b4";
}
.uniui-info-filled:before {
content: "\e649";
}
.uniui-reload:before {
content: "\e6b2";
}
.uniui-micoff-filled:before {
content: "\e6b0";
}
.uniui-map-pin-ellipse:before {
content: "\e6ac";
}
.uniui-map-pin:before {
content: "\e6ad";
}
.uniui-location:before {
content: "\e6ae";
}
.uniui-starhalf:before {
content: "\e683";
}
.uniui-star:before {
content: "\e688";
}
.uniui-star-filled:before {
content: "\e68f";
}
.uniui-calendar:before {
content: "\e6a0";
}
.uniui-fire:before {
content: "\e6a1";
}
.uniui-medal:before {
content: "\e6a2";
}
.uniui-font:before {
content: "\e6a3";
}
.uniui-gift:before {
content: "\e6a4";
}
.uniui-link:before {
content: "\e6a5";
}
.uniui-notification:before {
content: "\e6a6";
}
.uniui-staff:before {
content: "\e6a7";
}
.uniui-vip:before {
content: "\e6a8";
}
.uniui-folder-add:before {
content: "\e6a9";
}
.uniui-tune:before {
content: "\e6aa";
}
.uniui-auth:before {
content: "\e6ab";
}
.uniui-person:before {
content: "\e699";
}
.uniui-email-filled:before {
content: "\e69a";
}
.uniui-phone-filled:before {
content: "\e69b";
}
.uniui-phone:before {
content: "\e69c";
}
.uniui-email:before {
content: "\e69e";
}
.uniui-personadd:before {
content: "\e69f";
}
.uniui-chatboxes-filled:before {
content: "\e692";
}
.uniui-contact:before {
content: "\e693";
}
.uniui-chatbubble-filled:before {
content: "\e694";
}
.uniui-contact-filled:before {
content: "\e695";
}
.uniui-chatboxes:before {
content: "\e696";
}
.uniui-chatbubble:before {
content: "\e697";
}
.uniui-upload-filled:before {
content: "\e68e";
}
.uniui-upload:before {
content: "\e690";
}
.uniui-weixin:before {
content: "\e691";
}
.uniui-compose:before {
content: "\e67f";
}
.uniui-qq:before {
content: "\e680";
}
.uniui-download-filled:before {
content: "\e681";
}
.uniui-pyq:before {
content: "\e682";
}
.uniui-sound:before {
content: "\e684";
}
.uniui-trash-filled:before {
content: "\e685";
}
.uniui-sound-filled:before {
content: "\e686";
}
.uniui-trash:before {
content: "\e687";
}
.uniui-videocam-filled:before {
content: "\e689";
}
.uniui-spinner-cycle:before {
content: "\e68a";
}
.uniui-weibo:before {
content: "\e68b";
}
.uniui-videocam:before {
content: "\e68c";
}
.uniui-download:before {
content: "\e68d";
}
.uniui-help:before {
content: "\e679";
}
.uniui-navigate-filled:before {
content: "\e67a";
}
.uniui-plusempty:before {
content: "\e67b";
}
.uniui-smallcircle:before {
content: "\e67c";
}
.uniui-minus-filled:before {
content: "\e67d";
}
.uniui-micoff:before {
content: "\e67e";
}
.uniui-closeempty:before {
content: "\e66c";
}
.uniui-clear:before {
content: "\e66d";
}
.uniui-navigate:before {
content: "\e66e";
}
.uniui-minus:before {
content: "\e66f";
}
.uniui-image:before {
content: "\e670";
}
.uniui-mic:before {
content: "\e671";
}
.uniui-paperplane:before {
content: "\e672";
}
.uniui-close:before {
content: "\e673";
}
.uniui-help-filled:before {
content: "\e674";
}
.uniui-paperplane-filled:before {
content: "\e675";
}
.uniui-plus:before {
content: "\e676";
}
.uniui-mic-filled:before {
content: "\e677";
}
.uniui-image-filled:before {
content: "\e678";
}
.uniui-locked-filled:before {
content: "\e668";
}
.uniui-info:before {
content: "\e669";
}
.uniui-locked:before {
content: "\e66b";
}
.uniui-camera-filled:before {
content: "\e658";
}
.uniui-chat-filled:before {
content: "\e659";
}
.uniui-camera:before {
content: "\e65a";
}
.uniui-circle:before {
content: "\e65b";
}
.uniui-checkmarkempty:before {
content: "\e65c";
}
.uniui-chat:before {
content: "\e65d";
}
.uniui-circle-filled:before {
content: "\e65e";
}
.uniui-flag:before {
content: "\e65f";
}
.uniui-flag-filled:before {
content: "\e660";
}
.uniui-gear-filled:before {
content: "\e661";
}
.uniui-home:before {
content: "\e662";
}
.uniui-home-filled:before {
content: "\e663";
}
.uniui-gear:before {
content: "\e664";
}
.uniui-smallcircle-filled:before {
content: "\e665";
}
.uniui-map-filled:before {
content: "\e666";
}
.uniui-map:before {
content: "\e667";
}
.uniui-refresh-filled:before {
content: "\e656";
}
.uniui-refresh:before {
content: "\e657";
}
.uniui-cloud-upload:before {
content: "\e645";
}
.uniui-cloud-download-filled:before {
content: "\e646";
}
.uniui-cloud-download:before {
content: "\e647";
}
.uniui-cloud-upload-filled:before {
content: "\e648";
}
.uniui-redo:before {
content: "\e64a";
}
.uniui-images-filled:before {
content: "\e64b";
}
.uniui-undo-filled:before {
content: "\e64c";
}
.uniui-more:before {
content: "\e64d";
}
.uniui-more-filled:before {
content: "\e64e";
}
.uniui-undo:before {
content: "\e64f";
}
.uniui-images:before {
content: "\e650";
}
.uniui-paperclip:before {
content: "\e652";
}
.uniui-settings:before {
content: "\e653";
}
.uniui-search:before {
content: "\e654";
}
.uniui-redo-filled:before {
content: "\e655";
}
.uniui-list:before {
content: "\e644";
}
.uniui-mail-open-filled:before {
content: "\e63a";
}
.uniui-hand-down-filled:before {
content: "\e63c";
}
.uniui-hand-down:before {
content: "\e63d";
}
.uniui-hand-up-filled:before {
content: "\e63e";
}
.uniui-hand-up:before {
content: "\e63f";
}
.uniui-heart-filled:before {
content: "\e641";
}
.uniui-mail-open:before {
content: "\e643";
}
.uniui-heart:before {
content: "\e639";
}
.uniui-loop:before {
content: "\e633";
}
.uniui-pulldown:before {
content: "\e632";
}
.uniui-scan:before {
content: "\e62a";
}
.uniui-bars:before {
content: "\e627";
}
.uniui-checkbox:before {
content: "\e62b";
}
.uniui-checkbox-filled:before {
content: "\e62c";
}
.uniui-shop:before {
content: "\e62f";
}
.uniui-headphones:before {
content: "\e630";
}
.uniui-cart:before {
content: "\e631";
}
page {
background-color: #f5f5f5;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.container {
padding: 20rpx;
}
.card {
background: #ffffff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.btn-primary {
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
color: #ffffff;
border: none;
border-radius: 40rpx;
padding: 24rpx 48rpx;
font-size: 32rpx;
font-weight: 500;
text-align: center;
}
.btn-primary:active {
opacity: 0.85;
}
.price-text {
color: #3366ff;
font-weight: 600;
}
.amount-text {
color: #f59e0b;
font-weight: 700;
}page{--status-bar-height:25px;--top-window-height:0px;--window-top:0px;--window-bottom:0px;--window-left:0px;--window-right:0px;--window-magin:0px}[data-c-h="true"]{display: none !important;}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

+9
View File
@@ -0,0 +1,9 @@
"use strict";
const _imports_0$1 = "/static/logo.png";
const _imports_0 = "/assets/Price.0f657164.png";
const _imports_1 = "/static/Location.png";
const _imports_2 = "/assets/Recycle.06ae8010.png";
exports._imports_0 = _imports_0$1;
exports._imports_0$1 = _imports_0;
exports._imports_1 = _imports_1;
exports._imports_2 = _imports_2;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,71 @@
"use strict";
const common_vendor = require("../../../../../common/vendor.js");
const getVal = (val) => {
const reg = /^[0-9]*$/g;
return typeof val === "number" || reg.test(val) ? val + "px" : val;
};
const _sfc_main = {
name: "UniIcons",
emits: ["click"],
props: {
type: {
type: String,
default: ""
},
color: {
type: String,
default: "#333333"
},
size: {
type: [Number, String],
default: 16
},
customPrefix: {
type: String,
default: ""
},
fontFamily: {
type: String,
default: ""
}
},
data() {
return {
icons: common_vendor.fontData
};
},
computed: {
unicode() {
let code = this.icons.find((v) => v.font_class === this.type);
if (code) {
return code.unicode;
}
return "";
},
iconSize() {
return getVal(this.size);
},
styleObj() {
if (this.fontFamily !== "") {
return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`;
}
return `color: ${this.color}; font-size: ${this.iconSize};`;
}
},
methods: {
_onClick(e) {
this.$emit("click", e);
}
}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return {
a: common_vendor.s($options.styleObj),
b: common_vendor.n("uniui-" + $props.type),
c: common_vendor.n($props.customPrefix),
d: common_vendor.n($props.customPrefix ? $props.type : ""),
e: common_vendor.o((...args) => $options._onClick && $options._onClick(...args))
};
}
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
wx.createComponent(Component);
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
@@ -0,0 +1 @@
<text style="{{a}}" class="{{['uni-icons', b, c, d]}}" bindtap="{{e}}"><slot></slot></text>
File diff suppressed because one or more lines are too long
+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;
}
+64
View File
@@ -0,0 +1,64 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const stores_bluetooth = require("../../stores/bluetooth.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "bluetooth",
setup(__props) {
const bluetoothStore = stores_bluetooth.useBluetoothStore();
const toggleScan = () => {
if (bluetoothStore.isDiscovering) {
bluetoothStore.stopScan();
} else {
bluetoothStore.startScan();
}
};
const connect = async (deviceId) => {
if (bluetoothStore.isConnected) {
await bluetoothStore.disconnect();
}
await bluetoothStore.connect(deviceId);
if (bluetoothStore.isConnected) {
common_vendor.index.showToast({ title: "连接成功", icon: "success" });
setTimeout(() => {
common_vendor.index.navigateBack();
}, 1500);
}
};
const disconnect = async () => {
await bluetoothStore.disconnect();
common_vendor.index.showToast({ title: "已断开连接", icon: "none" });
};
const getSignalStrength = (rssi) => {
if (rssi >= -50) return "📶";
if (rssi >= -70) return "📡";
return "📴";
};
return (_ctx, _cache) => {
var _a;
return common_vendor.e({
a: common_vendor.t(common_vendor.unref(bluetoothStore).isDiscovering ? "⏹️" : "🔍"),
b: common_vendor.t(common_vendor.unref(bluetoothStore).isDiscovering ? "停止搜索" : "搜索设备"),
c: common_vendor.unref(bluetoothStore).isDiscovering ? 1 : "",
d: common_vendor.o(toggleScan),
e: common_vendor.unref(bluetoothStore).isConnected
}, common_vendor.unref(bluetoothStore).isConnected ? {
f: common_vendor.t((_a = common_vendor.unref(bluetoothStore).connectedDevice) == null ? void 0 : _a.name),
g: common_vendor.o(disconnect)
} : {}, {
h: common_vendor.unref(bluetoothStore).deviceList.length > 0
}, common_vendor.unref(bluetoothStore).deviceList.length > 0 ? {
i: common_vendor.f(common_vendor.unref(bluetoothStore).deviceList, (device, k0, i0) => {
return {
a: common_vendor.t(device.name),
b: common_vendor.t(device.deviceId),
c: common_vendor.t(getSignalStrength(device.RSSI)),
d: device.deviceId,
e: common_vendor.o(($event) => connect(device.deviceId), device.deviceId)
};
})
} : {});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-b0f86abb"]]);
wx.createPage(MiniProgramPage);
+6
View File
@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "蓝牙连接",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="container data-v-b0f86abb"><view class="scan-header data-v-b0f86abb"><view class="{{['scan-btn', 'data-v-b0f86abb', c && 'scanning']}}" bindtap="{{d}}"><text class="scan-icon data-v-b0f86abb">{{a}}</text><text class="data-v-b0f86abb">{{b}}</text></view></view><view class="status-section data-v-b0f86abb"><view wx:if="{{e}}" class="status-item connected data-v-b0f86abb"><text class="status-dot data-v-b0f86abb"></text><text class="status-text data-v-b0f86abb">已连接接 {{f}}</text><view class="disconnect-btn data-v-b0f86abb" bindtap="{{g}}">断开</view></view><view wx:else class="status-item disconnected data-v-b0f86abb"><text class="status-dot data-v-b0f86abb"></text><text class="status-text data-v-b0f86abb">未连接接设备</text></view></view><view wx:if="{{h}}" class="device-list data-v-b0f86abb"><view class="list-title data-v-b0f86abb"><text class="list-icon data-v-b0f86abb">📱</text><text class="data-v-b0f86abb">可用设备</text></view><view wx:for="{{i}}" wx:for-item="device" wx:key="d" class="device-item data-v-b0f86abb" bindtap="{{device.e}}"><view class="device-info data-v-b0f86abb"><text class="device-icon data-v-b0f86abb">📦</text><view class="device-detail data-v-b0f86abb"><text class="device-name data-v-b0f86abb">{{device.a}}</text><text class="device-id data-v-b0f86abb">{{device.b}}</text></view></view><view class="device-signal data-v-b0f86abb"><text class="data-v-b0f86abb">{{device.c}}</text></view></view></view><view wx:else class="empty-state data-v-b0f86abb"><text class="empty-icon data-v-b0f86abb">📡</text><text class="empty-text data-v-b0f86abb">暂无可用设备</text><text class="empty-hint data-v-b0f86abb">请确保电子秤已开启蓝牙</text></view><view class="tips-card data-v-b0f86abb"><text class="tips-icon data-v-b0f86abb">💡</text><text class="tips-text data-v-b0f86abb">搜索范围10米,设备名称通常包含"Scale"</text></view></view>
+171
View File
@@ -0,0 +1,171 @@
.container.data-v-b0f86abb {
min-height: 100vh;
background: #f5f5f5;
padding: 32rpx;
}
.scan-header.data-v-b0f86abb {
margin-bottom: 24rpx;
}
.scan-btn.data-v-b0f86abb {
background: #fff;
border-radius: 40rpx;
padding: 24rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: 600;
color: #3366ff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);
}
.scan-btn.scanning.data-v-b0f86abb {
background: #fee2e2;
color: #ef4444;
}
.scan-icon.data-v-b0f86abb {
margin-right: 12rpx;
}
.status-section.data-v-b0f86abb {
margin-bottom: 32rpx;
}
.status-item.data-v-b0f86abb {
display: flex;
align-items: center;
padding: 20rpx 24rpx;
border-radius: 12rpx;
}
.status-item.connected.data-v-b0f86abb {
background: #dcfce7;
}
.status-item.disconnected.data-v-b0f86abb {
background: #fef2f2;
}
.status-dot.data-v-b0f86abb {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
margin-right: 12rpx;
}
.connected .status-dot.data-v-b0f86abb {
background: #22c55e;
}
.disconnected .status-dot.data-v-b0f86abb {
background: #ef4444;
}
.status-text.data-v-b0f86abb {
flex: 1;
font-size: 28rpx;
}
.connected .status-text.data-v-b0f86abb {
color: #166534;
}
.disconnected .status-text.data-v-b0f86abb {
color: #991b1b;
}
.disconnect-btn.data-v-b0f86abb {
font-size: 26rpx;
color: #ef4444;
padding: 8rpx 20rpx;
background: rgba(239, 68, 68, 0.1);
border-radius: 8rpx;
}
.device-list.data-v-b0f86abb {
background: #fff;
border-radius: 16rpx;
overflow: hidden;
margin-bottom: 24rpx;
}
.list-title.data-v-b0f86abb {
display: flex;
align-items: center;
padding: 24rpx;
font-size: 30rpx;
font-weight: 600;
color: #333;
border-bottom: 1rpx solid #f0f0f0;
}
.list-icon.data-v-b0f86abb {
margin-right: 12rpx;
}
.device-item.data-v-b0f86abb {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.device-item.data-v-b0f86abb:last-child {
border-bottom: none;
}
.device-item.data-v-b0f86abb:active {
background: #f9fafb;
}
.device-info.data-v-b0f86abb {
display: flex;
align-items: center;
flex: 1;
}
.device-icon.data-v-b0f86abb {
font-size: 40rpx;
margin-right: 16rpx;
}
.device-detail.data-v-b0f86abb {
display: flex;
flex-direction: column;
}
.device-name.data-v-b0f86abb {
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 4rpx;
}
.device-id.data-v-b0f86abb {
font-size: 22rpx;
color: #999;
}
.device-signal.data-v-b0f86abb {
font-size: 26rpx;
color: #666;
padding: 6rpx 16rpx;
background: #f3f4f6;
border-radius: 20rpx;
}
.empty-state.data-v-b0f86abb {
display: flex;
flex-direction: column;
align-items: center;
padding: 80rpx 40rpx;
background: #fff;
border-radius: 16rpx;
margin-bottom: 24rpx;
}
.empty-icon.data-v-b0f86abb {
font-size: 80rpx;
margin-bottom: 20rpx;
}
.empty-text.data-v-b0f86abb {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 8rpx;
}
.empty-hint.data-v-b0f86abb {
font-size: 26rpx;
color: #999;
}
.tips-card.data-v-b0f86abb {
background: #eff6ff;
border: 1rpx solid #dbeafe;
border-radius: 12rpx;
padding: 20rpx 24rpx;
display: flex;
align-items: center;
}
.tips-icon.data-v-b0f86abb {
font-size: 32rpx;
margin-right: 12rpx;
}
.tips-text.data-v-b0f86abb {
font-size: 26rpx;
color: #1e40af;
}
+225
View File
@@ -0,0 +1,225 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_assets = require("../../common/assets.js");
const stores_price = require("../../stores/price.js");
const stores_region = require("../../stores/region.js");
const utils_price = require("../../utils/price.js");
const api_index = require("../../api/index.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: "index",
setup(__props) {
const priceStore = stores_price.usePriceStore();
const regionStore = stores_region.useRegionStore();
const cities = common_vendor.ref([]);
const districts = common_vendor.ref([]);
const communities = common_vendor.ref([]);
const users = common_vendor.ref([]);
const showCityPicker = common_vendor.ref(false);
const showDistrictPicker = common_vendor.ref(false);
const showCommunityPicker = common_vendor.ref(false);
const showUserPicker = common_vendor.ref(false);
const goToPrice = () => {
common_vendor.index.navigateTo({ url: "/pages/price/price" });
};
const goToWeigh = (category) => {
common_vendor.index.navigateTo({ url: `/pages/weigh/weigh?category=${category}` });
};
const loadCities = async () => {
cities.value = await api_index.regionApi.getCities();
};
const loadDistricts = async (city) => {
const result = await api_index.regionApi.getDistricts(city);
districts.value = [...result, "其他"];
};
const loadCommunities = async (city, district) => {
const actualDistrict = district === "其他" ? "" : district;
const result = await api_index.regionApi.getStations(city, actualDistrict);
communities.value = [...result, "其他"];
};
const selectCity = async (city) => {
regionStore.setCity(city);
showCityPicker.value = false;
await loadDistricts(city);
};
const selectDistrict = async (district) => {
regionStore.setDistrict(district);
showDistrictPicker.value = false;
await loadCommunities(regionStore.selectedCity, district);
};
const loadUsers = async () => {
const stationName = regionStore.selectedCommunity;
if (stationName) {
const result = await api_index.regionApi.getSiteUsers(stationName);
if (result.length > 0) {
users.value = [...result];
} else {
users.value = ["新增商户", "新增个人"];
}
} else {
users.value = ["新增商户", "新增个人"];
}
};
const selectCommunity = async (community) => {
regionStore.setCommunity(community);
showCommunityPicker.value = false;
await loadUsers();
};
const selectUser = (user) => {
regionStore.setUser(user);
showUserPicker.value = false;
};
const onCustomDistrictInput = (e) => {
regionStore.setCustomDistrict(e.detail.value);
};
const onCustomCommunityInput = (e) => {
regionStore.setCustomCommunity(e.detail.value);
};
const onCustomUserInput = (e) => {
regionStore.setCustomUser(e.detail.value);
};
const closePickers = () => {
showCityPicker.value = false;
showDistrictPicker.value = false;
showCommunityPicker.value = false;
showUserPicker.value = false;
};
common_vendor.onMounted(async () => {
const isLoggedIn = common_vendor.index.getStorageSync("collector_login");
if (!isLoggedIn) {
common_vendor.index.redirectTo({ url: "/pages/user/login" });
return;
}
priceStore.loadPrices();
await loadCities();
if (regionStore.selectedCity) {
await loadDistricts(regionStore.selectedCity);
}
});
common_vendor.onShow(() => {
priceStore.loadPrices();
});
return (_ctx, _cache) => {
return common_vendor.e({
a: common_assets._imports_0$1,
b: common_vendor.o(goToPrice),
c: common_assets._imports_1,
d: common_vendor.t(common_vendor.unref(regionStore).selectedCity || "请选择城市"),
e: common_vendor.o(($event) => showCityPicker.value = true),
f: common_vendor.t(common_vendor.unref(regionStore).selectedDistrict || "请选择区"),
g: common_vendor.o(($event) => showDistrictPicker.value = true),
h: !common_vendor.unref(regionStore).selectedCity ? 1 : "",
i: common_vendor.unref(regionStore).selectedDistrict === "其他"
}, common_vendor.unref(regionStore).selectedDistrict === "其他" ? {
j: common_vendor.unref(regionStore).customDistrict,
k: common_vendor.o(onCustomDistrictInput)
} : {}, {
l: common_vendor.t(common_vendor.unref(regionStore).selectedCommunity || "请选择回收站点"),
m: common_vendor.o(($event) => showCommunityPicker.value = true),
n: !common_vendor.unref(regionStore).selectedDistrict ? 1 : "",
o: common_vendor.unref(regionStore).selectedCommunity === "其他"
}, common_vendor.unref(regionStore).selectedCommunity === "其他" ? {
p: common_vendor.unref(regionStore).customCommunity,
q: common_vendor.o(onCustomCommunityInput)
} : {}, {
r: common_vendor.t(common_vendor.unref(regionStore).selectedUser || "请选择用户"),
s: common_vendor.o(($event) => showUserPicker.value = true),
t: !common_vendor.unref(regionStore).selectedCommunity ? 1 : "",
v: common_vendor.unref(regionStore).selectedUser === "新增商户"
}, common_vendor.unref(regionStore).selectedUser === "新增商户" ? {
w: common_vendor.unref(regionStore).customUser,
x: common_vendor.o(onCustomUserInput)
} : {}, {
y: common_vendor.unref(regionStore).selectedUser === "新增个人"
}, common_vendor.unref(regionStore).selectedUser === "新增个人" ? {
z: common_vendor.unref(regionStore).customUser,
A: common_vendor.o(onCustomUserInput)
} : {}, {
B: common_assets._imports_2,
C: common_vendor.f(common_vendor.unref(priceStore).prices, (item, k0, i0) => {
return {
a: "83a5a03c-0-" + i0,
b: common_vendor.p({
type: common_vendor.unref(utils_price.getCategoryIcon)(item.category),
size: 64,
color: "#3366ff"
}),
c: common_vendor.t(item.name),
d: common_vendor.t(item.price),
e: common_vendor.t(item.unit === "kg" ? "kg" : "个"),
f: item.category,
g: common_vendor.o(($event) => goToWeigh(item.category), item.category)
};
}),
D: showCityPicker.value
}, showCityPicker.value ? {
E: common_vendor.o(closePickers),
F: common_vendor.f(cities.value, (city, k0, i0) => {
return {
a: common_vendor.t(city),
b: city,
c: common_vendor.unref(regionStore).selectedCity === city ? 1 : "",
d: common_vendor.o(($event) => selectCity(city), city)
};
}),
G: common_vendor.o(() => {
}),
H: common_vendor.o(closePickers)
} : {}, {
I: showDistrictPicker.value
}, showDistrictPicker.value ? {
J: common_vendor.o(closePickers),
K: common_vendor.f(districts.value, (district, k0, i0) => {
return {
a: common_vendor.t(district),
b: district,
c: common_vendor.unref(regionStore).selectedDistrict === district ? 1 : "",
d: common_vendor.o(($event) => selectDistrict(district), district)
};
}),
L: common_vendor.o(() => {
}),
M: common_vendor.o(closePickers)
} : {}, {
N: showCommunityPicker.value
}, showCommunityPicker.value ? {
O: common_vendor.o(closePickers),
P: common_vendor.f(communities.value, (community, k0, i0) => {
return {
a: common_vendor.t(community),
b: community,
c: common_vendor.unref(regionStore).selectedCommunity === community ? 1 : "",
d: common_vendor.o(($event) => selectCommunity(community), community)
};
}),
Q: common_vendor.o(() => {
}),
R: common_vendor.o(closePickers)
} : {}, {
S: showUserPicker.value
}, showUserPicker.value ? {
T: common_vendor.o(closePickers),
U: common_vendor.f(users.value, (user, k0, i0) => {
return {
a: common_vendor.t(user),
b: user,
c: common_vendor.unref(regionStore).selectedUser === user ? 1 : "",
d: common_vendor.o(($event) => selectUser(user), user)
};
}),
V: common_vendor.o(() => {
}),
W: common_vendor.o(closePickers)
} : {});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-83a5a03c"]]);
wx.createPage(MiniProgramPage);
+8
View File
@@ -0,0 +1,8 @@
{
"navigationBarTitleText": "易分宝回收",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {
"uni-icons": "../../node-modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons"
}
}
File diff suppressed because one or more lines are too long
+213
View File
@@ -0,0 +1,213 @@
.container.data-v-83a5a03c {
min-height: 100vh;
background: #f5f5f5;
}
.content.data-v-83a5a03c {
padding: 32rpx;
padding-top: 48rpx;
padding-bottom: 180rpx;
}
.region-card.data-v-83a5a03c {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 32rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.region-title.data-v-83a5a03c {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
display: flex;
align-items: center;
}
.region-icon.data-v-83a5a03c {
width: 36rpx;
height: 36rpx;
margin-right: 12rpx;
}
.region-row.data-v-83a5a03c {
margin-bottom: 16rpx;
}
.region-item.data-v-83a5a03c {
display: flex;
align-items: center;
justify-content: space-between;
}
.region-label.data-v-83a5a03c {
font-size: 28rpx;
color: #666;
width: 120rpx;
}
.region-select.data-v-83a5a03c {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding: 16rpx 20rpx;
background: #f8f8f8;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
}
.region-select.disabled.data-v-83a5a03c {
opacity: 0.5;
pointer-events: none;
}
.region-select .arrow.data-v-83a5a03c {
font-size: 20rpx;
color: #999;
}
.custom-region.data-v-83a5a03c {
padding-left: 120rpx;
margin-bottom: 16rpx;
}
.custom-region .region-input.data-v-83a5a03c {
width: calc(100% - 20rpx);
height: 80rpx;
padding: 20rpx;
background: #f8f8f8;
border-radius: 8rpx;
font-size: 28rpx;
box-sizing: border-box;
margin-left: 10rpx;
line-height: 40rpx;
}
.picker-overlay.data-v-83a5a03c {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: flex-end;
z-index: 1000;
}
.picker-content.data-v-83a5a03c {
width: 100%;
background: #fff;
border-radius: 24rpx 24rpx 0 0;
max-height: 60vh;
}
.picker-header.data-v-83a5a03c {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 32rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.picker-title.data-v-83a5a03c {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.picker-close.data-v-83a5a03c {
font-size: 36rpx;
color: #999;
}
.picker-list.data-v-83a5a03c {
max-height: 50vh;
}
.picker-item.data-v-83a5a03c {
padding: 28rpx 32rpx;
font-size: 30rpx;
color: #333;
border-bottom: 1rpx solid #f5f5f5;
}
.picker-item.active.data-v-83a5a03c {
color: #3366ff;
background: #f0f5ff;
}
.price-card.data-v-83a5a03c {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.price-card-left.data-v-83a5a03c {
display: flex;
align-items: center;
}
.price-icon.data-v-83a5a03c {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
.price-label.data-v-83a5a03c {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.price-card-right.data-v-83a5a03c {
color: #3366ff;
}
.price-arrow.data-v-83a5a03c {
font-size: 40rpx;
opacity: 0.8;
}
.section-title.data-v-83a5a03c {
display: flex;
align-items: center;
margin-bottom: 24rpx;
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.section-icon.data-v-83a5a03c {
width: 36rpx;
height: 36rpx;
margin-right: 12rpx;
}
.category-grid.data-v-83a5a03c {
display: flex;
flex-wrap: wrap;
gap: 24rpx;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
}
.category-item.data-v-83a5a03c {
width: 47%;
background: #fff;
border-radius: 16rpx;
padding: 32rpx 24rpx;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
transition: all 0.2s;
box-sizing: border-box;
}
.category-item.data-v-83a5a03c:active {
transform: scale(0.98);
opacity: 0.9;
}
.category-icon.data-v-83a5a03c {
margin-bottom: 16rpx;
}
.category-name.data-v-83a5a03c {
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 8rpx;
}
.category-price.data-v-83a5a03c {
display: flex;
align-items: baseline;
}
.price-value.data-v-83a5a03c {
font-size: 36rpx;
font-weight: 700;
color: #3366ff;
}
.price-unit.data-v-83a5a03c {
font-size: 24rpx;
color: #999;
margin-left: 4rpx;
}
+64
View File
@@ -0,0 +1,64 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const utils_order = require("../../utils/order.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: "detail",
setup(__props) {
const order = common_vendor.ref(null);
const goBack = () => {
common_vendor.index.navigateBack();
};
const createNewOrder = () => {
common_vendor.index.switchTab({ url: "/pages/index/index" });
};
common_vendor.onLoad(async (options) => {
if (options == null ? void 0 : options.orderId) {
const data = common_vendor.index.getStorageSync("orders");
const orders = data ? JSON.parse(data) : [];
order.value = orders.find((o) => o.orderId === options.orderId) || null;
}
});
return (_ctx, _cache) => {
var _a, _b, _c, _d, _e, _f, _g;
return {
a: common_vendor.t((_a = order.value) == null ? void 0 : _a.orderId),
b: common_vendor.t(order.value ? common_vendor.unref(utils_order.formatOrderTime)(order.value.timestamp) : "-"),
c: common_vendor.t(((_b = order.value) == null ? void 0 : _b.status) === "completed" ? "已完成" : ((_c = order.value) == null ? void 0 : _c.status) === "pending" ? "待处理" : "已取消"),
d: common_vendor.n((_d = order.value) == null ? void 0 : _d.status),
e: common_vendor.f((_e = order.value) == null ? void 0 : _e.items, (item, index, i0) => {
return {
a: "5511cfa9-0-" + i0,
b: common_vendor.p({
type: common_vendor.unref(utils_price.getCategoryIcon)(item.category),
size: 40,
color: "#3366ff"
}),
c: common_vendor.t(item.name),
d: common_vendor.t(item.unit === "kg" ? "重量" : "数量"),
e: common_vendor.t(item.weight || item.count),
f: common_vendor.t(item.unit === "kg" ? "kg" : "个"),
g: common_vendor.t(item.unitPrice),
h: common_vendor.t(item.unit === "kg" ? "kg" : "个"),
i: common_vendor.t(item.amount.toFixed(2)),
j: index
};
}),
f: common_vendor.t(((_f = order.value) == null ? void 0 : _f.totalAmount.toFixed(2)) || "0.00"),
g: common_vendor.t(((_g = order.value) == null ? void 0 : _g.totalAmount.toFixed(2)) || "0.00"),
h: common_vendor.o(goBack),
i: common_vendor.o(createNewOrder)
};
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-5511cfa9"]]);
wx.createPage(MiniProgramPage);
+8
View File
@@ -0,0 +1,8 @@
{
"navigationBarTitleText": "订单详情",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {
"uni-icons": "../../node-modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons"
}
}
+1
View File
@@ -0,0 +1 @@
<view class="container data-v-5511cfa9"><view class="detail-card data-v-5511cfa9"><view class="detail-header data-v-5511cfa9"><view class="order-info data-v-5511cfa9"><text class="order-id data-v-5511cfa9">{{a}}</text><text class="order-time data-v-5511cfa9">{{b}}</text></view><view class="{{['order-status', 'data-v-5511cfa9', d]}}">{{c}}</view></view><view class="detail-section data-v-5511cfa9"><view class="section-title data-v-5511cfa9"><text class="section-icon data-v-5511cfa9">📦</text><text class="data-v-5511cfa9">回收物品</text></view><view class="items-list data-v-5511cfa9"><view wx:for="{{e}}" wx:for-item="item" wx:key="j" class="item-card data-v-5511cfa9"><view class="item-left data-v-5511cfa9"><uni-icons wx:if="{{item.b}}" class="item-icon data-v-5511cfa9" u-i="{{item.a}}" bind:__l="__l" u-p="{{item.b}}"/><view class="item-info data-v-5511cfa9"><text class="item-name data-v-5511cfa9">{{item.c}}</text><text class="item-spec data-v-5511cfa9">{{item.d}}: {{item.e}} {{item.f}}</text></view></view><view class="item-right data-v-5511cfa9"><text class="item-price data-v-5511cfa9">¥{{item.g}}/{{item.h}}</text><text class="item-amount data-v-5511cfa9">¥{{item.i}}</text></view></view></view></view><view class="detail-section data-v-5511cfa9"><view class="section-title data-v-5511cfa9"><text class="section-icon data-v-5511cfa9">💰</text><text class="data-v-5511cfa9">金额明细</text></view><view class="amount-detail data-v-5511cfa9"><view class="amount-row data-v-5511cfa9"><text class="amount-label data-v-5511cfa9">物品总价</text><text class="amount-value data-v-5511cfa9">¥{{f}}</text></view><view class="amount-row data-v-5511cfa9"><text class="amount-label data-v-5511cfa9">优惠金额</text><text class="amount-value discount data-v-5511cfa9">-¥0.00</text></view><view class="amount-row total data-v-5511cfa9"><text class="amount-label data-v-5511cfa9">实付金额</text><text class="amount-value data-v-5511cfa9">¥{{g}}</text></view></view></view></view><view class="bottom-actions data-v-5511cfa9"><view class="action-btn secondary data-v-5511cfa9" bindtap="{{h}}"><text class="data-v-5511cfa9">返回</text></view><view class="action-btn primary data-v-5511cfa9" bindtap="{{i}}"><text class="data-v-5511cfa9">继续回收</text></view></view></view>
+175
View File
@@ -0,0 +1,175 @@
.container.data-v-5511cfa9 {
min-height: 100vh;
background: #f5f5f5;
padding: 32rpx;
padding-bottom: 160rpx;
}
.detail-card.data-v-5511cfa9 {
background: #fff;
border-radius: 16rpx;
overflow: hidden;
}
.detail-header.data-v-5511cfa9 {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 28rpx 24rpx;
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
}
.order-info.data-v-5511cfa9 {
display: flex;
flex-direction: column;
}
.order-id.data-v-5511cfa9 {
font-size: 30rpx;
font-weight: 600;
color: #fff;
margin-bottom: 8rpx;
}
.order-time.data-v-5511cfa9 {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
.order-status.data-v-5511cfa9 {
font-size: 24rpx;
padding: 8rpx 20rpx;
border-radius: 20rpx;
background: rgba(255, 255, 255, 0.2);
color: #fff;
}
.detail-section.data-v-5511cfa9 {
padding: 24rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.detail-section.data-v-5511cfa9:last-child {
border-bottom: none;
}
.section-title.data-v-5511cfa9 {
display: flex;
align-items: center;
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
}
.section-icon.data-v-5511cfa9 {
margin-right: 12rpx;
}
.items-list.data-v-5511cfa9 {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.item-card.data-v-5511cfa9 {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
background: #f9fafb;
border-radius: 12rpx;
}
.item-left.data-v-5511cfa9 {
display: flex;
align-items: center;
flex: 1;
}
.item-icon.data-v-5511cfa9 {
font-size: 44rpx;
margin-right: 16rpx;
}
.item-info.data-v-5511cfa9 {
display: flex;
flex-direction: column;
}
.item-name.data-v-5511cfa9 {
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 4rpx;
}
.item-spec.data-v-5511cfa9 {
font-size: 24rpx;
color: #999;
}
.item-right.data-v-5511cfa9 {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.item-price.data-v-5511cfa9 {
font-size: 24rpx;
color: #999;
margin-bottom: 4rpx;
}
.item-amount.data-v-5511cfa9 {
font-size: 32rpx;
font-weight: 600;
color: #3366ff;
}
.amount-detail.data-v-5511cfa9 {
background: #f9fafb;
border-radius: 12rpx;
padding: 20rpx;
}
.amount-row.data-v-5511cfa9 {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12rpx 0;
}
.amount-row.total.data-v-5511cfa9 {
padding-top: 16rpx;
margin-top: 12rpx;
border-top: 1rpx dashed #e5e7eb;
}
.amount-label.data-v-5511cfa9 {
font-size: 28rpx;
color: #666;
}
.total .amount-label.data-v-5511cfa9 {
font-weight: 600;
color: #333;
}
.amount-value.data-v-5511cfa9 {
font-size: 28rpx;
font-weight: 600;
color: #333;
}
.amount-value.discount.data-v-5511cfa9 {
color: #f59e0b;
}
.total .amount-value.data-v-5511cfa9 {
font-size: 36rpx;
color: #3366ff;
}
.bottom-actions.data-v-5511cfa9 {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
gap: 24rpx;
padding: 24rpx 32rpx;
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
background: #fff;
box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.action-btn.data-v-5511cfa9 {
flex: 1;
border-radius: 40rpx;
padding: 24rpx;
text-align: center;
font-size: 32rpx;
font-weight: 600;
}
.action-btn.secondary.data-v-5511cfa9 {
background: #f3f4f6;
color: #666;
}
.action-btn.primary.data-v-5511cfa9 {
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
color: #fff;
}
.action-btn.data-v-5511cfa9:active {
opacity: 0.85;
}
+98
View File
@@ -0,0 +1,98 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const stores_order = require("../../stores/order.js");
const utils_order = require("../../utils/order.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "list",
setup(__props) {
const orderStore = stores_order.useOrderStore();
const selectedOrders = common_vendor.ref([]);
const isAllSelected = common_vendor.computed(() => {
return orderStore.orders.length > 0 && selectedOrders.value.length === orderStore.orders.length;
});
const selectedTotalAmount = common_vendor.computed(() => {
return selectedOrders.value.reduce((sum, orderId) => {
const order = orderStore.orders.find((o) => o.id === orderId);
return sum + ((order == null ? void 0 : order.totalAmount) || 0);
}, 0);
});
const toggleSelect = (orderId) => {
const index = selectedOrders.value.indexOf(orderId);
if (index > -1) {
selectedOrders.value.splice(index, 1);
} else {
selectedOrders.value.push(orderId);
}
};
const toggleSelectAll = () => {
if (isAllSelected.value) {
selectedOrders.value = [];
} else {
selectedOrders.value = orderStore.orders.map((o) => o.id);
}
};
const handleDelete = (orderId) => {
common_vendor.index.showModal({
title: "确认删除",
content: "确定要删除这笔订单吗?",
success: async (res) => {
if (res.confirm) {
await orderStore.deleteOrder(orderId);
selectedOrders.value = selectedOrders.value.filter((id) => id !== orderId);
}
}
});
};
const getRegionText = (order) => {
const parts = [];
if (order.city) parts.push(order.city);
if (order.district) parts.push(order.district);
if (order.community) parts.push(order.community);
return parts.join(" > ") || "未选择区域";
};
common_vendor.onMounted(() => {
orderStore.loadOrders();
});
return (_ctx, _cache) => {
return common_vendor.e({
a: common_vendor.unref(orderStore).orders.length > 0
}, common_vendor.unref(orderStore).orders.length > 0 ? {
b: common_vendor.f(common_vendor.unref(orderStore).orders, (order, k0, i0) => {
return common_vendor.e({
a: selectedOrders.value.includes(order.id)
}, selectedOrders.value.includes(order.id) ? {} : {}, {
b: selectedOrders.value.includes(order.id) ? 1 : "",
c: common_vendor.o(($event) => toggleSelect(order.id), order.id),
d: common_vendor.t(getRegionText(order)),
e: common_vendor.t(common_vendor.unref(utils_order.formatOrderTime)(order.createTime)),
f: common_vendor.f(order.items, (item, index, i1) => {
return {
a: common_vendor.t(item.name),
b: common_vendor.t(item.weight || item.count),
c: common_vendor.t(item.unit === "kg" ? "kg" : "个"),
d: common_vendor.t(item.price.toFixed(2)),
e: common_vendor.t(item.unit === "kg" ? "kg" : "个"),
f: common_vendor.t(item.amount.toFixed(2)),
g: index
};
}),
g: common_vendor.t(order.totalAmount.toFixed(2)),
h: common_vendor.o(($event) => handleDelete(order.id), order.id),
i: order.id
});
})
} : {}, {
c: selectedOrders.value.length > 0
}, selectedOrders.value.length > 0 ? common_vendor.e({
d: isAllSelected.value
}, isAllSelected.value ? {} : {}, {
e: isAllSelected.value ? 1 : "",
f: common_vendor.o(toggleSelectAll),
g: common_vendor.t(selectedOrders.value.length),
h: common_vendor.t(selectedTotalAmount.value.toFixed(2))
}) : {});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-80f8e5f8"]]);
wx.createPage(MiniProgramPage);
+6
View File
@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "订单列表",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="container data-v-80f8e5f8"><view class="content data-v-80f8e5f8"><view wx:if="{{a}}" class="order-list data-v-80f8e5f8"><view wx:for="{{b}}" wx:for-item="order" wx:key="i" class="order-item data-v-80f8e5f8"><view class="order-checkbox data-v-80f8e5f8" catchtap="{{order.c}}"><view class="{{['checkbox', 'data-v-80f8e5f8', order.b && 'checked']}}"><text wx:if="{{order.a}}" class="check-icon data-v-80f8e5f8">✓</text></view></view><view class="order-content data-v-80f8e5f8"><view class="order-header data-v-80f8e5f8"><view class="order-region data-v-80f8e5f8"><text class="region-icon data-v-80f8e5f8">📍</text><text class="region-text data-v-80f8e5f8">{{order.d}}</text></view><text class="order-time data-v-80f8e5f8">{{order.e}}</text></view><view class="order-items data-v-80f8e5f8"><view wx:for="{{order.f}}" wx:for-item="item" wx:key="g" class="order-item-row data-v-80f8e5f8"><text class="item-name data-v-80f8e5f8">{{item.a}}</text><view class="item-info data-v-80f8e5f8"><text class="item-weight data-v-80f8e5f8">{{item.b}} {{item.c}}</text><text class="item-price data-v-80f8e5f8">¥{{item.d}}/{{item.e}}</text></view><text class="item-amount data-v-80f8e5f8">¥{{item.f}}</text></view></view><view class="order-footer data-v-80f8e5f8"><view class="order-total data-v-80f8e5f8"><text class="total-label data-v-80f8e5f8">合计:</text><text class="total-amount data-v-80f8e5f8">¥{{order.g}}</text></view><view class="order-actions data-v-80f8e5f8"><text class="delete-btn data-v-80f8e5f8" catchtap="{{order.h}}">删除</text></view></view></view></view></view><view wx:else class="empty-state data-v-80f8e5f8"><text class="empty-icon data-v-80f8e5f8">📭</text><text class="empty-text data-v-80f8e5f8">暂无订单</text><text class="empty-hint data-v-80f8e5f8">完成回收后将在此显示订单记录</text></view></view><view wx:if="{{c}}" class="bottom-bar data-v-80f8e5f8"><view class="select-all data-v-80f8e5f8" bindtap="{{f}}"><view class="{{['checkbox', 'data-v-80f8e5f8', e && 'checked']}}"><text wx:if="{{d}}" class="check-icon data-v-80f8e5f8">✓</text></view><text class="select-text data-v-80f8e5f8">全选</text></view><view class="selected-info data-v-80f8e5f8"><text class="selected-count data-v-80f8e5f8">已选 {{g}} 单</text><text class="selected-total data-v-80f8e5f8">合计: ¥{{h}}</text></view></view></view>
+210
View File
@@ -0,0 +1,210 @@
.container.data-v-80f8e5f8 {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 120rpx;
}
.content.data-v-80f8e5f8 {
padding: 32rpx;
}
.order-list.data-v-80f8e5f8 {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.order-item.data-v-80f8e5f8 {
display: flex;
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.order-checkbox.data-v-80f8e5f8 {
display: flex;
align-items: flex-start;
padding-right: 20rpx;
padding-top: 8rpx;
}
.checkbox.data-v-80f8e5f8 {
width: 44rpx;
height: 44rpx;
border: 2rpx solid #ddd;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.checkbox.checked.data-v-80f8e5f8 {
background: #3366ff;
border-color: #3366ff;
}
.check-icon.data-v-80f8e5f8 {
color: #fff;
font-size: 24rpx;
font-weight: bold;
}
.order-content.data-v-80f8e5f8 {
flex: 1;
}
.order-header.data-v-80f8e5f8 {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 16rpx;
padding-bottom: 16rpx;
border-bottom: 1rpx dashed #f0f0f0;
}
.order-region.data-v-80f8e5f8 {
display: flex;
align-items: center;
flex: 1;
}
.region-icon.data-v-80f8e5f8 {
font-size: 28rpx;
margin-right: 8rpx;
}
.region-text.data-v-80f8e5f8 {
font-size: 26rpx;
color: #333;
font-weight: 500;
}
.order-time.data-v-80f8e5f8 {
font-size: 24rpx;
color: #999;
}
.order-items.data-v-80f8e5f8 {
margin-bottom: 16rpx;
}
.order-item-row.data-v-80f8e5f8 {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12rpx 0;
}
.order-item-row.data-v-80f8e5f8:not(:last-child) {
border-bottom: 1rpx solid #f8f9fa;
}
.item-name.data-v-80f8e5f8 {
font-size: 28rpx;
color: #333;
flex: 1;
}
.item-info.data-v-80f8e5f8 {
display: flex;
flex-direction: column;
align-items: flex-end;
flex: 2;
margin-right: 16rpx;
}
.item-weight.data-v-80f8e5f8 {
font-size: 24rpx;
color: #666;
}
.item-price.data-v-80f8e5f8 {
font-size: 24rpx;
color: #999;
}
.item-amount.data-v-80f8e5f8 {
font-size: 28rpx;
font-weight: 600;
color: #3366ff;
}
.order-footer.data-v-80f8e5f8 {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 16rpx;
border-top: 1rpx dashed #f0f0f0;
}
.order-total.data-v-80f8e5f8 {
display: flex;
align-items: baseline;
}
.total-label.data-v-80f8e5f8 {
font-size: 26rpx;
color: #666;
margin-right: 8rpx;
}
.total-amount.data-v-80f8e5f8 {
font-size: 36rpx;
font-weight: 700;
color: #3366ff;
}
.order-actions.data-v-80f8e5f8 {
margin-left: 16rpx;
}
.delete-btn.data-v-80f8e5f8 {
font-size: 26rpx;
color: #ff4d4f;
padding: 8rpx 16rpx;
border: 1rpx solid #ff4d4f;
border-radius: 8rpx;
}
.empty-state.data-v-80f8e5f8 {
display: flex;
flex-direction: column;
align-items: center;
padding: 120rpx 40rpx;
background: #fff;
border-radius: 16rpx;
}
.empty-icon.data-v-80f8e5f8 {
font-size: 100rpx;
margin-bottom: 24rpx;
}
.empty-text.data-v-80f8e5f8 {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 12rpx;
}
.empty-hint.data-v-80f8e5f8 {
font-size: 26rpx;
color: #999;
}
.bottom-bar.data-v-80f8e5f8 {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 32rpx;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
background: #fff;
box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.08);
}
.select-all.data-v-80f8e5f8 {
display: flex;
align-items: center;
}
.select-text.data-v-80f8e5f8 {
font-size: 28rpx;
color: #333;
margin-left: 12rpx;
}
.selected-info.data-v-80f8e5f8 {
display: flex;
align-items: baseline;
gap: 16rpx;
}
.selected-count.data-v-80f8e5f8 {
font-size: 26rpx;
color: #666;
}
.selected-total.data-v-80f8e5f8 {
font-size: 32rpx;
font-weight: 700;
color: #3366ff;
}
.batch-delete.data-v-80f8e5f8 {
margin-left: 16rpx;
}
.batch-delete-btn.data-v-80f8e5f8 {
font-size: 28rpx;
color: #fff;
padding: 12rpx 24rpx;
background: #ff4d4f;
border-radius: 8rpx;
}
+50
View File
@@ -0,0 +1,50 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_assets = require("../../common/assets.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: "price",
setup(__props) {
const priceStore = stores_price.usePriceStore();
const refreshPrices = () => {
priceStore.loadPrices();
common_vendor.index.showToast({ title: "已刷新新", icon: "success" });
};
common_vendor.onMounted(() => {
priceStore.loadPrices();
});
return (_ctx, _cache) => {
return {
a: common_assets._imports_0$1,
b: common_vendor.t(common_vendor.unref(priceStore).date),
c: common_vendor.o(refreshPrices),
d: common_vendor.f(common_vendor.unref(priceStore).prices, (item, k0, i0) => {
return {
a: "51f4885f-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.unit === "kg" ? "重量" : "个数"),
e: common_vendor.t(item.price),
f: common_vendor.t(item.unit === "kg" ? "kg" : "个"),
g: item.category
};
})
};
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-51f4885f"]]);
wx.createPage(MiniProgramPage);
+8
View File
@@ -0,0 +1,8 @@
{
"navigationBarTitleText": "今日价格",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {
"uni-icons": "../../node-modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons"
}
}
+1
View File
@@ -0,0 +1 @@
<view class="container data-v-51f4885f"><view class="date-header data-v-51f4885f"><view class="date-label-wrap data-v-51f4885f"><image class="date-icon data-v-51f4885f" src="{{a}}" mode="aspectFit"/><text class="date-label data-v-51f4885f">今日价格</text></view><text class="date-value data-v-51f4885f">{{b}}</text></view><view class="refresh-btn data-v-51f4885f" bindtap="{{c}}"><text class="refresh-icon data-v-51f4885f">🔄</text><text class="data-v-51f4885f">刷新</text></view><view class="price-list data-v-51f4885f"><view wx:for="{{d}}" wx:for-item="item" wx:key="g" class="price-item data-v-51f4885f"><view class="price-item-left data-v-51f4885f"><uni-icons wx:if="{{item.b}}" class="price-icon data-v-51f4885f" u-i="{{item.a}}" bind:__l="__l" u-p="{{item.b}}"/><view class="price-info data-v-51f4885f"><text class="price-name data-v-51f4885f">{{item.c}}</text><text class="price-desc data-v-51f4885f">按{{item.d}}计价</text></view></view><view class="price-item-right data-v-51f4885f"><text class="price-amount data-v-51f4885f"><text class="currency data-v-51f4885f">¥</text><text class="amount-num data-v-51f4885f">{{item.e}}</text><text class="amount-unit data-v-51f4885f">/{{item.f}}</text></text></view></view></view><view class="tips-card data-v-51f4885f"><text class="tips-icon data-v-51f4885f">💡</text><text class="tips-text data-v-51f4885f">价格每日更新,实际回收以当日价格为准</text></view></view>
+122
View File
@@ -0,0 +1,122 @@
.container.data-v-51f4885f {
min-height: 100vh;
background: #f5f5f5;
padding: 32rpx;
}
.date-header.data-v-51f4885f {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
}
.date-label-wrap.data-v-51f4885f {
display: flex;
align-items: center;
}
.date-icon.data-v-51f4885f {
width: 48rpx;
height: 48rpx;
margin-right: 12rpx;
}
.date-label.data-v-51f4885f {
font-size: 40rpx;
font-weight: 700;
color: #333;
}
.date-value.data-v-51f4885f {
font-size: 28rpx;
color: #666;
}
.refresh-btn.data-v-51f4885f {
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border-radius: 40rpx;
padding: 16rpx 32rpx;
margin-bottom: 24rpx;
font-size: 28rpx;
color: #3366ff;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
}
.refresh-icon.data-v-51f4885f {
margin-right: 8rpx;
}
.price-list.data-v-51f4885f {
background: #fff;
border-radius: 16rpx;
overflow: hidden;
margin-bottom: 24rpx;
}
.price-item.data-v-51f4885f {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28rpx 24rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.price-item.data-v-51f4885f:last-child {
border-bottom: none;
}
.price-item-left.data-v-51f4885f {
display: flex;
align-items: center;
}
.price-icon.data-v-51f4885f {
font-size: 48rpx;
margin-right: 20rpx;
}
.price-info.data-v-51f4885f {
display: flex;
flex-direction: column;
}
.price-name.data-v-51f4885f {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 4rpx;
}
.price-desc.data-v-51f4885f {
font-size: 24rpx;
color: #999;
}
.price-item-right.data-v-51f4885f {
display: flex;
align-items: baseline;
}
.price-amount.data-v-51f4885f {
display: flex;
align-items: baseline;
}
.currency.data-v-51f4885f {
font-size: 28rpx;
font-weight: 600;
color: #3366ff;
}
.amount-num.data-v-51f4885f {
font-size: 44rpx;
font-weight: 700;
color: #3366ff;
margin-left: 4rpx;
}
.amount-unit.data-v-51f4885f {
font-size: 24rpx;
color: #999;
margin-left: 4rpx;
}
.tips-card.data-v-51f4885f {
background: #fffbeb;
border: 1rpx solid #fef3c7;
border-radius: 12rpx;
padding: 20rpx 24rpx;
display: flex;
align-items: center;
}
.tips-icon.data-v-51f4885f {
font-size: 32rpx;
margin-right: 12rpx;
}
.tips-text.data-v-51f4885f {
font-size: 26rpx;
color: #92400e;
}
+79
View File
@@ -0,0 +1,79 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_assets = require("../../common/assets.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "login",
setup(__props) {
const phone = common_vendor.ref("");
const password = common_vendor.ref("");
const rememberMe = common_vendor.ref(false);
const isLoading = common_vendor.ref(false);
const mockUsers = [
{ id: "1", name: "管理员", phone: "13800138000", role: "admin", createTime: "2024-01-01" },
{ id: "2", name: "回收员小王", phone: "18698102228", role: "collector", createTime: "2024-01-15" }
];
const login = async () => {
if (!phone.value) {
common_vendor.index.showToast({ title: "请输入手机号", icon: "none" });
return;
}
if (phone.value.length !== 11) {
common_vendor.index.showToast({ title: "请输入正确的手机号", icon: "none" });
return;
}
if (!password.value) {
common_vendor.index.showToast({ title: "请输入密码", icon: "none" });
return;
}
isLoading.value = true;
try {
const user = mockUsers.find((u) => u.phone === phone.value && u.role === "collector");
console.log("Available users:", JSON.stringify(mockUsers));
console.log("Input phone:", phone.value);
console.log("Found user:", JSON.stringify(user));
if (user) {
if (password.value === "123456") {
common_vendor.index.setStorageSync("collector_login", true);
common_vendor.index.setStorageSync("collector_info", JSON.stringify(user));
common_vendor.index.showToast({ title: "登录成功", icon: "success" });
setTimeout(() => {
common_vendor.index.switchTab({ url: "/pages/index/index" });
}, 1500);
} else {
common_vendor.index.showToast({ title: "密码错误", icon: "none" });
}
} else {
common_vendor.index.showToast({ title: "用户不存在", icon: "none" });
}
} catch (error) {
console.error("Login error:", error);
common_vendor.index.showToast({ title: "登录失败", icon: "none" });
} finally {
isLoading.value = false;
}
};
const forgotPassword = () => {
common_vendor.index.showToast({ title: "请联系管理员重置密码", icon: "none" });
};
return (_ctx, _cache) => {
return common_vendor.e({
a: common_assets._imports_0,
b: phone.value,
c: common_vendor.o(($event) => phone.value = $event.detail.value),
d: password.value,
e: common_vendor.o(($event) => password.value = $event.detail.value),
f: rememberMe.value
}, rememberMe.value ? {} : {}, {
g: rememberMe.value ? 1 : "",
h: common_vendor.o(($event) => rememberMe.value = !rememberMe.value),
i: isLoading.value
}, isLoading.value ? {} : {}, {
j: common_vendor.o(login),
k: isLoading.value ? 1 : "",
l: common_vendor.o(forgotPassword)
});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-ebed24a8"]]);
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-ebed24a8"><view class="login-box data-v-ebed24a8"><image class="login-logo data-v-ebed24a8" src="{{a}}" mode="aspectFit"/><view class="login-title data-v-ebed24a8">易分宝回收</view><view class="login-subtitle data-v-ebed24a8">回收员登录</view><view class="form-group data-v-ebed24a8"><view class="form-label data-v-ebed24a8">手机号</view><input type="text" class="form-input data-v-ebed24a8" placeholder="请输入手机号" maxlength="11" value="{{b}}" bindinput="{{c}}"/></view><view class="form-group data-v-ebed24a8"><view class="form-label data-v-ebed24a8">密码</view><input type="password" class="form-input data-v-ebed24a8" placeholder="请输入密码" value="{{d}}" bindinput="{{e}}"/></view><view class="form-group data-v-ebed24a8"><view class="checkbox data-v-ebed24a8" bindtap="{{h}}"><view class="{{['checkbox-box', 'data-v-ebed24a8', g && 'checked']}}"><text wx:if="{{f}}" class="data-v-ebed24a8">✓</text></view><text class="data-v-ebed24a8">记住密码</text></view></view><view bindtap="{{j}}" class="{{['login-btn', 'data-v-ebed24a8', k && 'disabled']}}"><text wx:if="{{i}}" class="data-v-ebed24a8">登录中...</text><text wx:else class="data-v-ebed24a8">登录</text></view><view class="forgot-link data-v-ebed24a8" bindtap="{{l}}"><text class="data-v-ebed24a8">忘记密码?</text></view></view></view>
+106
View File
@@ -0,0 +1,106 @@
.login-container.data-v-ebed24a8 {
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-ebed24a8 {
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-ebed24a8 {
width: 160rpx;
height: 160rpx;
margin: 0 auto 24rpx;
display: block;
}
.login-title.data-v-ebed24a8 {
font-size: 40rpx;
font-weight: 700;
color: #333;
text-align: center;
margin-bottom: 8rpx;
}
.login-subtitle.data-v-ebed24a8 {
font-size: 28rpx;
color: #999;
text-align: center;
margin-bottom: 48rpx;
}
.form-group.data-v-ebed24a8 {
margin-bottom: 32rpx;
}
.form-label.data-v-ebed24a8 {
font-size: 28rpx;
color: #666;
margin-bottom: 12rpx;
}
.form-input.data-v-ebed24a8 {
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-ebed24a8:focus {
border-color: #3366ff;
}
.checkbox.data-v-ebed24a8 {
display: flex;
align-items: center;
font-size: 26rpx;
color: #666;
}
.checkbox-box.data-v-ebed24a8 {
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-ebed24a8 {
background: #3366ff;
border-color: #3366ff;
}
.login-btn.data-v-ebed24a8 {
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-ebed24a8 {
font-size: 32rpx;
font-weight: 600;
color: #fff;
}
.login-btn.data-v-ebed24a8:active:not(.disabled) {
opacity: 0.9;
}
.login-btn.disabled.data-v-ebed24a8 {
opacity: 0.6;
}
.forgot-link.data-v-ebed24a8 {
text-align: center;
margin-top: 32rpx;
}
.forgot-link text.data-v-ebed24a8 {
font-size: 26rpx;
color: #3366ff;
}
+46
View File
@@ -0,0 +1,46 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "profile",
setup(__props) {
const orders = common_vendor.ref([]);
const todayCount = common_vendor.computed(() => {
const today = (/* @__PURE__ */ new Date()).toDateString();
return orders.value.filter((o) => new Date(o.timestamp).toDateString() === today).length;
});
const todayAmount = common_vendor.computed(() => {
const today = (/* @__PURE__ */ new Date()).toDateString();
return orders.value.filter((o) => new Date(o.timestamp).toDateString() === today).reduce((sum, o) => sum + o.totalAmount, 0);
});
const totalCount = common_vendor.computed(() => orders.value.length);
const goToPrice = () => {
common_vendor.index.navigateTo({ url: "/pages/price/price" });
};
const goToBluetooth = () => {
common_vendor.index.navigateTo({ url: "/pages/bluetooth/bluetooth" });
};
const showAbout = () => {
common_vendor.index.showModal({
title: "关于我们",
content: "易分宝现场回收 v1.0.0\n\n致力于为回收行业提供便捷的现场回收解决方案",
showCancel: false
});
};
common_vendor.onMounted(() => {
const data = common_vendor.index.getStorageSync("orders");
orders.value = data ? JSON.parse(data) : [];
});
return (_ctx, _cache) => {
return {
a: common_vendor.t(todayCount.value),
b: common_vendor.t(todayAmount.value.toFixed(2)),
c: common_vendor.t(totalCount.value),
d: common_vendor.o(goToPrice),
e: common_vendor.o(goToBluetooth),
f: common_vendor.o(showAbout)
};
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-f6b4f04d"]]);
wx.createPage(MiniProgramPage);
+6
View File
@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "个人中心",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="container data-v-f6b4f04d"><view class="user-card data-v-f6b4f04d"><view class="avatar data-v-f6b4f04d"><text class="avatar-icon data-v-f6b4f04d">👤</text></view><view class="user-info data-v-f6b4f04d"><text class="user-name data-v-f6b4f04d">回收员</text><text class="user-id data-v-f6b4f04d">ID: YFB20260514</text></view><view class="edit-btn data-v-f6b4f04d"><text class="data-v-f6b4f04d">✏️</text></view></view><view class="stats-card data-v-f6b4f04d"><view class="stat-item data-v-f6b4f04d"><text class="stat-value data-v-f6b4f04d">{{a}}</text><text class="stat-label data-v-f6b4f04d">今日订单</text></view><view class="stat-divider data-v-f6b4f04d"></view><view class="stat-item data-v-f6b4f04d"><text class="stat-value data-v-f6b4f04d">¥{{b}}</text><text class="stat-label data-v-f6b4f04d">今日收入</text></view><view class="stat-divider data-v-f6b4f04d"></view><view class="stat-item data-v-f6b4f04d"><text class="stat-value data-v-f6b4f04d">{{c}}</text><text class="stat-label data-v-f6b4f04d">累计订单</text></view></view><view class="menu-card data-v-f6b4f04d"><view class="menu-title data-v-f6b4f04d">功能菜单</view><view class="menu-list data-v-f6b4f04d"><view class="menu-item data-v-f6b4f04d" bindtap="{{d}}"><text class="menu-icon data-v-f6b4f04d">📊</text><text class="menu-text data-v-f6b4f04d">价格查询</text><text class="menu-arrow data-v-f6b4f04d"></text></view><view class="menu-item data-v-f6b4f04d" bindtap="{{e}}"><text class="menu-icon data-v-f6b4f04d">📱</text><text class="menu-text data-v-f6b4f04d">蓝牙设置</text><text class="menu-arrow data-v-f6b4f04d"></text></view><view class="menu-item data-v-f6b4f04d" bindtap="{{f}}"><text class="menu-icon data-v-f6b4f04d">️</text><text class="menu-text data-v-f6b4f04d">关于我们</text><text class="menu-arrow data-v-f6b4f04d"></text></view></view></view><view class="version-info data-v-f6b4f04d"><text class="version-text data-v-f6b4f04d">易分宝现场回?v1.0.0</text></view></view>
+130
View File
@@ -0,0 +1,130 @@
.container.data-v-f6b4f04d {
min-height: 100vh;
background: #f5f5f5;
padding: 32rpx;
}
.user-card.data-v-f6b4f04d {
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
border-radius: 20rpx;
padding: 32rpx;
display: flex;
align-items: center;
margin-bottom: 24rpx;
}
.avatar.data-v-f6b4f04d {
width: 100rpx;
height: 100rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
}
.avatar-icon.data-v-f6b4f04d {
font-size: 56rpx;
}
.user-info.data-v-f6b4f04d {
flex: 1;
display: flex;
flex-direction: column;
}
.user-name.data-v-f6b4f04d {
font-size: 36rpx;
font-weight: 600;
color: #fff;
margin-bottom: 8rpx;
}
.user-id.data-v-f6b4f04d {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
.edit-btn.data-v-f6b4f04d {
width: 60rpx;
height: 60rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 36rpx;
color: #fff;
}
.stats-card.data-v-f6b4f04d {
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
display: flex;
justify-content: space-around;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.stat-item.data-v-f6b4f04d {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.stat-value.data-v-f6b4f04d {
font-size: 48rpx;
font-weight: 700;
color: #3366ff;
margin-bottom: 8rpx;
}
.stat-label.data-v-f6b4f04d {
font-size: 24rpx;
color: #999;
}
.stat-divider.data-v-f6b4f04d {
width: 1rpx;
background: #f0f0f0;
}
.menu-card.data-v-f6b4f04d {
background: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.menu-title.data-v-f6b4f04d {
padding: 24rpx;
font-size: 30rpx;
font-weight: 600;
color: #333;
border-bottom: 1rpx solid #f0f0f0;
}
.menu-list.data-v-f6b4f04d {
padding: 0 24rpx;
}
.menu-item.data-v-f6b4f04d {
display: flex;
align-items: center;
padding: 28rpx 0;
border-bottom: 1rpx solid #f8f9fa;
}
.menu-item.data-v-f6b4f04d:last-child {
border-bottom: none;
}
.menu-item.data-v-f6b4f04d:active {
opacity: 0.7;
}
.menu-icon.data-v-f6b4f04d {
font-size: 40rpx;
margin-right: 20rpx;
}
.menu-text.data-v-f6b4f04d {
flex: 1;
font-size: 30rpx;
color: #333;
}
.menu-arrow.data-v-f6b4f04d {
font-size: 36rpx;
color: #ccc;
}
.version-info.data-v-f6b4f04d {
text-align: center;
padding: 48rpx;
}
.version-text.data-v-f6b4f04d {
font-size: 24rpx;
color: #999;
}
+177
View File
@@ -0,0 +1,177 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const stores_price = require("../../stores/price.js");
const stores_bluetooth = require("../../stores/bluetooth.js");
const stores_order = require("../../stores/order.js");
const stores_region = require("../../stores/region.js");
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
__name: "weigh",
setup(__props) {
const priceStore = stores_price.usePriceStore();
const bluetoothStore = stores_bluetooth.useBluetoothStore();
const orderStore = stores_order.useOrderStore();
const regionStore = stores_region.useRegionStore();
const category = common_vendor.ref("");
const currentWeight = common_vendor.ref(0);
const count = common_vendor.ref(0);
const countInput = common_vendor.ref("");
const inputMode = common_vendor.ref("bluetooth");
const manualWeight = common_vendor.ref("");
const currentPrice = common_vendor.computed(() => {
return priceStore.getPriceByCategory(category.value);
});
const estimatedAmount = common_vendor.computed(() => {
if (!currentPrice.value) return 0;
const value = currentPrice.value.unit === "kg" ? inputMode.value === "bluetooth" ? currentWeight.value : parseFloat(manualWeight.value) || 0 : count.value;
return Number((value * currentPrice.value.price).toFixed(2));
});
common_vendor.onLoad(async (options) => {
if (options == null ? void 0 : options.category) {
category.value = options.category;
}
await priceStore.loadPrices();
bluetoothStore.init();
});
const goToBluetooth = () => {
common_vendor.index.navigateTo({ url: "/pages/bluetooth/bluetooth" });
};
const resetWeight = () => {
bluetoothStore.resetWeight();
currentWeight.value = 0;
};
const decreaseCount = () => {
if (count.value > 0) {
count.value--;
countInput.value = count.value.toString();
}
};
const increaseCount = () => {
count.value++;
countInput.value = count.value.toString();
};
const onCountInput = () => {
const value = parseInt(countInput.value) || 0;
count.value = Math.max(0, value);
};
const quickCountInput = (num) => {
count.value += num;
countInput.value = count.value.toString();
};
const switchMode = (mode) => {
inputMode.value = mode;
if (mode === "manual") {
manualWeight.value = currentWeight.value > 0 ? currentWeight.value.toString() : "";
}
};
const onManualWeightInput = () => {
const value = parseFloat(manualWeight.value);
if (!isNaN(value) && value >= 0) {
currentWeight.value = value;
}
};
const quickInput = (weight) => {
const current = parseFloat(manualWeight.value) || 0;
manualWeight.value = (current + weight).toFixed(2);
onManualWeightInput();
};
const confirmRecycle = async () => {
if (!currentPrice.value) {
common_vendor.index.showToast({ title: "请选择回收种类", icon: "none" });
return;
}
const value = currentPrice.value.unit === "kg" ? inputMode.value === "bluetooth" ? currentWeight.value : parseFloat(manualWeight.value) || 0 : count.value;
if (value <= 0) {
common_vendor.index.showToast({ title: currentPrice.value.unit === "kg" ? "请输入重量" : "请输入数量", icon: "none" });
return;
}
const orderItem = {
category: currentPrice.value.category,
name: currentPrice.value.name,
weight: currentPrice.value.unit === "kg" ? value : void 0,
count: currentPrice.value.unit === "piece" ? count.value : void 0,
unit: currentPrice.value.unit,
price: currentPrice.value.price,
amount: estimatedAmount.value
};
common_vendor.index.showModal({
title: "确认回收",
content: `确定回收${currentPrice.value.name} ${value}${currentPrice.value.unit === "kg" ? "kg" : "个"},金额¥${estimatedAmount.value.toFixed(2)}`,
success: async (res) => {
if (res.confirm) {
common_vendor.index.showLoading({ title: "保存中..." });
const region = regionStore.getRegion();
const order = await orderStore.createOrder([orderItem], region);
common_vendor.index.hideLoading();
if (order) {
common_vendor.index.showToast({ title: "回收成功", icon: "success" });
setTimeout(() => {
common_vendor.index.navigateBack();
}, 1500);
} else {
common_vendor.index.showToast({ title: "保存失败", icon: "none" });
}
}
}
});
};
common_vendor.onMounted(() => {
const updateWeight = () => {
currentWeight.value = bluetoothStore.currentWeight;
};
bluetoothStore.$subscribe(() => {
updateWeight();
});
updateWeight();
});
common_vendor.onShow(() => {
priceStore.loadPrices();
});
return (_ctx, _cache) => {
var _a, _b, _c, _d, _e;
return common_vendor.e({
a: common_vendor.t(common_vendor.unref(bluetoothStore).isConnected ? "🔵" : "⚪"),
b: common_vendor.t(common_vendor.unref(bluetoothStore).isConnected ? "已连接" : "未连接"),
c: common_vendor.unref(bluetoothStore).isConnected ? 1 : "",
d: common_vendor.t(((_a = currentPrice.value) == null ? void 0 : _a.name) || "-"),
e: common_vendor.t(((_b = currentPrice.value) == null ? void 0 : _b.price) || 0),
f: common_vendor.t(((_c = currentPrice.value) == null ? void 0 : _c.unit) === "kg" ? "kg" : "个"),
g: ((_d = currentPrice.value) == null ? void 0 : _d.unit) === "kg"
}, ((_e = currentPrice.value) == null ? void 0 : _e.unit) === "kg" ? common_vendor.e({
h: inputMode.value === "bluetooth" ? 1 : "",
i: common_vendor.o(($event) => switchMode("bluetooth")),
j: inputMode.value === "manual" ? 1 : "",
k: common_vendor.o(($event) => switchMode("manual")),
l: inputMode.value === "bluetooth"
}, inputMode.value === "bluetooth" ? {
m: common_vendor.t(currentWeight.value.toFixed(2))
} : {
n: common_vendor.o([($event) => manualWeight.value = $event.detail.value, onManualWeightInput]),
o: manualWeight.value
}, {
p: inputMode.value === "bluetooth"
}, inputMode.value === "bluetooth" ? {
q: common_vendor.o(goToBluetooth),
r: common_vendor.o(resetWeight)
} : {
s: common_vendor.o(($event) => quickInput(0.5)),
t: common_vendor.o(($event) => quickInput(1)),
v: common_vendor.o(($event) => quickInput(2)),
w: common_vendor.o(($event) => quickInput(5))
}) : {
x: common_vendor.o([($event) => countInput.value = $event.detail.value, onCountInput]),
y: countInput.value,
z: common_vendor.o(decreaseCount),
A: common_vendor.o(increaseCount),
B: common_vendor.o(($event) => quickCountInput(1)),
C: common_vendor.o(($event) => quickCountInput(5)),
D: common_vendor.o(($event) => quickCountInput(10)),
E: common_vendor.o(($event) => quickCountInput(50))
}, {
F: common_vendor.t(estimatedAmount.value.toFixed(2)),
G: common_vendor.o(confirmRecycle)
});
};
}
});
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-6f825acf"]]);
wx.createPage(MiniProgramPage);
+6
View File
@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "称重回收",
"navigationBarBackgroundColor": "#3366ff",
"navigationBarTextStyle": "white",
"usingComponents": {}
}
+1
View File
@@ -0,0 +1 @@
<view class="container data-v-6f825acf"><view class="status-bar data-v-6f825acf"><view class="{{['bluetooth-status', 'data-v-6f825acf', c && 'connected']}}"><text class="status-icon data-v-6f825acf">{{a}}</text><text class="data-v-6f825acf">{{b}}</text></view></view><view class="info-card data-v-6f825acf"><view class="info-item data-v-6f825acf"><text class="info-label data-v-6f825acf">回收种类</text><text class="info-value data-v-6f825acf">{{d}}</text></view><view class="info-item data-v-6f825acf"><text class="info-label data-v-6f825acf">单价</text><text class="info-value price-text data-v-6f825acf">¥{{e}}/{{f}}</text></view></view><view wx:if="{{g}}" class="display-card data-v-6f825acf"><view class="display-icon data-v-6f825acf">📏</view><view class="display-title data-v-6f825acf">重量输入</view><view class="mode-switch data-v-6f825acf"><view class="{{['mode-btn', 'data-v-6f825acf', h && 'active']}}" bindtap="{{i}}"><text class="data-v-6f825acf">蓝牙称重</text></view><view class="{{['mode-btn', 'data-v-6f825acf', j && 'active']}}" bindtap="{{k}}"><text class="data-v-6f825acf">手动输入</text></view></view><view wx:if="{{l}}" class="display-value-wrap data-v-6f825acf"><text class="display-value data-v-6f825acf">{{m}}</text><text class="display-unit data-v-6f825acf">kg</text></view><view wx:else class="manual-input data-v-6f825acf"><input class="data-v-6f825acf" type="digit" placeholder="请输入重量" bindinput="{{n}}" value="{{o}}"/><text class="input-unit data-v-6f825acf">kg</text></view><view wx:if="{{p}}" class="control-row data-v-6f825acf"><view class="control-btn data-v-6f825acf" bindtap="{{q}}"><text class="control-icon data-v-6f825acf">📱</text><text class="data-v-6f825acf">蓝牙连接</text></view><view class="control-btn data-v-6f825acf" bindtap="{{r}}"><text class="control-icon data-v-6f825acf">⚖️</text><text class="data-v-6f825acf">归零</text></view></view><view wx:else class="quick-input data-v-6f825acf"><view class="quick-btn data-v-6f825acf" bindtap="{{s}}">+0.5kg</view><view class="quick-btn data-v-6f825acf" bindtap="{{t}}">+1kg</view><view class="quick-btn data-v-6f825acf" bindtap="{{v}}">+2kg</view><view class="quick-btn data-v-6f825acf" bindtap="{{w}}">+5kg</view></view></view><view wx:else class="display-card data-v-6f825acf"><view class="display-icon data-v-6f825acf">🥫</view><view class="display-title data-v-6f825acf">个数统计</view><view class="manual-input data-v-6f825acf"><input class="data-v-6f825acf" type="number" placeholder="请输入数量" bindinput="{{x}}" value="{{y}}"/><text class="input-unit data-v-6f825acf">个</text></view><view class="count-controls data-v-6f825acf"><view class="count-btn minus data-v-6f825acf" bindtap="{{z}}"><text class="data-v-6f825acf">-</text></view><view class="count-btn plus data-v-6f825acf" bindtap="{{A}}"><text class="data-v-6f825acf">+</text></view></view><view class="quick-input data-v-6f825acf"><view class="quick-btn data-v-6f825acf" bindtap="{{B}}">+1</view><view class="quick-btn data-v-6f825acf" bindtap="{{C}}">+5</view><view class="quick-btn data-v-6f825acf" bindtap="{{D}}">+10</view><view class="quick-btn data-v-6f825acf" bindtap="{{E}}">+50</view></view></view><view class="amount-card data-v-6f825acf"><view class="amount-title data-v-6f825acf">💰 预估金额</view><view class="amount-value-wrap data-v-6f825acf"><text class="amount-currency data-v-6f825acf">¥</text><text class="amount-num data-v-6f825acf">{{F}}</text></view></view><view class="confirm-btn data-v-6f825acf" bindtap="{{G}}"><text class="data-v-6f825acf">确认回收</text></view></view>
+336
View File
@@ -0,0 +1,336 @@
.container.data-v-6f825acf {
min-height: 100vh;
background: #f5f5f5;
padding: 24rpx;
}
.status-bar.data-v-6f825acf {
display: flex;
justify-content: flex-end;
align-items: center;
margin-bottom: 24rpx;
}
.bluetooth-status.data-v-6f825acf {
display: flex;
align-items: center;
font-size: 26rpx;
color: #999;
}
.bluetooth-status.connected.data-v-6f825acf {
color: #3366ff;
}
.status-icon.data-v-6f825acf {
margin-right: 8rpx;
}
.info-card.data-v-6f825acf {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 24rpx;
display: flex;
justify-content: space-between;
}
.info-item.data-v-6f825acf {
display: flex;
flex-direction: column;
align-items: center;
}
.info-label.data-v-6f825acf {
font-size: 24rpx;
color: #999;
margin-bottom: 8rpx;
}
.info-value.data-v-6f825acf {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.info-value.price-text.data-v-6f825acf {
color: #3366ff;
}
.display-card.data-v-6f825acf {
background: #fff;
border-radius: 16rpx;
padding: 48rpx 24rpx;
margin-bottom: 24rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.display-icon.data-v-6f825acf {
font-size: 64rpx;
margin-bottom: 16rpx;
}
.display-title.data-v-6f825acf {
font-size: 28rpx;
color: #999;
margin-bottom: 24rpx;
}
.display-value-wrap.data-v-6f825acf {
display: flex;
align-items: baseline;
margin-bottom: 32rpx;
}
.display-value.data-v-6f825acf {
font-size: 96rpx;
font-weight: 700;
color: #333;
}
.display-unit.data-v-6f825acf {
font-size: 32rpx;
color: #999;
margin-left: 8rpx;
}
.mode-switch.data-v-6f825acf {
display: flex;
background: #f5f5f5;
border-radius: 12rpx;
padding: 8rpx;
margin-bottom: 32rpx;
width: 100%;
}
.mode-btn.data-v-6f825acf {
flex: 1;
text-align: center;
padding: 16rpx;
font-size: 28rpx;
color: #666;
border-radius: 8rpx;
transition: all 0.3s;
}
.mode-btn.active.data-v-6f825acf {
background: #3366ff;
color: #fff;
font-weight: 600;
}
.manual-input.data-v-6f825acf {
display: flex;
align-items: center;
gap: 16rpx;
margin-bottom: 32rpx;
width: 100%;
padding: 0 24rpx;
}
.manual-input input.data-v-6f825acf {
flex: 1;
height: 80rpx;
border: 2rpx solid #e5e7eb;
border-radius: 12rpx;
padding: 0 24rpx;
font-size: 48rpx;
font-weight: 600;
color: #333;
text-align: center;
}
.input-unit.data-v-6f825acf {
font-size: 32rpx;
color: #999;
font-weight: 600;
}
.quick-input.data-v-6f825acf {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
justify-content: center;
}
.quick-btn.data-v-6f825acf {
padding: 16rpx 32rpx;
background: #f0fdf4;
border: 2rpx solid #3366ff;
border-radius: 24rpx;
font-size: 26rpx;
color: #3366ff;
font-weight: 600;
transition: all 0.2s;
}
.quick-btn.data-v-6f825acf:active {
background: #3366ff;
color: #fff;
}
.control-row.data-v-6f825acf {
display: flex;
gap: 32rpx;
}
.control-btn.data-v-6f825acf {
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx 48rpx;
background: #f5f5f5;
border-radius: 12rpx;
font-size: 24rpx;
color: #666;
}
.control-icon.data-v-6f825acf {
font-size: 36rpx;
margin-bottom: 8rpx;
}
.count-controls.data-v-6f825acf {
display: flex;
gap: 48rpx;
margin-bottom: 32rpx;
}
.count-btn.data-v-6f825acf {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 48rpx;
font-weight: 300;
}
.count-btn.minus.data-v-6f825acf {
background: #f87171;
color: #fff;
}
.count-btn.plus.data-v-6f825acf {
background: #3366ff;
color: #fff;
}
.amount-card.data-v-6f825acf {
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
border-radius: 16rpx;
padding: 32rpx;
margin-bottom: 32rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.amount-title.data-v-6f825acf {
font-size: 28rpx;
color: #92400e;
margin-bottom: 12rpx;
}
.amount-value-wrap.data-v-6f825acf {
display: flex;
align-items: baseline;
}
.amount-currency.data-v-6f825acf {
font-size: 36rpx;
font-weight: 600;
color: #f59e0b;
}
.amount-num.data-v-6f825acf {
font-size: 72rpx;
font-weight: 700;
color: #f59e0b;
margin-left: 8rpx;
}
.region-card.data-v-6f825acf {
background: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 32rpx;
}
.region-title.data-v-6f825acf {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
}
.region-row.data-v-6f825acf {
margin-bottom: 16rpx;
}
.region-item.data-v-6f825acf {
display: flex;
align-items: center;
justify-content: space-between;
}
.region-label.data-v-6f825acf {
font-size: 26rpx;
color: #999;
width: 120rpx;
}
.region-select.data-v-6f825acf {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 24rpx;
background: #f8fafc;
border-radius: 12rpx;
font-size: 28rpx;
color: #333;
}
.region-select.disabled.data-v-6f825acf {
color: #ccc;
background: #f0f0f0;
}
.arrow.data-v-6f825acf {
font-size: 20rpx;
color: #999;
margin-left: 16rpx;
}
.custom-region.data-v-6f825acf {
margin-top: 20rpx;
padding-top: 20rpx;
border-top: 1rpx solid #f0f0f0;
}
.region-input.data-v-6f825acf {
flex: 1;
padding: 20rpx 24rpx;
background: #f8fafc;
border-radius: 12rpx;
font-size: 28rpx;
margin-left: 16rpx;
}
.picker-overlay.data-v-6f825acf {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: flex-end;
}
.picker-content.data-v-6f825acf {
width: 100%;
background: #fff;
border-radius: 24rpx 24rpx 0 0;
max-height: 70vh;
}
.picker-header.data-v-6f825acf {
display: flex;
align-items: center;
justify-content: space-between;
padding: 28rpx 32rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.picker-title.data-v-6f825acf {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.picker-close.data-v-6f825acf {
font-size: 32rpx;
color: #999;
padding: 8rpx;
}
.picker-list.data-v-6f825acf {
max-height: 60vh;
}
.picker-item.data-v-6f825acf {
padding: 28rpx 32rpx;
font-size: 30rpx;
color: #333;
border-bottom: 1rpx solid #f8fafc;
}
.picker-item.active.data-v-6f825acf {
color: #3366ff;
font-weight: 600;
}
.confirm-btn.data-v-6f825acf {
background: linear-gradient(135deg, #3366ff 0%, #254edb 100%);
border-radius: 48rpx;
padding: 32rpx;
text-align: center;
font-size: 34rpx;
font-weight: 600;
color: #fff;
box-shadow: 0 8rpx 24rpx rgba(16, 185, 129, 0.3);
}
.confirm-btn.data-v-6f825acf:active {
opacity: 0.85;
}
+36
View File
@@ -0,0 +1,36 @@
{
"description": "项目配置文件。",
"packOptions": {
"ignore": []
},
"setting": {
"urlCheck": false,
"es6": true,
"postcss": false,
"minified": false,
"newFeature": true,
"bigPackageSizeSupport": true
},
"compileType": "miniprogram",
"libVersion": "",
"appid": "wx0000000000000000",
"projectname": "易分宝现场回收",
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+70
View File
@@ -0,0 +1,70 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const utils_bluetooth = require("../utils/bluetooth.js");
const useBluetoothStore = common_vendor.defineStore("bluetooth", () => {
const isConnected = common_vendor.ref(false);
const isDiscovering = common_vendor.ref(false);
const deviceList = common_vendor.ref([]);
const connectedDevice = common_vendor.ref(null);
const currentWeight = common_vendor.ref(0);
const init = async () => {
try {
await utils_bluetooth.initBluetooth();
} catch (error) {
console.error("Bluetooth init failed:", error);
}
};
const startScan = async () => {
isDiscovering.value = true;
deviceList.value = [];
await utils_bluetooth.startDiscovery((devices) => {
deviceList.value = devices;
});
};
const stopScan = () => {
isDiscovering.value = false;
utils_bluetooth.stopDiscovery();
};
const connect = async (deviceId) => {
try {
await utils_bluetooth.connectDevice(deviceId);
const device = deviceList.value.find((d) => d.deviceId === deviceId);
if (device) {
connectedDevice.value = device;
isConnected.value = true;
}
utils_bluetooth.listenWeightData((weight) => {
currentWeight.value = weight;
});
} catch (error) {
console.error("Connect failed:", error);
}
};
const disconnect = async () => {
try {
await utils_bluetooth.disconnectDevice();
isConnected.value = false;
connectedDevice.value = null;
currentWeight.value = 0;
} catch (error) {
console.error("Disconnect failed:", error);
}
};
const resetWeight = () => {
currentWeight.value = 0;
};
return {
isConnected,
isDiscovering,
deviceList,
connectedDevice,
currentWeight,
init,
startScan,
stopScan,
connect,
disconnect,
resetWeight
};
});
exports.useBluetoothStore = useBluetoothStore;
+82
View File
@@ -0,0 +1,82 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const api_index = require("../api/index.js");
const useOrderStore = common_vendor.defineStore("order", () => {
const orders = common_vendor.ref([]);
const currentOrderItems = common_vendor.ref([]);
const loadOrders = async () => {
try {
orders.value = await api_index.orderApi.getOrders();
} catch (error) {
console.error("Failed to load orders:", error);
}
};
const addOrderItem = (item) => {
currentOrderItems.value.push(item);
};
const clearCurrentItems = () => {
currentOrderItems.value = [];
};
const createOrder = async (items, region) => {
try {
const totalAmount = items.reduce((sum, item) => sum + (item.amount || 0), 0);
const order = {
id: "",
items,
totalAmount,
createTime: (/* @__PURE__ */ new Date()).toISOString(),
status: "pending",
city: region == null ? void 0 : region.city,
district: region == null ? void 0 : region.district,
community: region == null ? void 0 : region.community
};
const createdOrder = await api_index.orderApi.addOrder(order);
if (createdOrder) {
await loadOrders();
return createdOrder;
}
return null;
} catch (error) {
console.error("Failed to create order:", error);
return null;
}
};
const updateOrder = async (order) => {
try {
await api_index.orderApi.updateOrder(order);
await loadOrders();
} catch (error) {
console.error("Failed to update order:", error);
}
};
const deleteOrder = async (id) => {
try {
await api_index.orderApi.deleteOrder(id);
await loadOrders();
} catch (error) {
console.error("Failed to delete order:", error);
}
};
const getOrder = async (orderId) => {
await loadOrders();
return orders.value.find((o) => o.id === orderId) || null;
};
const getTotalAmount = () => {
return currentOrderItems.value.reduce((sum, item) => {
return sum + (item.amount || 0);
}, 0);
};
return {
orders,
currentOrderItems,
loadOrders,
addOrderItem,
clearCurrentItems,
createOrder,
updateOrder,
deleteOrder,
getOrder,
getTotalAmount
};
});
exports.useOrderStore = useOrderStore;
+59
View File
@@ -0,0 +1,59 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const api_index = require("../api/index.js");
const usePriceStore = common_vendor.defineStore("price", () => {
const prices = common_vendor.ref([]);
const date = common_vendor.ref("");
const isLoading = common_vendor.ref(false);
const loadPrices = async () => {
isLoading.value = true;
try {
const data = await api_index.priceApi.getPrices();
if (data) {
prices.value = data.prices;
date.value = data.date;
}
} catch (error) {
console.error("Failed to load prices:", error);
}
isLoading.value = false;
};
const getPriceByCategory = (category) => {
return prices.value.find((p) => p.category === category);
};
const addPrice = async (priceItem) => {
try {
await api_index.priceApi.addPrice(priceItem);
await loadPrices();
} catch (error) {
console.error("Failed to add price:", error);
}
};
const updatePrice = async (priceItem, originalCategory) => {
try {
await api_index.priceApi.updatePrice(priceItem, originalCategory);
await loadPrices();
} catch (error) {
console.error("Failed to update price:", error);
}
};
const deletePrice = async (category) => {
try {
await api_index.priceApi.deletePrice(category);
await loadPrices();
} catch (error) {
console.error("Failed to delete price:", error);
}
};
return {
prices,
date,
isLoading,
loadPrices,
getPriceByCategory,
addPrice,
updatePrice,
deletePrice
};
});
exports.usePriceStore = usePriceStore;
+80
View File
@@ -0,0 +1,80 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const useRegionStore = common_vendor.defineStore("region", () => {
const selectedCity = common_vendor.ref("天津市");
const selectedDistrict = common_vendor.ref("");
const selectedCommunity = common_vendor.ref("");
const selectedUser = common_vendor.ref("");
const customDistrict = common_vendor.ref("");
const customCommunity = common_vendor.ref("");
const customUser = common_vendor.ref("");
const setCity = (city) => {
selectedCity.value = city;
selectedDistrict.value = "";
selectedCommunity.value = "";
selectedUser.value = "";
customDistrict.value = "";
customCommunity.value = "";
customUser.value = "";
};
const setDistrict = (district) => {
selectedDistrict.value = district;
selectedCommunity.value = "";
selectedUser.value = "";
customCommunity.value = "";
customUser.value = "";
};
const setCommunity = (community) => {
selectedCommunity.value = community;
selectedUser.value = "";
customUser.value = "";
};
const setUser = (user) => {
selectedUser.value = user;
};
const setCustomDistrict = (district) => {
customDistrict.value = district;
};
const setCustomCommunity = (community) => {
customCommunity.value = community;
};
const setCustomUser = (user) => {
customUser.value = user;
};
const getRegion = () => {
return {
city: selectedCity.value || void 0,
district: selectedDistrict.value === "其他" ? customDistrict.value || void 0 : selectedDistrict.value || void 0,
community: selectedCommunity.value === "其他" ? customCommunity.value || void 0 : selectedCommunity.value || void 0,
user: selectedUser.value === "其他" ? customUser.value || void 0 : selectedUser.value || void 0
};
};
const clearRegion = () => {
selectedCity.value = "天津市";
selectedDistrict.value = "";
selectedCommunity.value = "";
selectedUser.value = "";
customDistrict.value = "";
customCommunity.value = "";
customUser.value = "";
};
return {
selectedCity,
selectedDistrict,
selectedCommunity,
selectedUser,
customDistrict,
customCommunity,
customUser,
setCity,
setDistrict,
setCommunity,
setUser,
setCustomDistrict,
setCustomCommunity,
setCustomUser,
getRegion,
clearRegion
};
});
exports.useRegionStore = useRegionStore;
+54
View File
@@ -0,0 +1,54 @@
"use strict";
const common_vendor = require("../common/vendor.js");
const api_index = require("../api/index.js");
const useUserStore = common_vendor.defineStore("user", () => {
const users = common_vendor.ref([]);
const isLoading = common_vendor.ref(false);
const loadUsers = async () => {
isLoading.value = true;
try {
const data = await api_index.userApi.getUsers();
users.value = data;
} catch (error) {
console.error("Failed to load users:", error);
}
isLoading.value = false;
};
const addUser = async (user) => {
try {
await api_index.userApi.addUser(user);
await loadUsers();
} catch (error) {
console.error("Failed to add user:", error);
}
};
const updateUser = async (user) => {
try {
await api_index.userApi.updateUser(user);
await loadUsers();
} catch (error) {
console.error("Failed to update user:", error);
}
};
const deleteUser = async (id) => {
try {
await api_index.userApi.deleteUser(id);
await loadUsers();
} catch (error) {
console.error("Failed to delete user:", error);
}
};
const getUserById = (id) => {
return users.value.find((u) => u.id === id);
};
return {
users,
isLoading,
loadUsers,
addUser,
updateUser,
deleteUser,
getUserById
};
});
exports.useUserStore = useUserStore;
+451
View File
@@ -0,0 +1,451 @@
"use strict";
const common_vendor = require("../common/vendor.js");
let deviceId = "";
let serviceId = "";
let characteristicId = "";
let writeCharacteristicId = "";
let weightCallback = null;
const initBluetooth = () => {
return new Promise((resolve, reject) => {
common_vendor.index.openBluetoothAdapter({
success: () => {
console.log("Bluetooth adapter initialized");
resolve();
},
fail: (err) => {
console.error("Bluetooth init failed:", err);
reject(err);
}
});
});
};
const startDiscovery = (callback) => {
return new Promise((resolve) => {
const foundDevices = [];
common_vendor.index.startBluetoothDevicesDiscovery({
services: [],
success: () => {
console.log("Started discovery");
common_vendor.index.onBluetoothDeviceFound((res) => {
const devices = res.devices.filter((d) => d.name && (d.name.includes("Scale") || d.name.includes("秤") || d.name.includes("WXL")));
devices.forEach((device) => {
if (!foundDevices.find((d) => d.deviceId === device.deviceId)) {
foundDevices.push({
deviceId: device.deviceId,
name: device.name,
RSSI: device.RSSI || 0
});
}
});
callback([...foundDevices]);
});
setTimeout(() => {
common_vendor.index.stopBluetoothDevicesDiscovery();
resolve();
}, 1e4);
}
});
});
};
const stopDiscovery = () => {
common_vendor.index.stopBluetoothDevicesDiscovery();
};
const connectDevice = (deviceIdParam) => {
return new Promise((resolve, reject) => {
deviceId = deviceIdParam;
common_vendor.index.createBLEConnection({
deviceId: deviceIdParam,
success: () => {
console.log("Connected to device:", deviceIdParam);
getBLEDeviceServices(deviceIdParam).then(() => resolve()).catch(reject);
},
fail: (err) => {
console.error("Connection failed:", err);
reject(err);
}
});
});
};
const getBLEDeviceServices = (deviceIdParam) => {
return new Promise((resolve, reject) => {
common_vendor.index.getBLEDeviceServices({
deviceId: deviceIdParam,
success: (res) => {
console.log("=== Available Services ===");
res.services.forEach((s, i) => {
console.log(`${i + 1}. UUID: ${s.uuid}, Primary: ${s.isPrimary}`);
});
const commonServiceUUIDs = [
"0000FFE0",
"0000ffe0",
"0000180a",
"00001800",
"0000ffe5",
"0000fff0",
"fff0",
"0000ffe3",
"ffe3",
"0000ffe1",
"ffe1"
];
let foundService = res.services.find(
(s) => commonServiceUUIDs.some((uuid) => s.uuid.toLowerCase().startsWith(uuid.toLowerCase()))
);
if (!foundService && res.services.length > 0) {
foundService = res.services.find((s) => s.isPrimary) || res.services.find((s) => s.uuid.length === 4 || s.uuid.length === 8) || res.services[0];
console.log("Using fallback service:", foundService.uuid);
}
if (foundService) {
serviceId = foundService.uuid;
console.log("Selected service:", serviceId);
getBLEDeviceCharacteristics(deviceIdParam, foundService.uuid).then(() => resolve()).catch(reject);
} else {
reject(new Error("Service not found"));
}
},
fail: reject
});
});
};
const getBLEDeviceCharacteristics = (deviceIdParam, serviceIdParam) => {
return new Promise((resolve, reject) => {
common_vendor.index.getBLEDeviceCharacteristics({
deviceId: deviceIdParam,
serviceId: serviceIdParam,
success: (res) => {
console.log("=== Available Characteristics ===");
res.characteristics.forEach((c, i) => {
console.log(`${i + 1}. UUID: ${c.uuid}`);
console.log(` - Properties: notify=${c.properties.notify}, read=${c.properties.read}, write=${c.properties.write}, writeWithoutResponse=${c.properties.writeWithoutResponse}`);
});
const commonCharUUIDs = [
"0000FFE1",
"0000ffe1",
"0000ffe2",
"0000ffe4",
"0000fff1",
"fff1",
"0000ffe3",
"ffe3",
"00002a00",
"00002a01",
"00002a04",
"00002a05"
];
let characteristic = res.characteristics.find(
(c) => commonCharUUIDs.some((uuid) => c.uuid.toLowerCase().startsWith(uuid.toLowerCase())) && (c.properties.notify || c.properties.read)
);
const writeChar = res.characteristics.find((c) => c.properties.write || c.properties.writeWithoutResponse);
if (writeChar) {
writeCharacteristicId = writeChar.uuid;
console.log("Found write characteristic:", writeCharacteristicId);
}
if (!characteristic) {
characteristic = res.characteristics.find((c) => c.properties.notify);
}
if (!characteristic) {
characteristic = res.characteristics.find((c) => c.properties.read);
}
if (!characteristic && res.characteristics.length > 0) {
characteristic = res.characteristics.find((c) => c.uuid.length === 4 || c.uuid.length === 8) || res.characteristics[0];
console.log("Using fallback characteristic:", characteristic.uuid);
}
if (characteristic) {
characteristicId = characteristic.uuid;
console.log("Selected characteristic for read/notify:", characteristicId);
console.log("Properties:", characteristic.properties);
sendInitCommands(deviceIdParam, serviceIdParam);
if (characteristic.properties.notify) {
notifyBLECharacteristicValueChange(deviceIdParam, serviceIdParam, characteristic.uuid).then(() => resolve()).catch(reject);
} else if (characteristic.properties.read) {
readBLECharacteristicValue(deviceIdParam, serviceIdParam, characteristic.uuid).then(() => {
setupPeriodicRead(deviceIdParam, serviceIdParam, characteristic.uuid);
resolve();
}).catch(reject);
} else {
resolve();
}
} else {
reject(new Error("Characteristic not found"));
}
},
fail: reject
});
});
};
const sendInitCommands = (deviceIdParam, serviceIdParam) => {
if (!writeCharacteristicId) {
console.log("No write characteristic found, skipping init commands");
return;
}
const initCommands = [
stringToBuffer("START"),
stringToBuffer("ON"),
stringToBuffer("WEIGH"),
stringToBuffer("GET"),
stringToBuffer("1"),
new Uint8Array([1]).buffer,
new Uint8Array([2]).buffer,
new Uint8Array([3]).buffer,
new Uint8Array([85]).buffer,
new Uint8Array([170, 85]).buffer,
new Uint8Array([254, 1]).buffer,
new Uint8Array([255, 1]).buffer,
new Uint8Array([0, 0, 0, 1]).buffer
];
initCommands.forEach((cmd, index) => {
setTimeout(() => {
writeBLECharacteristicValue(deviceIdParam, serviceIdParam, writeCharacteristicId, cmd);
}, index * 200);
});
};
const writeBLECharacteristicValue = (deviceIdParam, serviceIdParam, characteristicIdParam, value) => {
common_vendor.index.writeBLECharacteristicValue({
deviceId: deviceIdParam,
serviceId: serviceIdParam,
characteristicId: characteristicIdParam,
value,
success: () => {
console.log("Wrote command:", arrayBufferToHex(value));
},
fail: (err) => {
console.log("Write failed (may be normal for read-only chars):", err.errMsg);
}
});
};
const stringToBuffer = (str) => {
const encoder = new TextEncoder();
return encoder.encode(str).buffer;
};
let readInterval = null;
const setupPeriodicRead = (deviceIdParam, serviceIdParam, characteristicIdParam) => {
if (readInterval) {
clearInterval(readInterval);
}
readInterval = setInterval(() => {
common_vendor.index.readBLECharacteristicValue({
deviceId: deviceIdParam,
serviceId: serviceIdParam,
characteristicId: characteristicIdParam,
success: (res) => {
handleBLEData(res.value);
},
fail: (err) => {
console.log("Periodic read failed:", err.errMsg);
}
});
}, 300);
console.log("Started periodic read every 300ms");
};
const notifyBLECharacteristicValueChange = (deviceIdParam, serviceIdParam, characteristicIdParam) => {
return new Promise((resolve, reject) => {
common_vendor.index.notifyBLECharacteristicValueChange({
deviceId: deviceIdParam,
serviceId: serviceIdParam,
characteristicId: characteristicIdParam,
state: true,
success: () => {
console.log("Notify enabled for:", characteristicIdParam);
resolve();
},
fail: (err) => {
console.log("Notify failed, trying read mode:", err.errMsg);
readBLECharacteristicValue(deviceIdParam, serviceIdParam, characteristicIdParam).then(() => {
setupPeriodicRead(deviceIdParam, serviceIdParam, characteristicIdParam);
resolve();
}).catch(reject);
}
});
});
};
const readBLECharacteristicValue = (deviceIdParam, serviceIdParam, characteristicIdParam) => {
return new Promise((resolve, reject) => {
common_vendor.index.readBLECharacteristicValue({
deviceId: deviceIdParam,
serviceId: serviceIdParam,
characteristicId: characteristicIdParam,
success: (res) => {
console.log("Read characteristic value received");
handleBLEData(res.value);
resolve();
},
fail: (err) => {
console.error("Read failed:", err);
reject(err);
}
});
});
};
const handleBLEData = (value) => {
console.log("=== BLE Data Received ===");
console.log("Data length:", value.byteLength, "bytes");
console.log("Hex:", arrayBufferToHex(value));
const asciiData = arrayBufferToString(value);
console.log("ASCII:", JSON.stringify(asciiData));
const weight = parseWeightData(value);
console.log("Parsed weight:", weight, "kg");
if (weight > 0 && weight < 1e3 && weightCallback) {
weightCallback(weight);
console.log("Weight sent to callback:", weight);
}
};
const listenWeightData = (callback) => {
weightCallback = callback;
console.log("Weight callback registered");
common_vendor.index.onBLECharacteristicValueChange((res) => {
console.log("BLE characteristic value changed event");
handleBLEData(res.value);
});
};
const parseWeightData = (buffer) => {
if (buffer.byteLength === 0) {
console.log("Empty buffer received");
return 0;
}
const dataView = new DataView(buffer);
const asciiData = arrayBufferToString(buffer);
const cleaned = asciiData.replace(/[\r\n\s\x00-\x1F]+/g, "");
console.log("Cleaned ASCII:", JSON.stringify(cleaned));
const textPatterns = [
/[+-]?\d+\.\d{1,3}\s*[kK][gG]?/,
/[+-]?\d+\.\d{1,3}/,
/[+-]?\d+\,\d{1,3}/,
/[+-]?\d+\.?\d*/
];
for (const pattern of textPatterns) {
const match = cleaned.match(pattern);
if (match) {
const numStr = match[0].replace(",", ".").replace(/[^0-9.-]/g, "");
const weight = parseFloat(numStr);
if (!isNaN(weight) && weight > 0 && weight < 1e3) {
console.log("Parsed from text:", weight);
return weight;
}
}
}
if (buffer.byteLength >= 2) {
const testValues = [];
if (buffer.byteLength >= 4) {
testValues.push(dataView.getInt32(0, true) / 1e3);
testValues.push(dataView.getInt32(0, false) / 1e3);
testValues.push(dataView.getFloat32(0, true));
testValues.push(dataView.getFloat32(0, false));
testValues.push(dataView.getUint32(0, true) / 1e3);
testValues.push(dataView.getUint32(0, false) / 1e3);
}
if (buffer.byteLength >= 2) {
testValues.push(dataView.getInt16(0, true) / 10);
testValues.push(dataView.getInt16(0, false) / 10);
testValues.push(dataView.getUint16(0, true) / 10);
testValues.push(dataView.getUint16(0, false) / 10);
testValues.push(dataView.getInt16(0, true) / 100);
testValues.push(dataView.getInt16(0, false) / 100);
testValues.push(dataView.getInt16(0, true) / 1e3);
testValues.push(dataView.getInt16(0, false) / 1e3);
}
if (buffer.byteLength >= 3) {
const byte1 = dataView.getUint8(0);
const byte2 = dataView.getUint8(1);
const byte3 = dataView.getUint8(2);
testValues.push((byte1 << 16 | byte2 << 8 | byte3) / 1e3);
testValues.push((byte3 << 16 | byte2 << 8 | byte1) / 1e3);
testValues.push((byte2 << 16 | byte1 << 8 | byte3) / 1e3);
}
console.log("Testing binary values:", testValues.filter((v) => v > 0 && v < 1e3));
for (const value of testValues) {
if (value > 0 && value < 1e3 && !isNaN(value)) {
console.log("Parsed from binary:", value);
return value;
}
}
}
if (buffer.byteLength >= 4) {
const bytes = new Uint8Array(buffer);
let bcdValue = "";
for (let i = 0; i < bytes.length; i++) {
const high = bytes[i] >> 4 & 15;
const low = bytes[i] & 15;
if (high >= 0 && high <= 9) bcdValue += high.toString();
if (low >= 0 && low <= 9) bcdValue += low.toString();
}
console.log("BCD value:", bcdValue);
if (bcdValue.length >= 1) {
let weight = parseFloat(bcdValue) / 1e3;
if (weight > 0 && weight < 1e3) {
console.log("Parsed from BCD:", weight);
return weight;
}
const dotIndex = bcdValue.length - 3;
if (dotIndex > 0) {
const formatted = bcdValue.slice(0, dotIndex) + "." + bcdValue.slice(dotIndex);
weight = parseFloat(formatted);
if (weight > 0 && weight < 1e3) {
console.log("Parsed from BCD with decimal:", weight);
return weight;
}
}
}
}
console.log("No valid weight found, returning 0");
return 0;
};
const arrayBufferToString = (buffer) => {
try {
const bytes = new Uint8Array(buffer);
let result = "";
for (let i = 0; i < bytes.length; i++) {
if (bytes[i] >= 32 && bytes[i] <= 126) {
result += String.fromCharCode(bytes[i]);
} else if (bytes[i] === 10 || bytes[i] === 13) {
result += bytes[i] === 10 ? "\n" : "\r";
}
}
return result;
} catch {
return "";
}
};
const arrayBufferToHex = (buffer) => {
const bytes = new Uint8Array(buffer);
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join(" ");
};
const disconnectDevice = () => {
return new Promise((resolve, reject) => {
if (readInterval) {
clearInterval(readInterval);
readInterval = null;
console.log("Stopped periodic read");
}
if (!deviceId) {
resolve();
return;
}
common_vendor.index.closeBLEConnection({
deviceId,
success: () => {
console.log("Disconnected successfully");
deviceId = "";
serviceId = "";
characteristicId = "";
writeCharacteristicId = "";
weightCallback = null;
resolve();
},
fail: (err) => {
console.log("Disconnect failed but clearing state:", err.errMsg);
deviceId = "";
serviceId = "";
characteristicId = "";
writeCharacteristicId = "";
weightCallback = null;
resolve();
}
});
});
};
exports.connectDevice = connectDevice;
exports.disconnectDevice = disconnectDevice;
exports.initBluetooth = initBluetooth;
exports.listenWeightData = listenWeightData;
exports.startDiscovery = startDiscovery;
exports.stopDiscovery = stopDiscovery;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
const formatOrderTime = (dateStr) => {
const date = new Date(dateStr);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}`;
};
exports.formatOrderTime = formatOrderTime;
+21
View File
@@ -0,0 +1,21 @@
"use strict";
require("../common/vendor.js");
({
date: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
});
const getCategoryIcon = (category) => {
const icons = {
"001": "file-text",
"002": "wrench",
"003": "bottle",
"004": "refresh",
"005": "shirt"
};
const allIcons = ["package", "file-text", "wrench", "bottle", "refresh", "shirt", "phone", "battery", "monitor", "sofa", "bag", "footprints", "book", "wine", "medicine"];
if (icons[category]) {
return icons[category];
}
const num = parseInt(category) || category.length;
return allIcons[num % allIcons.length];
};
exports.getCategoryIcon = getCategoryIcon;