9.18王德鹏/1

This commit is contained in:
2025-09-18 14:22:04 +08:00
parent a8dcee7296
commit 335e21347b
90 changed files with 1618 additions and 1346 deletions

View File

@@ -1,133 +1,184 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_http = require("../../common/http.js");
function toDateString(d) {
const m = (d.getMonth() + 1).toString().padStart(2, "0");
const day = d.getDate().toString().padStart(2, "0");
return `${d.getFullYear()}-${m}-${day}`;
}
const API_OF = {
sale: "/api/orders",
purchase: "/api/purchase-orders",
collect: "/api/payments",
fund: "/api/other-transactions",
stock: "/api/inventories/logs"
};
const _sfc_main = {
data() {
const today = /* @__PURE__ */ new Date();
const first = new Date(today.getFullYear(), today.getMonth(), 1);
return {
range: "month",
biz: "sale",
sub: "out",
kw: "",
begin: toDateString(first),
end: toDateString(today),
list: [],
loading: false
bizList: [
{ key: "sale", name: "出货" },
{ key: "purchase", name: "进货" },
{ key: "collect", name: "收款" },
{ key: "fund", name: "资金" },
{ key: "stock", name: "盘点" }
],
range: "month",
query: { kw: "" },
items: [],
page: 1,
size: 20,
finished: false,
loading: false,
startDate: "",
endDate: ""
};
},
computed: {
placeholder() {
return "单据号/客户名称/品名规格/备注";
},
periodLabel() {
return this.startDate && this.endDate ? `${this.startDate}~${this.endDate}` : "";
},
totalAmount() {
return this.list.reduce((s, o) => s + Number(o.amount || 0), 0);
return this.items.reduce((s, it) => s + Number(it.amount || 0), 0);
}
},
onLoad() {
try {
common_vendor.index.__f__("log", "at pages/detail/index.vue:92", "[detail] onLoad route = pages/detail/index");
} catch (e) {
}
this.computeRange();
this.reload();
},
methods: {
setRange(r) {
this.range = r;
const now = /* @__PURE__ */ new Date();
if (r === "today") {
this.begin = this.end = toDateString(now);
} else if (r === "week") {
const day = now.getDay() || 7;
const start = new Date(now);
start.setDate(now.getDate() - day + 1);
this.begin = toDateString(start);
this.end = toDateString(now);
} else if (r === "month") {
const first = new Date(now.getFullYear(), now.getMonth(), 1);
this.begin = toDateString(first);
this.end = toDateString(now);
} else if (r === "year") {
const first = new Date(now.getFullYear(), 0, 1);
this.begin = toDateString(first);
this.end = toDateString(now);
}
switchBiz(k) {
if (this.biz === k)
return;
this.biz = k;
this.reload();
},
async reload() {
switchRange(r) {
this.range = r;
this.computeRange();
this.reload();
},
computeRange() {
const now = /* @__PURE__ */ new Date();
const pad = (n) => String(n).padStart(2, "0");
const fmt = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
let start = now, end = now;
if (this.range === "today") {
start = end = now;
} else if (this.range === "week") {
const day = now.getDay() || 7;
start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - day + 1);
end = now;
} else if (this.range === "month") {
start = new Date(now.getFullYear(), now.getMonth(), 1);
end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
} else if (this.range === "year") {
start = new Date(now.getFullYear(), 0, 1);
end = new Date(now.getFullYear(), 11, 31);
} else {
start = new Date(now.getFullYear(), now.getMonth(), 1);
end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
}
this.startDate = fmt(start);
this.endDate = fmt(end);
},
reload() {
this.items = [];
this.page = 1;
this.finished = false;
this.loadMore();
},
async loadMore() {
if (this.loading || this.finished)
return;
this.loading = true;
try {
const res = await common_http.get("/api/sales/orders", { begin: this.begin, end: this.end, kw: this.kw, sub: this.sub });
this.list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
const path = API_OF[this.biz] || "/api/orders";
const params = { kw: this.query.kw, page: this.page, size: this.size, startDate: this.startDate, endDate: this.endDate, biz: this.biz };
if (this.biz === "sale")
params.type = "out";
const res = await common_http.get(path, params);
const list = Array.isArray(res == null ? void 0 : res.list) ? res.list : Array.isArray(res) ? res : [];
this.items = this.items.concat(list);
if (list.length < this.size)
this.finished = true;
this.page += 1;
} catch (e) {
this.list = [];
common_vendor.index.showToast({ title: "加载失败", icon: "none" });
} finally {
this.loading = false;
}
},
goCreate() {
common_vendor.index.navigateTo({ url: "/pages/order/create" });
formatDate(s) {
if (!s)
return "";
try {
const d = new Date(s);
const pad = (n) => String(n).padStart(2, "0");
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
} catch (_) {
return String(s).slice(0, 10);
}
},
open(o) {
onCreate() {
if (this.biz === "sale") {
common_vendor.index.navigateTo({ url: "/pages/order/create" });
return;
}
common_vendor.index.showToast({ title: "该类型创建页待实现", icon: "none" });
},
openDetail(it) {
common_vendor.index.showToast({ title: "详情开发中", icon: "none" });
}
}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return common_vendor.e({
a: $data.range === "custom" ? 1 : "",
b: common_vendor.o(($event) => $options.setRange("custom")),
c: $data.range === "week" ? 1 : "",
d: common_vendor.o(($event) => $options.setRange("week")),
e: $data.range === "today" ? 1 : "",
f: common_vendor.o(($event) => $options.setRange("today")),
g: $data.range === "month" ? 1 : "",
h: common_vendor.o(($event) => $options.setRange("month")),
i: $data.range === "year" ? 1 : "",
j: common_vendor.o(($event) => $options.setRange("year")),
k: $data.biz === "sale" ? 1 : "",
l: common_vendor.o(($event) => $data.biz = "sale"),
m: $data.biz === "purchase" ? 1 : "",
n: common_vendor.o(($event) => $data.biz = "purchase"),
o: $data.biz === "collection" ? 1 : "",
p: common_vendor.o(($event) => $data.biz = "collection"),
q: $data.biz === "capital" ? 1 : "",
r: common_vendor.o(($event) => $data.biz = "capital"),
s: $data.biz === "inventory" ? 1 : "",
t: common_vendor.o(($event) => $data.biz = "inventory"),
v: $data.sub === "out" ? 1 : "",
w: common_vendor.o(($event) => $data.sub = "out"),
x: $data.sub === "return" ? 1 : "",
y: common_vendor.o(($event) => $data.sub = "return"),
z: $data.sub === "receive" ? 1 : "",
A: common_vendor.o(($event) => $data.sub = "receive"),
B: common_vendor.o((...args) => $options.goCreate && $options.goCreate(...args)),
C: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
D: $data.kw,
E: common_vendor.o(($event) => $data.kw = $event.detail.value),
F: $data.range === "custom"
}, $data.range === "custom" ? {
G: common_vendor.t($data.begin),
H: $data.begin,
I: common_vendor.o((e) => {
$data.begin = e.detail.value;
$options.reload();
}),
J: common_vendor.t($data.end),
K: $data.end,
L: common_vendor.o((e) => {
$data.end = e.detail.value;
$options.reload();
})
} : {}, {
M: common_vendor.t($options.totalAmount.toFixed(2)),
N: common_vendor.f($data.list, (o, k0, i0) => {
a: common_vendor.n($data.range === "custom" && "active"),
b: common_vendor.o(($event) => $options.switchRange("custom")),
c: common_vendor.n($data.range === "week" && "active"),
d: common_vendor.o(($event) => $options.switchRange("week")),
e: common_vendor.n($data.range === "today" && "active"),
f: common_vendor.o(($event) => $options.switchRange("today")),
g: common_vendor.n($data.range === "month" && "active"),
h: common_vendor.o(($event) => $options.switchRange("month")),
i: common_vendor.n($data.range === "year" && "active"),
j: common_vendor.o(($event) => $options.switchRange("year")),
k: common_vendor.f($data.bizList, (b, k0, i0) => {
return {
a: common_vendor.t(o.orderDate),
b: common_vendor.t(o.customerName),
c: common_vendor.t(o.orderNo),
d: common_vendor.t(Number(o.amount).toFixed(2)),
e: o.id,
f: common_vendor.o(($event) => $options.open(o), o.id)
a: common_vendor.t(b.name),
b: b.key,
c: common_vendor.n($data.biz === b.key && "active"),
d: common_vendor.o(($event) => $options.switchBiz(b.key), b.key)
};
}),
l: $options.placeholder,
m: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
n: $data.query.kw,
o: common_vendor.o(common_vendor.m(($event) => $data.query.kw = $event.detail.value, {
trim: true
})),
p: common_vendor.t($options.periodLabel),
q: common_vendor.o((...args) => $options.reload && $options.reload(...args)),
r: common_vendor.t($options.totalAmount.toFixed(2)),
s: $data.items.length
}, $data.items.length ? {
t: common_vendor.f($data.items, (it, k0, i0) => {
return {
a: common_vendor.t($options.formatDate(it.orderTime || it.txTime || it.createdAt)),
b: common_vendor.t(it.customerName || it.supplierName || it.accountName || it.remark || "-"),
c: common_vendor.t(it.orderNo || it.code || it.id),
d: common_vendor.t((it.amount || 0).toFixed(2)),
e: it.id,
f: common_vendor.o(($event) => $options.openDetail(it), it.id)
};
})
} : {}, {
v: common_vendor.o((...args) => $options.loadMore && $options.loadMore(...args)),
w: common_vendor.o((...args) => $options.onCreate && $options.onCreate(...args))
});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);

View File

@@ -1 +1 @@
<view class="detail"><view class="filter-tabs"><view class="{{['tab', a && 'active']}}" bindtap="{{b}}">自定义</view><view class="{{['tab', c && 'active']}}" bindtap="{{d}}">本周</view><view class="{{['tab', e && 'active']}}" bindtap="{{f}}">今日</view><view class="{{['tab', g && 'active']}}" bindtap="{{h}}">本月</view><view class="{{['tab', i && 'active']}}" bindtap="{{j}}">本年</view></view><view class="biz-tabs"><view class="{{['biz', k && 'active']}}" bindtap="{{l}}">销售</view><view class="{{['biz', m && 'active']}}" bindtap="{{n}}">进货</view><view class="{{['biz', o && 'active']}}" bindtap="{{p}}">收款</view><view class="{{['biz', q && 'active']}}" bindtap="{{r}}">资金</view><view class="{{['biz', s && 'active']}}" bindtap="{{t}}">盘点</view></view><view class="card"><view class="subtabs"><view class="{{['sub', v && 'active']}}" bindtap="{{w}}">出货</view><view class="{{['sub', x && 'active']}}" bindtap="{{y}}">退货</view><view class="{{['sub', z && 'active']}}" bindtap="{{A}}">收款</view><view class="plus" bindtap="{{B}}">+</view></view><view class="search"><input placeholder="单据号/客户/名称/规格/备注" bindconfirm="{{C}}" value="{{D}}" bindinput="{{E}}"/></view><view wx:if="{{F}}" class="daterange"><picker mode="date" value="{{H}}" bindchange="{{I}}"><text>{{G}}</text></picker><text class="sep">—</text><picker mode="date" value="{{K}}" bindchange="{{L}}"><text>{{J}}</text></picker></view><view class="total">合计:¥ {{M}}</view><scroll-view scroll-y class="list"><view wx:for="{{N}}" wx:for-item="o" wx:key="e" class="row" bindtap="{{o.f}}"><view class="left"><view class="date">{{o.a}}</view><view class="name">{{o.b}}</view><view class="no">{{o.c}}</view></view><view class="right">¥ {{o.d}}</view></view></scroll-view></view></view>
<view class="page"><view class="seg"><view class="{{['seg-item', a]}}" bindtap="{{b}}">自定义</view><view class="{{['seg-item', c]}}" bindtap="{{d}}">本周</view><view class="{{['seg-item', e]}}" bindtap="{{f}}">今日</view><view class="{{['seg-item', g]}}" bindtap="{{h}}">本月</view><view class="{{['seg-item', i]}}" bindtap="{{j}}">本年</view></view><view class="content"><view class="biz-tabs"><view wx:for="{{k}}" wx:for-item="b" wx:key="b" class="{{['biz', b.c]}}" bindtap="{{b.d}}">{{b.a}}</view></view><view class="panel"><view class="toolbar"><view class="search"><input class="search-input" placeholder="{{l}}" bindconfirm="{{m}}" value="{{n}}" bindinput="{{o}}"/></view><view class="period">{{p}}</view><button size="mini" bindtap="{{q}}">查询</button></view><view class="total">合计:¥{{r}}</view><scroll-view scroll-y class="list" bindscrolltolower="{{v}}"><block wx:if="{{s}}"><view wx:for="{{t}}" wx:for-item="it" wx:key="e" class="item" bindtap="{{it.f}}"><view class="item-left"><view class="date">{{it.a}}</view><view class="name">{{it.b}}</view><view class="no">{{it.c}}</view></view><view class="amount">¥ {{it.d}}</view><view class="arrow"></view></view></block><view wx:else class="empty">暂无数据</view></scroll-view><view class="fab" bindtap="{{w}}"></view></view></view></view>

View File

@@ -1,43 +1,49 @@
.detail { display:flex;
.page { display:flex; flex-direction: column; height: 100vh;
}
.filter-tabs { display:flex; gap: 24rpx; padding: 18rpx 24rpx; color:#666;
.seg { display:flex; background:#fff;
}
.filter-tabs .tab.active { color:#2aa7b6; font-weight: 700;
.seg-item { flex:1; padding: 22rpx 0; text-align:center; color:#666;
}
.biz-tabs { position: fixed; left:0; top: 160rpx; bottom: 120rpx; width: 120rpx; display:flex; flex-direction: column; gap: 24rpx; padding: 12rpx;
.seg-item.active { color:#18b566; font-weight: 600;
}
.biz { background:#6aa9ff; color:#fff; border-radius: 16rpx; padding: 20rpx 0; text-align:center; opacity: .85;
.content { display:flex; flex:1; min-height: 0;
}
.biz.active { opacity: 1;
.biz-tabs { width: 120rpx; background:#eef6ff; display:flex; flex-direction: column;
}
.card { margin-left: 140rpx; background:#fff; border-radius: 24rpx; padding: 16rpx;
.biz { flex:0 0 120rpx; display:flex; align-items:center; justify-content:center; color:#4aa3d6;
}
.subtabs { display:flex; align-items:center; gap: 24rpx; padding: 8rpx 6rpx 12rpx;
.biz.active { background:#3ac1c9; color:#fff; border-radius: 0 16rpx 16rpx 0;
}
.sub { color:#57c2cf; padding: 8rpx 12rpx;
.panel { flex:1; display:flex; flex-direction: column; background:#fff; margin: 16rpx; border-radius: 16rpx; padding: 12rpx;
}
.sub.active { border-bottom: 4rpx solid #57c2cf; font-weight:700;
.toolbar { display:flex; align-items: center; gap: 12rpx; padding: 8rpx 6rpx;
}
.plus { margin-left:auto; width: 60rpx; height: 60rpx; border-radius: 30rpx; background:#2ec0d0; color:#fff; font-size: 40rpx; display:flex; align-items:center; justify-content:center;
.search { flex:1;
}
.search { background:#f6f7fb; border-radius: 999rpx; padding: 14rpx 20rpx; margin: 8rpx 0 12rpx;
.search-input { width:100%; background:#f6f6f6; border-radius: 12rpx; padding: 12rpx;
}
.daterange { display:flex; align-items:center; gap: 12rpx; color:#888; padding-bottom: 8rpx;
.period { color:#999; font-size: 24rpx; padding: 0 6rpx;
}
.daterange .sep { color:#ccc;
.total { color:#18b566; font-weight: 700; padding: 6rpx 6rpx 12rpx;
}
.total { color:#2ec0d0; font-weight: 800; padding: 12rpx 0; border-top: 2rpx solid #eaeaea;
.list { flex:1;
}
.list { height: calc(100vh - 420rpx);
.item { display:flex; align-items:center; padding: 20rpx 10rpx; border-bottom: 1rpx solid #f1f1f1;
}
.row { display:flex; justify-content: space-between; align-items:center; padding: 22rpx 10rpx; border-bottom: 1rpx solid #f0f0f0;
.item-left { flex:1;
}
.left .date { color:#999; margin-bottom: 6rpx;
.date { color:#999; font-size: 24rpx;
}
.left .name { color:#333; margin-bottom: 6rpx;
.name { color:#333; margin: 4rpx 0; font-weight: 600;
}
.left .no { color:#bbb;
.no { color:#bbb; font-size: 22rpx;
}
.right { color:#555;
.amount { color:#333; font-weight: 700;
}
.arrow { color:#ccc; font-size: 40rpx; margin-left: 8rpx;
}
.empty { height: 50vh; display:flex; align-items:center; justify-content:center; color:#999;
}
.fab { position: fixed; right: 30rpx; bottom: 120rpx; width: 100rpx; height: 100rpx; background:#18b566; color:#fff; border-radius: 50rpx; text-align:center; line-height: 100rpx; font-size: 48rpx; box-shadow: 0 8rpx 20rpx rgba(0,0,0,0.15);
}

View File

@@ -72,6 +72,14 @@ const _sfc_main = {
onCreateOrder() {
common_vendor.index.navigateTo({ url: "/pages/order/create" });
},
goDetail() {
this.activeTab = "detail";
try {
common_vendor.index.__f__("log", "at pages/index/index.vue:166", "[index] goDetail → /pages/detail/index");
} catch (e) {
}
common_vendor.index.navigateTo({ url: "/pages/detail/index" });
},
onNoticeTap(n) {
common_vendor.index.showModal({
title: "广告",
@@ -130,7 +138,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
o: common_vendor.o((...args) => $options.goProduct && $options.goProduct(...args)),
p: common_vendor.o((...args) => $options.onCreateOrder && $options.onCreateOrder(...args)),
q: $data.activeTab === "detail" ? 1 : "",
r: common_vendor.o(($event) => $data.activeTab = "detail"),
r: common_vendor.o((...args) => $options.goDetail && $options.goDetail(...args)),
s: $data.activeTab === "report" ? 1 : "",
t: common_vendor.o(($event) => $data.activeTab = "report"),
v: $data.activeTab === "me" ? 1 : "",

View File

@@ -165,6 +165,7 @@
box-shadow: 0 -6rpx 18rpx rgba(0,0,0,0.08);
-webkit-backdrop-filter: blur(10rpx);
backdrop-filter: blur(10rpx);
z-index: 9999;
}
.tab { flex: 1; text-align: center; color: #8a7535; font-size: 26rpx;
}

View File

@@ -27,7 +27,10 @@ const _sfc_main = {
activeCategory: "sale_income",
trxAmount: 0,
selectedAccountId: null,
selectedAccountName: ""
selectedAccountName: "",
// 收款/付款输入
payments: { cash: 0, bank: 0, wechat: 0 },
showMore: false
};
},
computed: {
@@ -54,6 +57,11 @@ const _sfc_main = {
},
counterpartyLabel() {
return this.customerName || this.supplierName || "—";
},
// 收款/付款合计
payTotal() {
const p = this.payments || { cash: 0, bank: 0, wechat: 0 };
return Number(p.cash || 0) + Number(p.bank || 0) + Number(p.wechat || 0);
}
},
methods: {
@@ -83,10 +91,19 @@ const _sfc_main = {
recalc() {
this.$forceUpdate();
},
recalcPay() {
this.$forceUpdate();
},
async submit() {
const isSaleOrPurchase = this.biz === "sale" || this.biz === "purchase";
const payload = isSaleOrPurchase ? {
type: this.biz === "sale" ? this.saleType : "purchase." + this.purchaseType,
const isCollectOrPay = this.biz === "sale" && this.saleType === "collect" || this.biz === "purchase" && this.purchaseType === "pay";
const saleTypeValue = this.biz === "sale" ? "sale." + this.saleType : "purchase." + this.purchaseType;
const payload = isSaleOrPurchase ? isCollectOrPay ? [
{ method: "cash", amount: Number(this.payments.cash || 0) },
{ method: "bank", amount: Number(this.payments.bank || 0) },
{ method: "wechat", amount: Number(this.payments.wechat || 0) }
].filter((p) => p.amount > 0) : {
type: saleTypeValue,
orderTime: this.order.orderTime,
customerId: this.order.customerId,
supplierId: this.order.supplierId,
@@ -102,7 +119,7 @@ const _sfc_main = {
remark: this.order.remark
};
try {
const url = isSaleOrPurchase ? "/api/orders" : "/api/other-transactions";
const url = isSaleOrPurchase ? isCollectOrPay ? `/api/payments/${this.biz}` : "/api/orders" : "/api/other-transactions";
await common_http.post(url, payload);
common_vendor.index.showToast({ title: "已保存", icon: "success" });
setTimeout(() => {
@@ -116,6 +133,7 @@ const _sfc_main = {
this.items = [];
this.trxAmount = 0;
this.order.remark = "";
this.payments = { cash: 0, bank: 0, wechat: 0 };
}
}
};
@@ -158,13 +176,42 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
F: common_vendor.o((...args) => $options.chooseSupplier && $options.chooseSupplier(...args))
} : {}, {
D: $data.biz === "purchase",
G: $data.biz === "sale" || $data.biz === "purchase"
}, $data.biz === "sale" || $data.biz === "purchase" ? {
H: common_vendor.t($options.totalQuantity),
I: common_vendor.t($options.totalAmount.toFixed(2)),
J: common_vendor.o((...args) => $options.chooseProduct && $options.chooseProduct(...args))
G: $data.biz === "sale" && $data.saleType === "collect" || $data.biz === "purchase" && $data.purchaseType === "pay"
}, $data.biz === "sale" && $data.saleType === "collect" || $data.biz === "purchase" && $data.purchaseType === "pay" ? common_vendor.e({
H: $data.biz === "sale"
}, $data.biz === "sale" ? {
I: common_vendor.t($options.customerLabel),
J: common_vendor.o((...args) => $options.chooseCustomer && $options.chooseCustomer(...args))
} : {
K: common_vendor.f($data.biz === "income" ? $options.incomeCategories : $options.expenseCategories, (c, k0, i0) => {
K: common_vendor.t($options.supplierLabel),
L: common_vendor.o((...args) => $options.chooseSupplier && $options.chooseSupplier(...args))
}, {
M: common_vendor.o([common_vendor.m(($event) => $data.payments.cash = $event.detail.value, {
number: true
}), ($event) => $options.recalcPay()]),
N: $data.payments.cash,
O: common_vendor.o([common_vendor.m(($event) => $data.payments.bank = $event.detail.value, {
number: true
}), ($event) => $options.recalcPay()]),
P: $data.payments.bank,
Q: common_vendor.o([common_vendor.m(($event) => $data.payments.wechat = $event.detail.value, {
number: true
}), ($event) => $options.recalcPay()]),
R: $data.payments.wechat,
S: common_vendor.t($data.showMore ? "收起" : ""),
T: common_vendor.o(($event) => $data.showMore = !$data.showMore),
U: common_vendor.t($options.payTotal.toFixed(2)),
V: $data.order.remark,
W: common_vendor.o(($event) => $data.order.remark = $event.detail.value),
X: common_vendor.t($data.order.orderTime),
Y: $data.order.orderTime,
Z: common_vendor.o((...args) => $options.onDateChange && $options.onDateChange(...args))
}) : $data.biz === "sale" || $data.biz === "purchase" ? {
ab: common_vendor.t($options.totalQuantity),
ac: common_vendor.t($options.totalAmount.toFixed(2)),
ad: common_vendor.o((...args) => $options.chooseProduct && $options.chooseProduct(...args))
} : {
ae: common_vendor.f($data.biz === "income" ? $options.incomeCategories : $options.expenseCategories, (c, k0, i0) => {
return {
a: common_vendor.t(c.label),
b: c.key,
@@ -172,22 +219,23 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
d: common_vendor.o(($event) => $data.activeCategory = c.key, c.key)
};
}),
L: common_vendor.t($options.counterpartyLabel),
M: common_vendor.o((...args) => $options.chooseCounterparty && $options.chooseCounterparty(...args)),
N: common_vendor.t($options.accountLabel),
O: common_vendor.o((...args) => $options.chooseAccount && $options.chooseAccount(...args)),
P: $data.trxAmount,
Q: common_vendor.o(common_vendor.m(($event) => $data.trxAmount = $event.detail.value, {
af: common_vendor.t($options.counterpartyLabel),
ag: common_vendor.o((...args) => $options.chooseCounterparty && $options.chooseCounterparty(...args)),
ah: common_vendor.t($options.accountLabel),
ai: common_vendor.o((...args) => $options.chooseAccount && $options.chooseAccount(...args)),
aj: $data.trxAmount,
ak: common_vendor.o(common_vendor.m(($event) => $data.trxAmount = $event.detail.value, {
number: true
})),
R: $data.order.remark,
S: common_vendor.o(($event) => $data.order.remark = $event.detail.value)
al: $data.order.remark,
am: common_vendor.o(($event) => $data.order.remark = $event.detail.value)
}, {
T: !$data.items.length
aa: $data.biz === "sale" || $data.biz === "purchase",
an: !$data.items.length
}, !$data.items.length ? {
U: common_assets._imports_0$1
ao: common_assets._imports_0$1
} : {
V: common_vendor.f($data.items, (it, idx, i0) => {
ap: common_vendor.f($data.items, (it, idx, i0) => {
return {
a: common_vendor.t(it.productName),
b: common_vendor.o([common_vendor.m(($event) => it.quantity = $event.detail.value, {
@@ -203,8 +251,8 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
};
})
}, {
W: common_vendor.o((...args) => $options.saveAndReset && $options.saveAndReset(...args)),
X: common_vendor.o((...args) => $options.submit && $options.submit(...args))
aq: common_vendor.o((...args) => $options.saveAndReset && $options.saveAndReset(...args)),
ar: common_vendor.o((...args) => $options.submit && $options.submit(...args))
});
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);

View File

@@ -1 +1 @@
<view class="order"><view class="tabs"><text class="{{[a && 'active']}}" bindtap="{{b}}">销售</text><text class="{{[c && 'active']}}" bindtap="{{d}}">进货</text><text class="{{[e && 'active']}}" bindtap="{{f}}">其他收入</text><text class="{{[g && 'active']}}" bindtap="{{h}}">其他支出</text></view><view wx:if="{{i}}" class="subtabs"><button class="{{['subbtn', j && 'active']}}" bindtap="{{k}}">出货</button><button class="{{['subbtn', l && 'active']}}" bindtap="{{m}}">退货</button><button class="{{['subbtn', n && 'active']}}" bindtap="{{o}}">收款</button></view><view wx:elif="{{p}}" class="subtabs"><button class="{{['subbtn', q && 'active']}}" bindtap="{{r}}">进货</button><button class="{{['subbtn', s && 'active']}}" bindtap="{{t}}">退货</button><button class="{{['subbtn', v && 'active']}}" bindtap="{{w}}">付款</button></view><picker mode="date" value="{{y}}" bindchange="{{z}}"><view class="field"><text class="label">时间</text><text class="value">{{x}}</text></view></picker><view wx:if="{{A}}" class="field" bindtap="{{C}}"><text class="label">客户</text><text class="value">{{B}}</text></view><view wx:elif="{{D}}" class="field" bindtap="{{F}}"><text class="label">供应商</text><text class="value">{{E}}</text></view><view wx:if="{{G}}"><view class="summary"><text>选中货品({{H}}</text><text>合计金额:¥ {{I}}</text></view><view class="add" bindtap="{{J}}">+</view></view><view wx:else><view class="chips"><view wx:for="{{K}}" wx:for-item="c" wx:key="b" class="{{['chip', c.c && 'active']}}" bindtap="{{c.d}}">{{c.a}}</view></view><view class="field" bindtap="{{M}}"><text class="label">往来单位</text><text class="value">{{L}}</text></view><view class="field" bindtap="{{O}}"><text class="label">结算账户</text><text class="value">{{N}}</text></view><view class="field"><text class="label">金额</text><input class="value" type="digit" placeholder="0.00" value="{{P}}" bindinput="{{Q}}"/></view><view class="textarea"><block wx:if="{{r0}}"><textarea maxlength="200" placeholder="备注最多输入200个字" value="{{R}}" bindinput="{{S}}"></textarea></block></view></view><view wx:if="{{T}}" class="empty"><image src="{{U}}" mode="widthFix" class="empty-img"></image><text class="empty-text">购物车里空空如也</text><text class="empty-sub">扫描或点击 “+” 选择商品吧</text></view><view wx:else class="list"><view wx:for="{{V}}" wx:for-item="it" wx:key="g" class="row"><view class="col name">{{it.a}}</view><view class="col qty"><input type="number" bindinput="{{it.b}}" value="{{it.c}}"/></view><view class="col price"><input type="number" bindinput="{{it.d}}" value="{{it.e}}"/></view><view class="col amount">¥ {{it.f}}</view></view></view><view class="bottom"><button class="ghost" bindtap="{{W}}">再记一笔</button><button class="primary" bindtap="{{X}}">保存</button></view></view>
<view class="order"><view class="tabs"><text class="{{[a && 'active']}}" bindtap="{{b}}">销售</text><text class="{{[c && 'active']}}" bindtap="{{d}}">进货</text><text class="{{[e && 'active']}}" bindtap="{{f}}">其他收入</text><text class="{{[g && 'active']}}" bindtap="{{h}}">其他支出</text></view><view wx:if="{{i}}" class="subtabs"><button class="{{['subbtn', j && 'active']}}" bindtap="{{k}}">出货</button><button class="{{['subbtn', l && 'active']}}" bindtap="{{m}}">退货</button><button class="{{['subbtn', n && 'active']}}" bindtap="{{o}}">收款</button></view><view wx:elif="{{p}}" class="subtabs"><button class="{{['subbtn', q && 'active']}}" bindtap="{{r}}">进货</button><button class="{{['subbtn', s && 'active']}}" bindtap="{{t}}">退货</button><button class="{{['subbtn', v && 'active']}}" bindtap="{{w}}">付款</button></view><picker mode="date" value="{{y}}" bindchange="{{z}}"><view class="field"><text class="label">时间</text><text class="value">{{x}}</text></view></picker><view wx:if="{{A}}" class="field" bindtap="{{C}}"><text class="label">客户</text><text class="value">{{B}}</text></view><view wx:elif="{{D}}" class="field" bindtap="{{F}}"><text class="label">供应商</text><text class="value">{{E}}</text></view><view wx:if="{{G}}"><view wx:if="{{H}}" class="field" bindtap="{{J}}"><text class="label">客户</text><text class="value">{{I}}</text></view><view wx:else class="field" bindtap="{{L}}"><text class="label">供应商</text><text class="value">{{K}}</text></view><view class="field pay-row"><text class="label">现金</text><input class="pay-input" type="digit" placeholder="0.00" bindinput="{{M}}" value="{{N}}"/></view><view class="field pay-row"><text class="label">银行存款</text><input class="pay-input" type="digit" placeholder="0.00" bindinput="{{O}}" value="{{P}}"/></view><view class="field pay-row"><text class="label">微信</text><input class="pay-input" type="digit" placeholder="0.00" bindinput="{{Q}}" value="{{R}}"/></view><view class="collapse-trigger" bindtap="{{T}}">{{S}}</view><view class="textarea"><view class="amount-badge">总金额:{{U}}</view><block wx:if="{{r0}}"><textarea maxlength="200" placeholder="备注最多输入200个字" value="{{V}}" bindinput="{{W}}"></textarea></block><view class="date-mini"><picker mode="date" value="{{Y}}" bindchange="{{Z}}"><text>{{X}}</text></picker></view></view></view><view wx:elif="{{aa}}"><view class="summary"><text>选中货品({{ab}}</text><text>合计金额:¥ {{ac}}</text></view><view class="add" bindtap="{{ad}}">+</view></view><view wx:else><view class="chips"><view wx:for="{{ae}}" wx:for-item="c" wx:key="b" class="{{['chip', c.c && 'active']}}" bindtap="{{c.d}}">{{c.a}}</view></view><view class="field" bindtap="{{ag}}"><text class="label">往来单位</text><text class="value">{{af}}</text></view><view class="field" bindtap="{{ai}}"><text class="label">结算账户</text><text class="value">{{ah}}</text></view><view class="field"><text class="label">金额</text><input class="value" type="digit" placeholder="0.00" value="{{aj}}" bindinput="{{ak}}"/></view><view class="textarea"><block wx:if="{{r0}}"><textarea maxlength="200" placeholder="备注最多输入200个字" value="{{al}}" bindinput="{{am}}"></textarea></block></view></view><view wx:if="{{an}}" class="empty"><image src="{{ao}}" mode="widthFix" class="empty-img"></image><text class="empty-text">购物车里空空如也</text><text class="empty-sub">扫描或点击 “+” 选择商品吧</text></view><view wx:else class="list"><view wx:for="{{ap}}" wx:for-item="it" wx:key="g" class="row"><view class="col name">{{it.a}}</view><view class="col qty"><input type="number" bindinput="{{it.b}}" value="{{it.c}}"/></view><view class="col price"><input type="number" bindinput="{{it.d}}" value="{{it.e}}"/></view><view class="col amount">¥ {{it.f}}</view></view></view><view class="bottom"><button class="ghost" bindtap="{{aq}}">再记一笔</button><button class="primary" bindtap="{{ar}}">保存</button></view></view>

View File

@@ -40,4 +40,13 @@
.bottom { position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 16rpx 24rpx calc(env(safe-area-inset-bottom) + 16rpx); box-shadow: 0 -4rpx 12rpx rgba(0,0,0,0.06);
}
.primary { width: 100%; background: linear-gradient(135deg, #FFE69A 0%, #F4CF62 45%, #D7A72E 100%); color:#493c1b; border-radius: 999rpx; padding: 20rpx 0; font-weight:800;
}
/* 收款/付款页样式 */
.pay-row .pay-input { text-align: right; color:#333;
}
.textarea { position: relative; padding: 16rpx 24rpx; background:#fff; border-top: 1rpx solid #eee;
}
.amount-badge { position: absolute; right: 24rpx; top: -36rpx; background: #d1f0ff; color:#107e9b; padding: 8rpx 16rpx; border-radius: 12rpx; font-size: 24rpx;
}
.date-mini { position: absolute; right: 24rpx; bottom: 20rpx; color:#666; font-size: 24rpx;
}

View File

@@ -1,251 +0,0 @@
"use strict";
const common_vendor = require("../../common/vendor.js");
const common_http = require("../../common/http.js");
function parseSafeStock(text) {
const m = String(text || "").match(/\s*(\d+(?:\.\d+)?)\s*(?:-|~|—|到|,)?\s*(\d+(?:\.\d+)?)?\s*/);
if (!m)
return { min: null, max: null };
return { min: m[1] ? Number(m[1]) : null, max: m[2] ? Number(m[2]) : null };
}
const _sfc_main = {
data() {
return {
id: null,
units: [],
categories: [],
form: {
name: "",
categoryId: null,
unitId: null,
barcode: "",
brand: "",
model: "",
spec: "",
purchasePrice: 0,
wholesalePrice: 0,
bigClientPrice: 0,
retailPrice: 0,
stock: 0,
safeMin: null,
safeMax: null,
images: []
}
};
},
onLoad(query) {
this.id = query && query.id ? Number(query.id) : null;
this.bootstrap();
},
computed: {
categoryLabel() {
const c = this.categories.find((x) => x.id === this.form.categoryId);
return c ? c.name : "未选择";
},
unitLabel() {
const u = this.units.find((x) => x.id === this.form.unitId);
return u ? u.name : "未选择";
},
safeStockText: {
get() {
const a = this.form.safeMin != null ? String(this.form.safeMin) : "";
const b = this.form.safeMax != null ? String(this.form.safeMax) : "";
if (!a && !b)
return "";
if (a && b)
return a + "-" + b;
return a || b;
},
set(v) {
const { min, max } = parseSafeStock(v);
this.form.safeMin = min;
this.form.safeMax = max;
}
}
},
methods: {
async bootstrap() {
try {
const [units, cats] = await Promise.all([
common_http.get("/api/product/units"),
common_http.get("/api/product/categories")
]);
this.units = Array.isArray(units == null ? void 0 : units.list) ? units.list : Array.isArray(units) ? units : [];
this.categories = Array.isArray(cats == null ? void 0 : cats.list) ? cats.list : Array.isArray(cats) ? cats : [];
} catch (_) {
}
if (this.id) {
try {
const d = await common_http.get("/api/product/detail", { id: this.id });
Object.assign(this.form, {
name: d.name || "",
categoryId: d.categoryId || null,
unitId: d.unitId || null,
barcode: d.barcode || "",
brand: d.brand || "",
model: d.model || "",
spec: d.spec || "",
purchasePrice: Number(d.purchasePrice || 0),
wholesalePrice: Number(d.wholesalePrice || 0),
bigClientPrice: Number(d.bigClientPrice || 0),
retailPrice: Number(d.retailPrice || 0),
stock: Number(d.stock || 0),
safeMin: d.safeMin ?? null,
safeMax: d.safeMax ?? null,
images: Array.isArray(d.images) ? d.images : []
});
} catch (_) {
}
}
},
chooseCategory() {
if (!this.categories.length)
return;
common_vendor.index.showActionSheet({ itemList: this.categories.map((c) => c.name), success: ({ tapIndex }) => {
this.form.categoryId = this.categories[tapIndex].id;
} });
},
chooseUnit() {
if (!this.units.length)
return;
common_vendor.index.showActionSheet({ itemList: this.units.map((u) => u.name), success: ({ tapIndex }) => {
this.form.unitId = this.units[tapIndex].id;
} });
},
scanBarcode() {
common_vendor.index.scanCode({ onlyFromCamera: false, success: (res) => {
this.form.barcode = res.result;
}, fail: () => {
common_vendor.index.showToast({ title: "扫码失败,请手动录入", icon: "none" });
} });
},
async chooseImages() {
common_vendor.index.chooseImage({ count: 6, sizeType: ["compressed"], success: async (res) => {
try {
const uploaded = [];
for (const path of res.tempFilePaths) {
const ret = await common_http.upload("/api/upload", path, { biz: "product" });
uploaded.push(ret.url || ret.path || path);
}
this.form.images = (this.form.images || []).concat(uploaded).slice(0, 9);
} catch (e) {
common_vendor.index.showToast({ title: "上传失败", icon: "none" });
}
} });
},
moveLeft(i) {
if (i <= 0)
return;
const a = this.form.images;
[a[i - 1], a[i]] = [a[i], a[i - 1]];
},
moveRight(i) {
const a = this.form.images;
if (i >= a.length - 1)
return;
[a[i + 1], a[i]] = [a[i], a[i + 1]];
},
removeImg(i) {
this.form.images.splice(i, 1);
},
async submit() {
if (!this.form.name) {
common_vendor.index.showToast({ title: "请填写名称", icon: "none" });
return;
}
const payload = {
name: this.form.name,
categoryId: this.form.categoryId,
unitId: this.form.unitId,
barcode: this.form.barcode,
brand: this.form.brand,
model: this.form.model,
spec: this.form.spec,
purchasePrice: Number(this.form.purchasePrice || 0),
wholesalePrice: Number(this.form.wholesalePrice || 0),
bigClientPrice: Number(this.form.bigClientPrice || 0),
retailPrice: Number(this.form.retailPrice || 0),
stock: Number(this.form.stock || 0),
safeMin: this.form.safeMin,
safeMax: this.form.safeMax,
images: this.form.images
};
try {
if (this.id)
await common_http.put("/api/product", { id: this.id, ...payload });
else
await common_http.post("/api/product", payload);
common_vendor.index.showToast({ title: "已保存", icon: "success" });
setTimeout(() => {
common_vendor.index.navigateBack();
}, 600);
} catch (e) {
common_vendor.index.showToast({ title: e && e.message || "保存失败", icon: "none" });
}
}
}
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return {
a: $data.form.name,
b: common_vendor.o(common_vendor.m(($event) => $data.form.name = $event.detail.value, {
trim: true
})),
c: common_vendor.t($options.categoryLabel),
d: common_vendor.o((...args) => $options.chooseCategory && $options.chooseCategory(...args)),
e: common_vendor.t($options.unitLabel),
f: common_vendor.o((...args) => $options.chooseUnit && $options.chooseUnit(...args)),
g: $data.form.barcode,
h: common_vendor.o(common_vendor.m(($event) => $data.form.barcode = $event.detail.value, {
trim: true
})),
i: common_vendor.o((...args) => $options.scanBarcode && $options.scanBarcode(...args)),
j: $data.form.brand,
k: common_vendor.o(common_vendor.m(($event) => $data.form.brand = $event.detail.value, {
trim: true
})),
l: $data.form.model,
m: common_vendor.o(common_vendor.m(($event) => $data.form.model = $event.detail.value, {
trim: true
})),
n: $data.form.spec,
o: common_vendor.o(common_vendor.m(($event) => $data.form.spec = $event.detail.value, {
trim: true
})),
p: $data.form.purchasePrice,
q: common_vendor.o(common_vendor.m(($event) => $data.form.purchasePrice = $event.detail.value, {
number: true
})),
r: $data.form.wholesalePrice,
s: common_vendor.o(common_vendor.m(($event) => $data.form.wholesalePrice = $event.detail.value, {
number: true
})),
t: $data.form.bigClientPrice,
v: common_vendor.o(common_vendor.m(($event) => $data.form.bigClientPrice = $event.detail.value, {
number: true
})),
w: $data.form.retailPrice,
x: common_vendor.o(common_vendor.m(($event) => $data.form.retailPrice = $event.detail.value, {
number: true
})),
y: $data.form.stock,
z: common_vendor.o(common_vendor.m(($event) => $data.form.stock = $event.detail.value, {
number: true
})),
A: $options.safeStockText,
B: common_vendor.o(($event) => $options.safeStockText = $event.detail.value),
C: common_vendor.o((...args) => $options.chooseImages && $options.chooseImages(...args)),
D: common_vendor.f($data.form.images, (url, idx, i0) => {
return {
a: url,
b: common_vendor.o(($event) => $options.moveLeft(idx), idx),
c: common_vendor.o(($event) => $options.moveRight(idx), idx),
d: common_vendor.o(($event) => $options.removeImg(idx), idx),
e: idx
};
}),
E: common_vendor.o((...args) => $options.submit && $options.submit(...args))
};
}
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
wx.createPage(MiniProgramPage);
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/product/edit.js.map

View File

@@ -1,4 +0,0 @@
{
"navigationBarTitleText": "编辑货品",
"usingComponents": {}
}

View File

@@ -1 +0,0 @@
<view class="page"><view class="form"><view class="field"><text class="label">名称</text><input class="value" placeholder="必填" value="{{a}}" bindinput="{{b}}"/></view><view class="field" bindtap="{{d}}"><text class="label">类别</text><text class="value">{{c}}</text></view><view class="field" bindtap="{{f}}"><text class="label">主单位</text><text class="value">{{e}}</text></view><view class="field"><text class="label">条形码</text><input class="value" placeholder="手动录入或扫码" value="{{g}}" bindinput="{{h}}"/><button size="mini" class="scan" bindtap="{{i}}">扫码</button></view><view class="field"><text class="label">品牌</text><input class="value" placeholder="可选" value="{{j}}" bindinput="{{k}}"/></view><view class="field"><text class="label">型号</text><input class="value" placeholder="可选" value="{{l}}" bindinput="{{m}}"/></view><view class="field"><text class="label">规格</text><input class="value" placeholder="可选" value="{{n}}" bindinput="{{o}}"/></view><view class="grid2"><view class="field"><text class="label">进货价</text><input class="value" type="digit" value="{{p}}" bindinput="{{q}}"/></view><view class="field"><text class="label">批发价</text><input class="value" type="digit" value="{{r}}" bindinput="{{s}}"/></view><view class="field"><text class="label">大单报价</text><input class="value" type="digit" value="{{t}}" bindinput="{{v}}"/></view><view class="field"><text class="label">零售价</text><input class="value" type="digit" value="{{w}}" bindinput="{{x}}"/></view></view><view class="grid2"><view class="field"><text class="label">当前库存</text><input class="value" type="digit" value="{{y}}" bindinput="{{z}}"/></view><view class="field"><text class="label">安全库存</text><input class="value" type="text" placeholder="如 10-100" value="{{A}}" bindinput="{{B}}"/></view></view><view class="photos"><view class="photos-header"><text>商品图片</text><button size="mini" bindtap="{{C}}">选择图片</button></view><view class="photo-list"><view wx:for="{{D}}" wx:for-item="url" wx:key="e" class="photo"><image src="{{url.a}}" mode="aspectFill"/><view class="photo-actions"><text class="btn" bindtap="{{url.b}}">←</text><text class="btn" bindtap="{{url.c}}">→</text><text class="btn danger" bindtap="{{url.d}}">删</text></view></view></view></view></view><view class="bottom"><button class="primary" bindtap="{{E}}">保存</button></view></view>

View File

@@ -1,35 +0,0 @@
.page{ padding-bottom: 140rpx;
}
.form{ background:#fff;
}
.field{ display:flex; align-items:center; gap: 12rpx; padding: 22rpx 20rpx; border-bottom: 1rpx solid #f2f2f2;
}
.label{ color:#666; width: 160rpx;
}
.value{ flex:1; color:#333;
}
.scan{ flex: 0 0 auto;
}
.grid2{ display:grid; grid-template-columns: 1fr 1fr;
}
.photos{ padding: 16rpx 20rpx;
}
.photos-header{ display:flex; justify-content: space-between; align-items:center; margin-bottom: 12rpx;
}
.photo-list{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 12rpx;
}
.photo{ position: relative;
}
.photo image{ width: 100%; height: 200rpx; border-radius: 12rpx; background:#f6f6f6; display:block;
}
.photo-actions{ position:absolute; right:6rpx; bottom:6rpx; display:flex; gap: 6rpx;
}
.btn{ font-size: 22rpx; padding: 4rpx 8rpx; background: rgba(0,0,0,0.45); color:#fff; border-radius: 8rpx;
}
.btn.danger{ background: rgba(221,82,77,0.85);
}
.bottom{ position: fixed; left:0; right:0; bottom:0; background:#fff; padding: 16rpx 24rpx calc(env(safe-area-inset-bottom) + 16rpx); box-shadow: 0 -4rpx 12rpx rgba(0,0,0,0.06);
}
.primary{ width: 100%; background: linear-gradient(135deg, #FFE69A 0%, #F4CF62 45%, #D7A72E 100%); color:#493c1b; border-radius: 999rpx; padding: 20rpx 0; font-weight:800;
}

View File

@@ -16,6 +16,9 @@ const _sfc_main = {
this.fetchCategories();
this.reload();
},
onShow() {
this.reload();
},
computed: {
categoryNames() {
return this.categories.map((c) => c.name);

View File

@@ -35,8 +35,8 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
e: common_vendor.f($data.products, (p, k0, i0) => {
return {
a: common_vendor.t(p.name),
b: common_vendor.t(p.code),
c: common_vendor.t(p.stock || 0),
b: common_vendor.t((p.brand || "") + " " + (p.model || "") + " " + (p.spec || "")),
c: common_vendor.t(p.stock ?? 0),
d: p.id,
e: common_vendor.o(($event) => $options.select(p), p.id)
};